]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Rewritten kernel syncer. Now uses the rta trickery I've introduced yesterday
authorMartin Mares <mj@ucw.cz>
Tue, 8 Dec 1998 16:20:13 +0000 (16:20 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 8 Dec 1998 16:20:13 +0000 (16:20 +0000)
and does things "the right way". Few things are still missing (device
routes etc.), I'll add them later in the evening.

sysdep/linux/krt-scan.c
sysdep/unix/krt-set.c
sysdep/unix/krt-set.h
sysdep/unix/krt.h

index baa39d858f2597e9405ea4fa4d2a4031d2a4eecc..7dd64159c3854c2b4d39d3f43dcf3b51b7bfa4f9 100644 (file)
@@ -28,54 +28,39 @@ static int krt_scan_fd = -1;
 
 /* FIXME: Filtering */
 
-static void
-krt_magic_route(struct krt_proto *p, net *net, ip_addr gw)
+static int
+krt_uptodate(rte *k, rte *e)
 {
-  neighbor *ng;
-  rta a, *t;
-  rte *e;
+  rta *ka = k->attrs, *ea = e->attrs;
 
-  ng = neigh_find(&p->p, &gw, 0);
-  if (!ng)
-    {
-      log(L_ERR "Kernel told us to use non-neighbor %I for %I/%d\n", gw, net->n.prefix, net->n.pxlen);
-      return;
-    }
-  a.proto = &p->p;
-  a.source = RTS_INHERIT;
-  a.scope = SCOPE_UNIVERSE;
-  a.cast = RTC_UNICAST;
-  a.dest = RTD_ROUTER;
-  a.tos = 0;
-  a.flags = 0;
-  a.gw = gw;
-  a.from = IPA_NONE;
-  a.iface = ng->iface;
-  a.attrs = NULL;
-  t = rta_lookup(&a);
-  e = rte_get_temp(t);
-  e->net = net;
-  rte_update(net, &p->p, 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;
 }
 
 static void
-krt_parse_entry(byte *e, struct krt_proto *p)
+krt_parse_entry(byte *ent, struct krt_proto *p)
 {
   u32 dest0, gw0, mask0;
   ip_addr dest, gw, mask;
-  unsigned int flags;
+  unsigned int flags, verdict;
   int masklen;
   net *net;
-  byte *iface = e;
+  byte *iface = ent;
+  rta a;
+  rte *e, *old;
 
-  if (sscanf(e, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
+  if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
     {
-      log(L_ERR "krt read: unable to parse `%s'", e);
+      log(L_ERR "krt read: unable to parse `%s'", ent);
       return;
     }
-  while (*e != '\t')
-    e++;
-  *e = 0;
+  while (*ent != '\t')
+    ent++;
+  *ent = 0;
 
   dest = ipa_from_u32(dest0);
   ipa_ntoh(dest);
@@ -99,47 +84,69 @@ krt_parse_entry(byte *e, struct krt_proto *p)
       log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw);
       return;
     }
+
   net = net_get(&master_table, 0, dest, masklen);
-  if (net->routes)
+  a.proto = &p->p;
+  a.source = RTS_INHERIT;
+  a.scope = SCOPE_UNIVERSE;
+  a.cast = RTC_UNICAST;
+  a.tos = a.flags = a.aflags = 0;
+  a.from = IPA_NONE;
+  a.iface = NULL;
+  a.attrs = NULL;
+
+  if (flags & RTF_GATEWAY)
     {
-      rte *e = net->routes;
-      rta *a = e->attrs;
-      int ok;
-      switch (a->dest)
-       {
-       case RTD_ROUTER:
-         ok = (flags & RTF_GATEWAY) && ipa_equal(gw, a->gw);
-         break;
-       case RTD_DEVICE:
-#ifdef CONFIG_AUTO_ROUTES
-         ok = 1;
-         /* FIXME: What about static interface routes? */
-#else
-         ok = !(flags & RTF_GATEWAY) && !strcmp(iface, a->iface->name);
-#endif
-         break;
-       case RTD_UNREACHABLE:
-         ok = flags & RTF_REJECT;
-         break;
-       default:
-         ok = 0;
-       }
-      net->n.flags |= ok ? KRF_SEEN : KRF_UPDATE;
+      neighbor *ng = neigh_find(&p->p, &gw, 0);
+      if (ng)
+       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);
+      a.dest = RTD_ROUTER;
+      a.gw = gw;
+    }
+  else if (flags & RTF_REJECT)
+    {
+      a.dest = RTD_UNREACHABLE;
+      a.gw = IPA_NONE;
     }
   else
     {
-#ifdef CONFIG_AUTO_ROUTES
-      if (!(flags & RTF_GATEWAY))      /* It's a device route */
-       return;
-#endif
-      DBG("krt_parse_entry: kernel reporting unknown route %I/%d\n", dest, masklen);
-      if (p->scanopt.learn)
-       {
-         if (flags & RTF_GATEWAY)
-           krt_magic_route(p, net, gw);
-       }
-      net->n.flags |= KRF_UPDATE;
+      /* FIXME: Should support interface routes? */
+      /* FIXME: What about systems not generating their own if routes? (see CONFIG_AUTO_ROUTES) */
+      return;
+    }
+
+  e = rte_get_temp(&a);
+  e->net = net;
+  old = net->routes;
+  if (old && !krt_capable(old))
+    old = NULL;
+  if (old)
+    {
+      if (krt_uptodate(e, net->routes))
+       verdict = KRF_SEEN;
+      else
+       verdict = KRF_UPDATE;
+    }
+  else if (p->scanopt.learn && !net->routes)
+    verdict = KRF_LEARN;
+  else
+    verdict = KRF_DELETE;
+
+  DBG("krt_parse_entry: verdict %d\n", 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);
+      e->next = net->routes;
+      net->routes = e;
     }
+  else
+    rte_free(e);
 }
 
 static int
