On Fri, Feb 26, 2010 at 02:36:00PM +0100, Ondrej Zajicek wrote:
Hello
Thank you for the patch. I finally dared to rewrite parts of BSD kernel syncing code to make it more featureful and implement proper importing of alien routes. I used slightly different approach (checking RTF_PROTO1 flag instead of PID, because of we want to have a proper cleanup of our routes even when BIRD crashed and is restarted.), so i used just a half of our patch (RTF_UP/RTF_DONE flag handling).
Are you using BIRD with PPP access-server on FreeBSD, as you wrote in the original e-mail? What flags have the routes added by the PPP daemon?
Yes, I'm using BIRD with OSPF in production on 2 PPPoE access-servers and 1 router. It's 1.1.4 with modified patch - I've got lost in bird/kernel interaction and left it in "somehow it works" state. Something's definitely wrong with it, because there are lots of errors like "KIF: error 17 writting cmd 1 route to socket (192.168.67.55/32)" on every rescan of kernel proto. Here is this patch, maybe you can make some use of it. And in release 8 of FreeBSD routing subsystem has been changed a lot, I don't know if it will work on 8... diff -U 3 -r sysdep1/bsd/krt-sock.c sysdep/bsd/krt-sock.c --- sysdep1/bsd/krt-sock.c 2010-03-02 20:42:59.000000000 +0200 +++ sysdep/bsd/krt-sock.c 2009-12-17 12:23:36.000000000 +0200 @@ -10,6 +10,7 @@ #include <ctype.h> #include <fcntl.h> #include <unistd.h> +#include <errno.h> #include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> @@ -198,7 +199,7 @@ msg.rtm.rtm_msglen = l; if ((l = write(rt_sock, (char *)&msg, l)) < 0) { - log(L_ERR "KIF: error writting route to socket (%I/%d)", net->n.prefix, net->n.pxlen); + log(L_ERR "KIF: error %d writting cmd %d route to socket (%I/%d)", errno, cmd, net->n.prefix, net->n.pxlen); } } @@ -208,6 +209,7 @@ if (old) { DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen); + log(L_WARN "krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen); krt_sock_send(RTM_DELETE, old); } if (new) @@ -269,11 +271,19 @@ int src; int flags = msg->rtm.rtm_flags; int addrs = msg->rtm.rtm_addrs; + pid_t sender_pid = msg->rtm.rtm_pid; + pid_t my_pid; int masklen = -1; - if (!(flags & RTF_UP)) + if (msg->rtm.rtm_errno) { - DBG("Down.\n"); + DBG("Error message.\n"); + return; + } + + if ( (!(flags & RTF_UP)) && scan ) + { + DBG("Not up in scan.\n"); return; } @@ -340,8 +350,14 @@ a.iface = ng->iface; else { - log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen); - return; + if (ng) + { + log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d (bad scope)", igate, net->n.prefix, net->n.pxlen); + return; + } else { + log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d (no such neighbor)", igate, net->n.prefix, net->n.pxlen); + return; + } } a.dest = RTD_ROUTER; @@ -374,7 +390,24 @@ return; } - src = KRT_SRC_UNKNOWN; /* FIXME */ + if (scan) + { + log(L_TRACE "Kernel scanned route pid %d", sender_pid); + src = KRT_SRC_UNKNOWN; /* FIXME */ + src = KRT_SRC_ALIEN; + } + else /* !scan - async msg contains pid of sender */ + { + src = KRT_SRC_ALIEN; + my_pid = getpid(); + if (sender_pid == my_pid) + { + src = KRT_SRC_BIRD; + /* filter out to save some allocation/freeing work */ + DBG("Echo of our own route, ignoring\n"); + return; + } + } e = rte_get_temp(&a); e->net = net; @@ -504,10 +537,17 @@ ifa.pxlen = masklen; memcpy(&ifa.brd, &ibrd, sizeof(ip_addr)); - scope = ipa_classify(ifa.ip); - - ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen)); + if (iface->flags & IF_MULTIACCESS) + { + ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen)); + } + else /* PtP iface */ + { + ifa.prefix = ifa.opposite = ifa.brd; + } + scope = ipa_classify(ifa.ip); + if (scope < 0) { log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, iface->name); @@ -581,6 +621,7 @@ { byte *next; int mib[6], on; + int msgs_count = 0; size_t obl, needed; struct ks_msg *m; @@ -612,14 +653,18 @@ if( sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0) { if(on != needed) return; /* The buffer size changed since last sysctl */ - die("RT scan 2"); + log(L_ERR "Sysctl scan error: %d, bufsize=%d", errno, on); +// die("RT scan 2"); +return; } for (next = *buf; next < (*buf + needed); next += m->rtm.rtm_msglen) { m = (struct ks_msg *)next; krt_read_msg(p, m, 1); + msgs_count++; } + log(L_TRACE "Kernel scanned (cmd %d, %d bytes, %d msgs).", cmd, needed, msgs_count); } void diff -U 3 -r sysdep1/cf/bsd.h sysdep/cf/bsd.h --- sysdep1/cf/bsd.h 2010-03-02 20:42:59.000000000 +0200 +++ sysdep/cf/bsd.h 2009-11-11 22:18:41.621053000 +0200 @@ -7,7 +7,7 @@ */ #define CONFIG_AUTO_ROUTES -#undef CONFIG_SELF_CONSCIOUS +#define CONFIG_SELF_CONSCIOUS #undef CONFIG_MULTIPLE_TABLES #undef CONFIG_UNIX_IFACE diff -U 3 -r sysdep1/unix/krt.c sysdep/unix/krt.c --- sysdep1/unix/krt.c 2010-03-02 20:42:59.000000000 +0200 +++ sysdep/unix/krt.c 2009-11-13 17:38:41.000000000 +0200 @@ -688,7 +688,7 @@ switch (src) { case KRT_SRC_BIRD: - ASSERT(0); /* Should be filtered by the back end */ + break; /* filter out echoes of our activity */ case KRT_SRC_REDIRECT: DBG("It's a redirect, kill him! Kill! Kill!\n"); krt_set_notify(p, net, NULL, e); -- Eugene Perevyazko