]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Hopefully finished kernel syncer (krt) rewrite:
authorMartin Mares <mj@ucw.cz>
Tue, 8 Dec 1998 18:37:58 +0000 (18:37 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 8 Dec 1998 18:37:58 +0000 (18:37 +0000)
  o  Interface syncing is now a part of krt and it can have configurable
     parameters. Actually, the only one is scan rate now :)
  o  Kernel routing table syncing is now synchronized with interface
     syncing (we need the most recent version of the interface list
     to prevent lots of routes to non-existent destinations from
     appearing). Instead of its own timer, we just check if it's
     route scan time after each iface list scan.
  o  Syncing of device routes implemented.
  o  CONFIG_AUTO_ROUTES should control syncing of automatic device routes.
  o  Rewrote krt_remove_route() to really remove routes :)
  o  Better diagnostics.
  o  Fixed a couple of bugs.

12 files changed:
TODO
bird.conf
sysdep/linux/krt-scan.Y
sysdep/linux/krt-scan.c
sysdep/linux/krt-scan.h
sysdep/unix/Modules
sysdep/unix/krt-iface.Y [new file with mode: 0644]
sysdep/unix/krt-iface.h [new file with mode: 0644]
sysdep/unix/krt-set.c
sysdep/unix/krt.h
sysdep/unix/sync-if.c
sysdep/unix/sync-rt.c

diff --git a/TODO b/TODO
index 6298a53f11c509df89d4d622af917ad0f0fb0c57..476506fda521a9a3ebcf88e756ea85d8d43da50b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -16,9 +16,11 @@ Core
 - default preferences of protocols: prefer BGP over OSPF/RIP external routes?
 - secondary addresses -> subinterfaces
 - check if all protocols set proper packet priorities and TTL's.
+
 - better default protocol names
 - config: comments at end of line -> explicit ';' needed?
 - remove post-config hooks?
+- command-line arguments: name of config file
 
 - static: check validity of route destination?
 - static: device routes
index 1d1c39af5e7dde434ab2c627655483884b8a3cee..6411a566da38f374479942ecf5337430b28e48b5 100644 (file)
--- a/bird.conf
+++ b/bird.conf
@@ -20,13 +20,18 @@ protocol device {
 
 protocol kernel {
 #      disabled
-       learn;                  # Learn all routes from the kernel
+#      learn;                  # Learn all routes from the kernel
        scan time 10;           # Scan kernel tables every 10 seconds
+#      route scan time 20;     # But routes only every 20 seconds
 }
 
 protocol static {
 #      disabled
+       route 0.0.0.0/0 via 62.168.0.13
+       route 62.168.0.0/25 reject
 #      route 10.0.0.0/8 reject
-#      route 10.1.0.0:255.255.255.0 via 62.168.0.3
+#      route 10.1.1.0:255.255.255.0 via 62.168.0.3
+#      route 10.1.2.0:255.255.255.0 via 62.168.0.3
+#      route 10.1.3.0:255.255.255.0 via 62.168.0.4
 #      route 10.2.0.0/24 via "arc0"
 }
index fcdcfe66e57aae4a3195dce0bb7f799bfddf48ec..d02df113307d03ace59a256e4dcc2396aa4f1721 100644 (file)
@@ -12,7 +12,7 @@ CF_HDR
 
 CF_DECLS
 
-CF_KEYWORDS(LEARN, SCAN, TIME)
+CF_KEYWORDS(LEARN, ROUTE, SCAN, TIME)
 
 CF_GRAMMAR
 
@@ -22,9 +22,9 @@ krt_scan_item:
    LEARN bool {
       ((struct krt_proto *) this_proto)->scanopt.learn = $2;
    }
- | SCAN TIME expr {
+ | ROUTE SCAN TIME expr {
       /* Scan time of 0 means scan on startup only */
-      ((struct krt_proto *) this_proto)->scanopt.recurrence = $3;
+      ((struct krt_proto *) this_proto)->scanopt.scan_time = $4;
    }
  ;
 
index 7dd64159c3854c2b4d39d3f43dcf3b51b7bfa4f9..9801f8a36dd49ecdf4a1cb6a9870f434bdb7b900 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <net/route.h>
@@ -28,6 +29,22 @@ static int krt_scan_fd = -1;
 
 /* FIXME: Filtering */
 
+struct iface *
+krt_temp_iface(struct krt_proto *x, char *name)
+{
+  SCANOPT;
+  struct iface *i;
+
+  WALK_LIST(i, p->temp_ifs)
+    if (!strcmp(i->name, name))
+      return i;
+  i = mb_alloc(x->p.pool, sizeof(struct iface));
+  bzero(i, sizeof(*i));
+  strcpy(i->name, name);
+  add_tail(&p->temp_ifs, &i->n);
+  return i;
+}
+
 static int
 krt_uptodate(rte *k, rte *e)
 {
@@ -35,10 +52,15 @@ krt_uptodate(rte *k, rte *e)
 
   if (ka->dest != ea->dest)
     return 0;
-  if (ka->dest == RTD_ROUTER && !ipa_equal(ka->gw, ea->gw))
-    return 0;
-  /* FIXME: Device routes */
-  return 1;
+  switch (ka->dest)
+    {
+    case RTD_ROUTER:
+      return ipa_equal(ka->gw, ea->gw);
+    case RTD_DEVICE:
+      return !strcmp(ka->iface->name, ea->iface->name);
+    default:
+      return 1;
+    }
 }
 
 static void
@@ -76,7 +98,10 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
   DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags);
 
   if (!(flags & RTF_UP))
-    return;
+    {
+      DBG("Down.\n");
+      return;
+    }
   if (flags & RTF_HOST)
     masklen = 32;
   if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */
@@ -86,6 +111,13 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
     }
 
   net = net_get(&master_table, 0, dest, masklen);
