]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Asynchronous feeding of protocols.
authorMartin Mares <mj@ucw.cz>
Fri, 19 May 2000 10:46:26 +0000 (10:46 +0000)
committerMartin Mares <mj@ucw.cz>
Fri, 19 May 2000 10:46:26 +0000 (10:46 +0000)
TODO
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-table.c

diff --git a/TODO b/TODO
index f2380b349f44d551fcc193b771fe68905770ff61..ed32e6b0e3be09f52598feaae8eefeeb71ac06e2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,10 +5,8 @@ Core
 - client: data losses on large dumps?
 
 - table: ocassional core dumps in rt_prune()
-- table: do feeding by parts
 
-- bgp: timing of updates?
-- bgp: dump and get_route_info
+- bgp: get_route_info
 
 Documentation
 ~~~~~~~~~~~~~
@@ -33,6 +31,7 @@ Globals
 Various ideas
 ~~~~~~~~~~~~~
 - static: allow specifying a per-route filter program for setting route attributes?
+- bgp: timing of updates?
 - netlink: realms
 - netlink: import Linux route attributes to our rta's, so that they can be filtered?
 - config: executable config files
index e81aadc9979cd46e30d920abada8b945850b9f15..76467aa56acb4c9c2643b353ce8bdda3925aa15e 100644 (file)
@@ -409,6 +409,25 @@ proto_fell_down(struct proto *p)
   proto_rethink_goal(p);
 }
 
+static void
+proto_feed_more(void *P)
+{
+  struct proto *p = P;
+
+  DBG("Feeding protocol %s continued\n", p->name);
+  if (rt_feed_baby(p))
+    {
+      p->core_state = FS_HAPPY;
+      proto_relink(p);
+      DBG("Protocol %s up and running\n", p->name);
+    }
+  else
+    {
+      p->attn->hook = proto_feed_more;
+      ev_schedule(p->attn);            /* Will continue later... */
+    }
+}
+
 static void
 proto_feed(void *P)
 {
@@ -417,10 +436,7 @@ proto_feed(void *P)
   DBG("Feeding protocol %s\n", p->name);
   proto_add_announce_hook(p, p->table);
   if_feed_baby(p);
-  rt_feed_baby(p);
-  p->core_state = FS_HAPPY;
-  proto_relink(p);
-  DBG("Protocol %s up and running\n", p->name);
+  proto_feed_more(P);
 }
 
 void
@@ -444,8 +460,12 @@ proto_notify_state(struct proto *p, unsigned ps)
        }
       else if (cs == FS_FLUSHING)      /* Still flushing... */
        ;
-      else                             /* Need to start flushing */
-       goto schedule_flush;
+      else
+       {
+         if (cs == FS_FEEDING)         /* Need to abort feeding */
+           rt_feed_baby_abort(p);
+         goto schedule_flush;          /* Need to start flushing */
+       }
       break;
     case PS_START:
       ASSERT(ops == PS_DOWN);
index df9064b36f5161b47b441dfa2f486f576293b943..64ea4661dbf07db1fa6946785c65441481eec5c0 100644 (file)
@@ -151,6 +151,9 @@ struct proto {
   struct filter *out_filter;           /* Output filter */
   struct announce_hook *ahooks;                /* Announcement hooks for this protocol */
 
+  struct fib_iterator *feed_iterator;  /* Routing table iterator used during protocol feeding */
+  struct announce_hook *feed_ahook;    /* Announce hook we currently feed */
+
   /* Hic sunt protocol-specific data */
 };
 
index 20709e94a08042c2cc6ac6fff299fdac9f897024..183e80b5e4b297479b31ee267bf2e3561d82778b 100644 (file)
@@ -197,7 +197,8 @@ rte *rte_do_cow(rte *);
 static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
 void rt_dump(rtable *);
 void rt_dump_all(void);
-void rt_feed_baby(struct proto *p);
+int rt_feed_baby(struct proto *p);
+void rt_feed_baby_abort(struct proto *p);
 void rt_prune(rtable *tab);
 void rt_prune_all(void);
 struct rtable_config *rt_new_table(struct symbol *s);
index 7133ed49581a1300cc83c243b22e0ed46b329a07..d81dd857de16517354bb02960fe4979ad3028970 100644 (file)
@@ -200,35 +200,6 @@ rte_announce(rtable *tab, net *net, rte *new, rte *old, ea_list *tmpa)
     }
 }
 
-void
-rt_feed_baby(struct proto *p)
-{
-  struct announce_hook *h;
-
-  if (!p->ahooks)
-    return;
-  DBG("Announcing routes to new protocol %s\n", p->name);
-  for(h=p->ahooks; h; h=h->next)
-    {
-      rtable *t = h->table;
-      FIB_WALK(&t->fib, fn)
-       {
-         net *n = (net *) fn;
-         rte *e;
-         for(e=n->routes; e; e=e->next)
-           {
-             struct proto *q = e->attrs->proto;
-             ea_list *tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
-             do_rte_announce(h, n, e, NULL, tmpa, ipa_classify(n->n.prefix));
-             lp_flush(rte_update_pool);
-             if (p->core_state != FS_FEEDING)
-               return;  /* In the meantime, the protocol fell down. */
-           }
-       }
-      FIB_WALK_END;
-    }
-}
-
 static inline int
 rte_validate(rte *e)
 {
@@ -683,6 +654,74 @@ rt_commit(struct config *new, struct config *old)
   DBG("\tdone\n");
 }
 
+int
+rt_feed_baby(struct proto *p)
+{
+  struct announce_hook *h;
+  struct fib_iterator *fit;
+  int max_feed = 2;                    /* FIXME */
+
+  if (!p->feed_ahook)                  /* Need to initialize first */
+    {
+      if (!p->ahooks)
+       return 1;
+      DBG("Announcing routes to new protocol %s\n", p->name);
+      p->feed_ahook = p->ahooks;
+      fit = p->feed_iterator = mb_alloc(p->pool, sizeof(struct fib_iterator));
+      goto next_hook;
+    }
+  fit = p->feed_iterator;
+
+again:
+  h = p->feed_ahook;
+  FIB_ITERATE_START(&h->table->fib, fit, fn)
+    {
+      net *n = (net *) fn;
+      rte *e;
+      for(e=n->routes; e; e=e->next)
+       {
+         struct proto *q = e->attrs->proto;
+         ea_list *tmpa;
+
+         if (p->core_state != FS_FEEDING)
+           return 1;  /* In the meantime, the protocol fell down. */
+         rte_update_lock();
+         tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
+         do_rte_announce(h, n, e, NULL, tmpa, ipa_classify(n->n.prefix));
+         rte_update_unlock();
+         if (!--max_feed)
+           {
+             FIB_ITERATE_PUT(fit, fn);
+             return 0;
+           }
+       }
+    }
+  FIB_ITERATE_END(fn);
+  p->feed_ahook = h->next;
+  if (!p->feed_ahook)
+    {
+      mb_free(p->feed_iterator);
+      p->feed_iterator = NULL;
+      return 1;
+    }
+
+next_hook:
+  h = p->feed_ahook;
+  FIB_ITERATE_INIT(fit, &h->table->fib);
+  goto again;
+}
+
+void
+rt_feed_baby_abort(struct proto *p)
+{
+  if (p->feed_ahook)
+    {
+      /* Unlink the iterator and exit */
+      fit_get(&p->feed_ahook->table->fib, p->feed_iterator);
+      p->feed_ahook = NULL;
+    }
+}
+
 /*
  *  CLI commands
  */