@@ -187,7 +194,7 @@ krt_scan_proc(struct krt_proto *p)
 }
 
 static void
-krt_prune(void)
+krt_prune(struct krt_proto *p)
 {
   struct rtable *t = &master_table;
   struct fib_node *f;
@@ -200,24 +207,57 @@ krt_prune(void)
   FIB_WALK(&t->fib, f)
     {
       net *n = (net *) f;
-      switch (f->flags)
+      int verdict = f->flags;
+      rte *new, *old;
+
+      if (verdict != KRF_CREATE && verdict != KRF_SEEN)
        {
-       case KRF_UPDATE:
-         DBG("krt_prune: removing %I/%d\n", n->n.prefix, n->n.pxlen);
-         krt_remove_route(n, NULL);
-         /* Fall-thru */
-       case 0:
-         if (n->routes)
+         old = n->routes;
+         n->routes = old->next;
+       }
+      else
+       old = NULL;
+      new = n->routes;
+
+      switch (verdict)
+       {
+       case KRF_CREATE:
+         if (new)
            {
-             DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen);
-             krt_add_route(n, n->routes);
+             if (new->attrs->source == RTS_INHERIT)
+               {
+                 DBG("krt_prune: removing inherited %I/%d\n", n->n.prefix, n->n.pxlen);
+                 rte_update(n, &p->p, NULL);
+               }
+             else
+               {
+                 DBG("krt_prune: reinstalling %I/%d\n", n->n.prefix, n->n.pxlen);
+                 krt_add_route(new);
+               }
            }
          break;
        case KRF_SEEN:
+         /* Nothing happens */
+         break;
+       case KRF_UPDATE:
+         DBG("krt_prune: updating %I/%d\n", n->n.prefix, n->n.pxlen);
+         krt_remove_route(old);
+         krt_add_route(new);
+         break;
+       case KRF_DELETE:
+         DBG("krt_prune: deleting %I/%d\n", n->n.prefix, n->n.pxlen);
+         krt_remove_route(old);
+         break;
+       case KRF_LEARN:
+         DBG("krt_prune: learning %I/%d\n", n->n.prefix, n->n.pxlen);
+         rte_update(n, &p->p, new);
          break;
        default:
          die("krt_prune: invalid route status");
        }
+
+      if (old)
+       rte_free(old);
       f->flags = 0;
     }
   FIB_WALK_END;
@@ -229,7 +269,7 @@ krt_scan_fire(timer *t)
   struct krt_proto *p = t->data;
 
   if (krt_scan_proc(p))
-    krt_prune();
+    krt_prune(p);
 }
 
 void
index 2c355eeee6c03f0095f19d3b15d257b15619dcdf..8bc2df1190210e370cc94e4cc4ed700525e37b75 100644 (file)
@@ -22,7 +22,7 @@
 #include "lib/krt.h"
 
 int
-krt_capable(net *net, rte *e)
+krt_capable(rte *e)
 {
   rta *a = e->attrs;
 
@@ -40,11 +40,12 @@ krt_capable(net *net, rte *e)
 }
 
 void
-krt_remove_route(net *net, rte *old)
+krt_remove_route(rte *old)
 {
+  net *net = old->net;
   struct rtentry re;
 
-  if (old && !krt_capable(net, old))
+  if (!krt_capable(old) || old->attrs->source == RTS_INHERIT)
     {
       DBG("krt_remove_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
       return;
@@ -58,12 +59,13 @@ krt_remove_route(net *net, rte *old)
 }
 
 void
-krt_add_route(net *net, rte *new)
+krt_add_route(rte *new)
 {
+  net *net = new->net;
   struct rtentry re;
   rta *a = new->attrs;
 
-  if (!krt_capable(net, new))
+  if (!krt_capable(new) || new->attrs->source == RTS_INHERIT)
     {
       DBG("krt_add_route(ignored %I/%d)\n", net->n.prefix, net->n.pxlen);
       return;
@@ -105,9 +107,9 @@ krt_set_notify(struct proto *x, net *net, rte *new, rte *old)
   if (x->state != PRS_UP)
     return;
   if (old)
-    krt_remove_route(net, old);
+    krt_remove_route(old);
   if (new)
-    krt_add_route(net, new);
+    krt_add_route(new);
 }
 
 void
@@ -117,3 +119,4 @@ krt_set_preconfig(struct krt_proto *x)
     die("krt set: missing socket");
   x->p.rt_notify = krt_set_notify;
 }
+
index a2107e12737308f33c17434470e01973a3e69a13..214d91ac3cae348faedb72adc20d056299319bfe 100644 (file)
@@ -12,8 +12,8 @@
 struct krt_set_params {
 };
 
-void krt_remove_route(net *net, rte *old);
-void krt_add_route(net *net, rte *new);
-int krt_capable(net *net, rte *e);
+void krt_remove_route(rte *old);
+void krt_add_route(rte *new);
+int krt_capable(rte *e);
 
 #endif
index 24122e941756336ebeb51dd4b37bdc695b52531d..aae5bd574617b3368cc26b575bc3bd8be5785073 100644 (file)
 
 /* Flags stored in net->n.flags */
 
+#define KRF_CREATE 0                   /* Not seen in kernel table */
 #define KRF_SEEN 1                     /* Seen in kernel table during last scan */
 #define KRF_UPDATE 2                   /* Need to update this entry */
+#define KRF_DELETE 3                   /* Should be deleted */
+#define KRF_LEARN 4                    /* We should learn this route */
 
 /* sync-rt.c */