+  if (net->n.flags)
+    {
+      /* Route to this destination was already seen. Strange, but it happens... */
+      DBG("Already seen.\n");
+      return;
+    }
+
   a.proto = &p->p;
   a.source = RTS_INHERIT;
   a.scope = SCOPE_UNIVERSE;
@@ -102,7 +134,7 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
        a.iface = ng->iface;
       else
        /* FIXME: Remove this warning? */
-       log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d\n", gw, net->n.prefix, net->n.pxlen);
+       log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
       a.dest = RTD_ROUTER;
       a.gw = gw;
     }
@@ -111,10 +143,15 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
       a.dest = RTD_UNREACHABLE;
       a.gw = IPA_NONE;
     }
+  else if (isalpha(iface[0]))
+    {
+      a.dest = RTD_DEVICE;
+      a.gw = IPA_NONE;
+      a.iface = krt_temp_iface(p, iface);
+    }
   else
     {
-      /* FIXME: Should support interface routes? */
-      /* FIXME: What about systems not generating their own if routes? (see CONFIG_AUTO_ROUTES) */
+      log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
       return;
     }
 
@@ -135,13 +172,14 @@ krt_parse_entry(byte *ent, struct krt_proto *p)
   else
     verdict = KRF_DELETE;
 
-  DBG("krt_parse_entry: verdict %d\n", verdict);
+  DBG("krt_parse_entry: verdict=%s\n", ((char *[]) { "CREATE", "SEEN", "UPDATE", "DELETE", "LEARN" }) [verdict]);
 
   net->n.flags = verdict;
   if (verdict != KRF_SEEN)
     {
       /* Get a cached copy of attributes and link the route */
-      e->attrs = rta_lookup(e->attrs);
+      a.source = RTS_DUMMY;
+      e->attrs = rta_lookup(&a);
       e->next = net->routes;
       net->routes = e;
     }
@@ -155,7 +193,7 @@ krt_scan_proc(struct krt_proto *p)
   byte buf[32768];
   int l, seen_hdr;
 
-  DBG("Scanning kernel table...\n");
+  DBG("Scanning kernel routing table...\n");
   if (krt_scan_fd < 0)
     {
       krt_scan_fd = open("/proc/net/route", O_RDONLY);
@@ -263,13 +301,18 @@ krt_prune(struct krt_proto *p)
   FIB_WALK_END;
 }
 
-static void
-krt_scan_fire(timer *t)
+void
+krt_scan_ifaces_done(struct krt_proto *x)
 {
-  struct krt_proto *p = t->data;
+  SCANOPT;
 
-  if (krt_scan_proc(p))
-    krt_prune(p);
+  p->accum_time += x->ifopt.scan_time;
+  if (p->scan_time && p->accum_time >= p->scan_time)
+    {
+      p->accum_time %= p->scan_time;
+      if (krt_scan_proc(x))
+       krt_prune(x);
+    }
 }
 
 void
@@ -277,30 +320,21 @@ krt_scan_preconfig(struct krt_proto *x)
 {
   SCANOPT;
 
-  p->recurrence = 60;
+  p->scan_time = 1;
   p->learn = 0;
+  init_list(&p->temp_ifs);
 }
 
 void
 krt_scan_start(struct krt_proto *x)
 {
   SCANOPT;
-  timer *t = tm_new(x->p.pool);
-
-  p->timer = t;
-  t->hook = krt_scan_fire;
-  t->data = x;
-  t->recurrent = p->recurrence;
-  krt_scan_fire(t);
-  if (t->recurrent)
-    tm_start(t, t->recurrent);
+
+  /* Force krt scan after first interface scan */
+  p->accum_time = p->scan_time - x->ifopt.scan_time;
 }
 
 void
 krt_scan_shutdown(struct krt_proto *x)
 {
-  SCANOPT;
-
-  tm_stop(p->timer);
-  /* FIXME: Remove all krt's? */
 }
index 18073e2b91e04353ee252eb127eafb54bbd92e84..fe41d46cfe0a453244ad1f980fde10ba77f1bbc2 100644 (file)
 #define _BIRD_KRT_SCAN_H_
 
 struct krt_scan_params {
-  int recurrence;                      /* How often should we scan krt, 0=only on startup */
   int learn;                           /* Should we learn routes from the kernel? */
-  struct timer *timer;
+  list temp_ifs;                       /* Temporary interfaces */
+  int scan_time;                       /* How often should we scan krt, 0=only on startup */
+  int accum_time;                      /* Accumulated scanning time */
 };
 
 #endif
index 441c3f0742f67ff371f0fc6f60c47de11799d8ad..f6db6d35bc53848357c476b44559d4b1fbc1adc7 100644 (file)
@@ -9,3 +9,5 @@ krt.Y
 krt.h
 krt-set.c
 krt-set.h
+krt-iface.h
+krt-iface.Y
diff --git a/sysdep/unix/krt-iface.Y b/sysdep/unix/krt-iface.Y
new file mode 100644 (file)
index 0000000..becb70c
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *     BIRD -- UNIX Interface Syncer Configuration
+ *
+ *     (c) 1998 Martin Mares <mj@ucw.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+CF_HDR
+
+#include "lib/krt-scan.h"
+
+CF_DECLS
+
+CF_KEYWORDS(LEARN, ROUTE, SCAN, TIME)
+
+CF_GRAMMAR
+
+CF_ADDTO(kern_proto, kern_proto krt_if_item ';')
+
+krt_if_item:
+   SCAN TIME expr {
+      /* Scan time of 0 means scan on startup only */
+      ((struct krt_proto *) this_proto)->ifopt.scan_time = $3;
+   }
+ ;
+
+CF_CODE
+
+CF_END
diff --git a/sysdep/unix/krt-iface.h b/sysdep/unix/krt-iface.h
new file mode 100644 (file)
index 0000000..95cfff8
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *     BIRD -- Unix Kernel Interface Syncer -- Setting Parameters
+ *
+ *     (c) 1998 Martin Mares <mj@ucw.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_KRT_IFACE_H_
+#define _BIRD_KRT_IFACE_H_
+
+struct krt_if_params {
+  int scan_time;
+};
+
+#endif
index 8bc2df1190210e370cc94e4cc4ed700525e37b75..33d5bca0a8e90c97aee0dc1b8fe2c4152111f113 100644 (file)
@@ -29,9 +29,7 @@ krt_capable(rte *e)
   return
     a->cast == RTC_UNICAST &&
     (a->dest == RTD_ROUTER
-#ifndef CONFIG_AUTO_ROUTES
      || a->dest == RTD_DEVICE
-#endif
 #ifdef RTF_REJECT
      || a->dest == RTD_UNREACHABLE
 #endif
@@ -39,38 +37,25 @@ krt_capable(rte *e)
     !a->tos;
 }
 
-void
-krt_remove_route(rte *old)
+static inline int
+krt_capable_op(rte *e)
 {
-  net *net = old->net;
-  struct rtentry re;
+  rta *a = e->attrs;
 
-  if (!krt_capable(old) || old->attrs->source == RTS_INHERIT)
-    {
-      DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
-      return;
-    }
-  DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
-  bzero(&re, sizeof(re));
-  fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
-  fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
-  if (ioctl(if_scan_sock, SIOCDELRT, &re) < 0)
-    log(L_ERR "SIOCDELRT(%I/%d): %m", net->n.prefix, net->n.pxlen);
+#ifdef CONFIG_AUTO_ROUTES
+  if (a->dest == RTD_ROUTER && a->source == RTS_DEVICE)
+    return 0;
+#endif
+  return krt_capable(e);
 }
 
-void
-krt_add_route(rte *new)
+static void
+krt_ioctl(int ioc, rte *e, char *name)
 {
-  net *net = new->net;
+  net *net = e->net;
   struct rtentry re;
-  rta *a = new->attrs;
+  rta *a = e->attrs;
 
-  if (!krt_capable(new) || new->attrs->source == RTS_INHERIT)
-    {
-      DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
-      return;
-    }
-  DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
   bzero(&re, sizeof(re));
   fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
   fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
@@ -83,11 +68,9 @@ krt_add_route(rte *new)
       fill_in_sockaddr((struct sockaddr_in *) &re.rt_gateway, a->gw, 0);
       re.rt_flags |= RTF_GATEWAY;
       break;
-#ifndef CONFIG_AUTO_ROUTES
     case RTD_DEVICE:
       re.rt_dev = a->iface->name;
       break;
-#endif
 #ifdef RTF_REJECT
     case RTD_UNREACHABLE:
       re.rt_flags |= RTF_REJECT;
@@ -97,8 +80,36 @@ krt_add_route(rte *new)
       die("krt set: unknown flags, but not filtered");
     }
 
-  if (ioctl(if_scan_sock, SIOCADDRT, &re) < 0)
-    log(L_ERR "SIOCADDRT(%I/%d): %m", net->n.prefix, net->n.pxlen);
+  if (ioctl(if_scan_sock, ioc, &re) < 0)
+    log(L_ERR "%s(%I/%d): %m", name, net->n.prefix, net->n.pxlen);
+}
+
+void
+krt_remove_route(rte *old)
+{
+  net *net = old->net;
+
+  if (!krt_capable_op(old))
+    {
+      DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
+      return;
+    }
+  DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
+  krt_ioctl(SIOCDELRT, old, "SIOCDELRT");
+}
+
+void
+krt_add_route(rte *new)
+{
+  net *net = new->net;
+
+  if (!krt_capable_op(new))
+    {
+      DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
+      return;
+    }
+  DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
+  krt_ioctl(SIOCADDRT, new, "SIOCADDRT");
 }
 
 void
@@ -119,4 +130,3 @@ krt_set_preconfig(struct krt_proto *x)
     die("krt set: missing socket");
   x->p.rt_notify = krt_set_notify;
 }
-
index aae5bd574617b3368cc26b575bc3bd8be5785073..4ea88d50b4cf09f5d1d616a3bc7d125344155bce 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "lib/krt-scan.h"
 #include "lib/krt-set.h"
+#include "lib/krt-iface.h"
 
 /* Flags stored in net->n.flags */
 
@@ -28,6 +29,7 @@ struct krt_proto {
   struct proto p;
   struct krt_set_params setopt;
   struct krt_scan_params scanopt;
+  struct krt_if_params ifopt;
 };
 
 extern struct proto *cf_krt_proto;
@@ -37,9 +39,16 @@ extern struct proto *cf_krt_proto;
 void krt_scan_preconfig(struct krt_proto *);
 void krt_scan_start(struct krt_proto *);
 void krt_scan_shutdown(struct krt_proto *);
+void krt_scan_ifaces_done(struct krt_proto *);
 
 /* krt-set.c */
 
 void krt_set_preconfig(struct krt_proto *);
 
+/* sync-if.c */
+
+void krt_if_preconfig(struct krt_proto *);
+void krt_if_start(struct krt_proto *);
+void krt_if_shutdown(struct krt_proto *);
+
 #endif
index 76426e73c9570d5ead4a17a0a2c6a418a53c0bc0..70a2c0ce46f24616eed3bd3c6f2cd6225affab46 100644 (file)
 
 #include "nest/bird.h"
 #include "nest/iface.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
 #include "lib/timer.h"
+#include "lib/krt.h"
 
 #include "unix.h"
 
 int if_scan_sock;
-int if_scan_period = 60;
 
 static timer *if_scan_timer;
 
@@ -131,8 +133,9 @@ scan_if(timer *t)
   struct ifconf ic;
   static int last_ifbuf_size = 4*sizeof(struct ifreq);
   int res;
+  struct krt_proto *p = t->data;
 
-  DBG("Scanning interfaces...\n");
+  DBG("It's interface scan time...\n");
   for(;;)
     {
       if (last_ifbuf_size)
@@ -165,6 +168,32 @@ scan_if(timer *t)
       DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
 #endif
     }
+  krt_scan_ifaces_done(p);
+}
+
+void
+krt_if_start(struct krt_proto *p)
+{
+  if_scan_timer = tm_new(&root_pool);
+  if_scan_timer->hook = scan_if;
+  if_scan_timer->data = p;
+  if_scan_timer->recurrent = p->ifopt.scan_time;
+  scan_if(if_scan_timer);
+  tm_start(if_scan_timer, p->ifopt.scan_time);
+}
+
+void
+krt_if_preconfig(struct krt_proto *p)
+{
+  p->ifopt.scan_time = 60;
+}
+
+void
+krt_if_shutdown(struct krt_proto *p)
+{
+  tm_stop(if_scan_timer);
+  rfree(if_scan_timer);
+  /* FIXME: What should we do with interfaces? */
 }
 
 void
@@ -174,9 +203,4 @@ scan_if_init(void)
   DBG("Using socket %d for interface and route scanning\n", if_scan_sock);
   if (if_scan_sock < 0)
     die("Cannot create scanning socket: %m");
-  scan_if(NULL);
-  if_scan_timer = tm_new(&root_pool);
-  if_scan_timer->hook = scan_if;
-  if_scan_timer->recurrent = if_scan_period;
-  tm_start(if_scan_timer, if_scan_period);
 }
index 169494e2163b5c1693440d36719bc989fbbb8a6a..dc79118dd2d614d3cf1b3fa6d33bb46a5b8a5bd9 100644 (file)
@@ -30,6 +30,7 @@ krt_start(struct proto *P)
 {
   struct krt_proto *p = (struct krt_proto *) P;
   krt_scan_start(p);
+  krt_if_start(p);
 }
 
 void
@@ -37,6 +38,7 @@ krt_shutdown(struct proto *P, int time)
 {
   struct krt_proto *p = (struct krt_proto *) P;
   krt_scan_shutdown(p);
+  krt_if_shutdown(p);
 }
 
 void
@@ -50,6 +52,7 @@ krt_preconfig(struct protocol *x)
   p->p.shutdown = krt_shutdown;
   krt_scan_preconfig(p);
   krt_set_preconfig(p);
+  krt_if_preconfig(p);
 }
 
 struct protocol proto_unix_kernel = {