]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
From now we support multiple tables. The master_table variable is
authorMartin Mares <mj@ucw.cz>
Mon, 17 May 1999 20:14:52 +0000 (20:14 +0000)
committerMartin Mares <mj@ucw.cz>
Mon, 17 May 1999 20:14:52 +0000 (20:14 +0000)
definitely gone. Both rte_update() and rte_discard() have an additional
argument telling which table should they modify.

Also, rte_update() no longer walks the whole protocol list -- each table
has a list of all protocols connected to this table and having the
rt_notify hook set. Each protocol can also freely decide (by calling
proto_add_announce_hook) to connect to any other table, but it will
be probably used only by the table-to-table protocol.

The default debugging dumps now include all routing tables and also
all their connections.

conf/conf.c
conf/confbase.Y
doc/bird.conf.example
nest/config.Y
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-table.c

index 61fe9f8846415e9fd4b31291793530a7799e99ba..0ce593c76215cdc5cbc1326b876fac3f0d7a8499 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdarg.h>
 
 #include "nest/bird.h"
+#include "nest/route.h"
 #include "nest/protocol.h"
 #include "nest/iface.h"
 #include "lib/resource.h"
@@ -49,6 +50,7 @@ config_parse(struct config *c)
   cf_lex_init(1);
   cf_lex_init_tables();
   protos_preconfig(c);
+  rt_preconfig(c);
   cf_parse();
   filters_postconfig();                        /* FIXME: Do we really need this? */
   protos_postconfig(c);
@@ -65,6 +67,7 @@ void
 config_commit(struct config *c)
 {
   config = c;
+  rt_commit(c);
   protos_commit(c);
 }
 
index 522a1803a4f2d7757fa725172551d35f0e32df97..2343536a134f060236a11f275e915ec24f579d20 100644 (file)
@@ -25,6 +25,7 @@ CF_DECLS
   ip_addr a;
   struct symbol *s;
   char *t;
+  struct rtable_config *r;
   struct f_inst *x;
   struct filter *f;
   struct f_tree *e;
@@ -78,8 +79,7 @@ expr:
 CF_ADDTO(conf, definition)
 definition:
    DEFINE SYM '=' expr ';' {
-     if ($2->class != SYM_VOID) cf_error("Symbol already defined");
-     $2->class = SYM_NUMBER;
+     cf_define_symbol($2, SYM_NUMBER, NULL);
      $2->aux = $4;
    }
  ;
index 6580ee7a02c753f0c16af6668fe1219eb470ad5b..c3becbb5310ec3204c41315189bad57a51ec18de 100644 (file)
@@ -11,6 +11,8 @@
 #filter sink { reject; }
 #filter okay { accept; }
 
+#table testable;
+
 #protocol rip MyRIP_test {
 #      preference xyzzy;
 #      debug all;
@@ -38,6 +40,7 @@ protocol device {
 
 protocol static {
 #      disabled;
+#      table testable;
 #      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;
index c535e9ecdd57306062f8c412c811e8d1a8e398fc..667f435ce3a64ff1c7cd43890bdcb119e037dae1 100644 (file)
@@ -17,16 +17,18 @@ void rt_dev_add_iface(char *);
 CF_DECLS
 
 CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
-CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE)
+CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE)
 
 %type <i> idval
 %type <f> imexport
+%type <r> rtable
 
 CF_GRAMMAR
 
 /* Setting of router ID */
 
 CF_ADDTO(conf, rtrid)
+
 rtrid: ROUTER ID idval ';' {
    new_config->router_id = $3;
    }
@@ -37,6 +39,19 @@ idval:
  | IPA { $$ = ipa_to_u32($1); }
  ;
 
+/* Creation of routing tables */
+
+CF_ADDTO(conf, newtab)
+
+newtab: TABLE SYM {
+     struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
+     struct symbol *s = $2;
+     cf_define_symbol(s, SYM_TABLE, c);
+     c->name = s->name;
+     add_tail(&new_config->tables, &c->n);
+   }
+ ;
+
 /* Definition of protocols */
 
 CF_ADDTO(conf, proto)
@@ -51,9 +66,7 @@ proto_name:
      this_proto->name = s->name;
      }
  | SYM {
-     if ($1->class) cf_error("Symbol already defined");
-     $1->class = SYM_PROTO;
-     $1->def = this_proto;
+     cf_define_symbol($1, SYM_PROTO, this_proto);
      this_proto->name = $1->name;
    }
  ;
@@ -70,6 +83,7 @@ proto_item:
  | DEBUG OFF { this_proto->debug = 0; }
  | IMPORT imexport { this_proto->in_filter = $2; }
  | EXPORT imexport { this_proto->out_filter = $2; }
+ | TABLE rtable { this_proto->table = $2; }
  ;
 
 imexport:
@@ -78,6 +92,13 @@ imexport:
  | NONE { $$ = FILTER_REJECT; }
  ;
 
+rtable:
+   SYM {
+     if ($1->class != SYM_TABLE) cf_error("Table name expected");
+     $$ = $1->def;
+   }
+ ;
+
 /* Direct device route protocol */
 
 CF_ADDTO(proto, dev_proto '}')
index ad4aa11d83a2ce3bfbbc41164e273bd7dd0db39f..3199fee26e2618a0c7811015abbba630321711ac 100644 (file)
@@ -86,7 +86,7 @@ proto_new(struct proto_config *c, unsigned size)
   p->preference = c->preference;
   p->disabled = c->disabled;
   p->proto = pr;
-  p->table = &master_table;
+  p->table = (c->table ? : c->global->master_rtc)->table;
   p->in_filter = c->in_filter;
   p->out_filter = c->out_filter;
   return p;
@@ -101,6 +101,33 @@ proto_init_instance(struct proto *p)
   p->attn->data = p;
 }
 
+struct announce_hook *
+proto_add_announce_hook(struct proto *p, struct rtable *t)
+{
+  struct announce_hook *h;
+
+  if (!p->rt_notify)
+    return NULL;
+  DBG("Connecting protocol %s to table %s\n", p->name, t->name);
+  h = mb_alloc(p->pool, sizeof(struct announce_hook));
+  h->table = t;
+  h->proto = p;
+  h->next = p->ahooks;
+  p->ahooks = h;
+  add_tail(&t->hooks, &h->n);
+  return h;
+}
+
+static void
+proto_flush_hooks(struct proto *p)
+{
+  struct announce_hook *h;
+
+  for(h=p->ahooks; h; h=h->next)
+    rem_node(&h->n);
+  p->ahooks = NULL;
+}
+
 void *
 proto_config_new(struct protocol *pr, unsigned size)
 {
@@ -296,6 +323,7 @@ proto_feed(void *P)
   struct proto *p = 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;
@@ -365,11 +393,12 @@ proto_flush_all(void *unused)
 {
   struct proto *p;
 
-  rt_prune(&master_table);
+  rt_prune_all();
   neigh_prune();
   while ((p = HEAD(flush_proto_list))->n.next)
     {
       DBG("Flushing protocol %s\n", p->name);
+      proto_flush_hooks(p);
       rfree(p->pool);
       p->pool = NULL;
       p->core_state = FS_HUNGRY;
index 5e1e2ce9bf760db29313967fcfb53ae047b34d01..3aed2f21a31b4d9d2ef131a521350ebc93e3c1a7 100644 (file)
@@ -73,6 +73,7 @@ struct proto_config {
   struct protocol *proto;              /* Protocol */
   char *name;
   unsigned debug, preference, disabled;        /* Generic parameters */
+  struct rtable_config *table;         /* Table we're attached to */
   struct filter *in_filter, *out_filter; /* Attached filters */
 
   /* Protocol-specific data follow... */
@@ -128,9 +129,10 @@ struct proto {
   void (*rte_insert)(struct network *, struct rte *);
   void (*rte_remove)(struct network *, struct rte *);
 
-  struct rtable *table;                        /* Routing table we're connected to */
+  struct rtable *table;                        /* Our primary routing table */
   struct filter *in_filter;            /* Input filter */
   struct filter *out_filter;           /* Output filter */
+  struct announce_hook *ahooks;                /* Announcement hooks for this protocol */
 
   /* Hic sunt protocol-specific data */
 };
@@ -222,6 +224,19 @@ void proto_notify_state(struct proto *p, unsigned state);
 
 extern struct proto_config *cf_dev_proto;
 
+/*
+ *     Route Announcement Hook
+ */
+
+struct announce_hook {
+  node n;
+  struct rtable *table;
+  struct proto *proto;
+  struct announce_hook *next;          /* Next hook for the same protocol */
+};
+
+struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
+
 /*
  *     Callback to sysdep code when shutdown is finished
  */
index 10628cdb937e457e9e6c4ba5dd642eb522ad7f29..5e6b87394cb95b5ad89fe79503ec7fa923b8268e 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _BIRD_ROUTE_H_
 #define _BIRD_ROUTE_H_
 
+#include "lib/lists.h"
 #include "lib/resource.h"
 #include "lib/timer.h"
 
@@ -104,9 +105,17 @@ void fit_put(struct fib_iterator *, struct fib_node *);
  *     It's guaranteed that there is at most one RTE for every (prefix,proto) pair.
  */
 
+struct rtable_config {
+  node n;
+  char *name;
+  struct rtable *table;
+};
+
 typedef struct rtable {
+  node n;                              /* Node in list of all tables */
   struct fib fib;
   char *name;                          /* Name of this table */
+  list hooks;                          /* List of announcement hooks */
 } rtable;
 
 typedef struct network {
@@ -152,16 +161,18 @@ typedef struct rte {
 
 #define REF_COW 1                      /* Copy this rte on write */
 
-extern rtable master_table;
+struct config;
 
 void rt_init(void);
+void rt_preconfig(struct config *);
+void rt_commit(struct config *);
 void rt_setup(pool *, rtable *, char *);
 static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
 static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
 rte *rte_find(net *net, struct proto *p);
 rte *rte_get_temp(struct rta *);
-void rte_update(net *net, struct proto *p, rte *new);
-void rte_discard(rte *old);
+void rte_update(rtable *tab, net *net, struct proto *p, rte *new);
+void rte_discard(rtable *tab, rte *old);
 void rte_dump(rte *);
 void rte_free(rte *);
 rte *rte_do_cow(rte *);
@@ -170,6 +181,7 @@ void rt_dump(rtable *);
 void rt_dump_all(void);
 void rt_feed_baby(struct proto *p);
 void rt_prune(rtable *tab);
+void rt_prune_all(void);
 
 /*
  *     Route Attributes
index 2b60bb839c59ce03a8457afa7289d5da305839b6..a603c7f107f6bdbca647e78101d4dabb0f89091f 100644 (file)
@@ -15,9 +15,9 @@
 #include "nest/protocol.h"
 #include "lib/resource.h"
 #include "lib/event.h"
+#include "conf/conf.h"
 #include "filter/filter.h"
 
-rtable master_table;
 static slab *rte_slab;
 static linpool *rte_update_pool;
 
@@ -25,6 +25,7 @@ static linpool *rte_update_pool;
 #define RT_GC_MIN_COUNT 100
 
 static pool *rt_table_pool;
+static list routing_tables;
 static event *rt_gc_event;
 static bird_clock_t rt_last_gc;
 static int rt_gc_counter;
@@ -44,6 +45,7 @@ rt_setup(pool *p, rtable *t, char *name)
   bzero(t, sizeof(*t));
   fib_init(&t->fib, p, sizeof(rte), 0, rte_init);
   t->name = name;
+  init_list(&t->hooks);
 }
 
 rte *
@@ -97,8 +99,9 @@ rte_better(rte *new, rte *old)
 }
 
 static inline void
-do_rte_announce(struct proto *p, net *net, rte *new, rte *old, ea_list *tmpa)
+do_rte_announce(struct announce_hook *a, net *net, rte *new, rte *old, ea_list *tmpa)
 {
+  struct proto *p = a->proto;
   rte *new0 = new;
   rte *old0 = old;
   if (new)
@@ -132,39 +135,42 @@ do_rte_announce(struct proto *p, net *net, rte *new, rte *old, ea_list *tmpa)
 }
 
 static void
-rte_announce(net *net, rte *new, rte *old, ea_list *tmpa)
+rte_announce(rtable *tab, net *net, rte *new, rte *old, ea_list *tmpa)
 {
-  struct proto *p;
+  struct announce_hook *a;
 
-  WALK_LIST(p, proto_list)
+  WALK_LIST(a, tab->hooks)
     {
-      ASSERT(p->core_state == FS_HAPPY);
-      if (p->rt_notify)
-       do_rte_announce(p, net, new, old, tmpa);
+      ASSERT(a->proto->core_state == FS_HAPPY);
+      do_rte_announce(a, net, new, old, tmpa);
     }
 }
 
 void
 rt_feed_baby(struct proto *p)
 {
-  rtable *t = &master_table;
+  struct announce_hook *h;
 
-  if (!p->rt_notify)
+  if (!p->ahooks)
     return;
   debug("Announcing routes to new protocol %s\n", p->name);
-  FIB_WALK(&t->fib, fn)
+  for(h=p->ahooks; h; h=h->next)
     {
-      net *n = (net *) fn;
-      rte *e;
-      for(e=n->routes; e; e=e->next)
+      rtable *t = h->table;
+      FIB_WALK(&t->fib, fn)
        {
-         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(p, n, e, NULL, tmpa);
-         lp_flush(rte_update_pool);
+         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);
+             lp_flush(rte_update_pool);
+           }
        }
+      FIB_WALK_END;
     }
-  FIB_WALK_END;
 }
 
 static inline int
@@ -215,7 +221,7 @@ rte_free_quick(rte *e)
 }
 
 static void
-rte_recalculate(net *net, struct proto *p, rte *new, ea_list *tmpa)
+rte_recalculate(rtable *table, net *net, struct proto *p, rte *new, ea_list *tmpa)
 {
   rte *old_best = net->routes;
   rte *old = NULL;
@@ -234,7 +240,7 @@ rte_recalculate(net *net, struct proto *p, rte *new, ea_list *tmpa)
 
   if (new && rte_better(new, old_best))        /* It's a new optimal route => announce and relink it */
     {
-      rte_announce(net, new, old_best, tmpa);
+      rte_announce(table, net, new, old_best, tmpa);
       new->next = net->routes;
       net->routes = new;
     }
@@ -246,7 +252,7 @@ rte_recalculate(net *net, struct proto *p, rte *new, ea_list *tmpa)
          for(s=net->routes; s; s=s->next)
            if (rte_better(s, r))
              r = s;
-         rte_announce(net, r, old_best, tmpa);
+         rte_announce(table, net, r, old_best, tmpa);
          if (r)                        /* Re-link the new optimal route */
            {
              k = &net->routes;
@@ -301,7 +307,7 @@ rte_update_unlock(void)
 }
 
 void
-rte_update(net *net, struct proto *p, rte *new)
+rte_update(rtable *table, net *net, struct proto *p, rte *new)
 {
   ea_list *tmpa = NULL;
 
@@ -324,7 +330,7 @@ rte_update(net *net, struct proto *p, rte *new)
        new->attrs = rta_lookup(new->attrs);
       new->flags |= REF_COW;
     }
-  rte_recalculate(net, p, new, tmpa);
+  rte_recalculate(table, net, p, new, tmpa);
   rte_update_unlock();
   return;
 
@@ -334,10 +340,10 @@ drop:
 }
 
 void
-rte_discard(rte *old)                  /* Non-filtered route deletion, used during garbage collection */
+rte_discard(rtable *t, rte *old)       /* Non-filtered route deletion, used during garbage collection */
 {
   rte_update_lock();
-  rte_recalculate(old->net, old->attrs->proto, NULL, NULL);
+  rte_recalculate(t, old->net, old->attrs->proto, NULL, NULL);
   rte_update_unlock();
 }
 
@@ -361,6 +367,7 @@ rt_dump(rtable *t)
 {
   rte *e;
   net *n;
+  struct announce_hook *a;
 
   debug("Dump of routing table <%s>\n", t->name);
 #ifdef DEBUGGING
@@ -373,20 +380,27 @@ rt_dump(rtable *t)
        rte_dump(e);
     }
   FIB_WALK_END;
+  WALK_LIST(a, t->hooks)
+    debug("\tAnnounces routes to protocol %s\n", a->proto->name);
   debug("\n");
 }
 
 void
 rt_dump_all(void)
 {
-  rt_dump(&master_table);
+  rtable *t;
+
+  WALK_LIST(t, routing_tables)
+    rt_dump(t);
 }
 
 static void
 rt_gc(void *unused)
 {
+  rtable *t;
+
   DBG("Entered routing table garbage collector after %d seconds and %d deletes\n", (int)(now - rt_last_gc), rt_gc_counter);
-  rt_prune(&master_table);
+  rt_prune_all();
   rt_last_gc = now;
   rt_gc_counter = 0;
 }
@@ -397,11 +411,11 @@ rt_init(void)
   rta_init();
   rt_table_pool = rp_new(&root_pool, "Routing tables");
   rte_update_pool = lp_new(rt_table_pool, 4080);
-  rt_setup(rt_table_pool, &master_table, "master");
   rte_slab = sl_new(rt_table_pool, sizeof(rte));
   rt_last_gc = now;
   rt_gc_event = ev_new(rt_table_pool);
   rt_gc_event->hook = rt_gc;
+  init_list(&routing_tables);
 }
 
 void
@@ -422,7 +436,7 @@ again:
       for (e=n->routes; e; e=e->next, rcnt++)
        if (e->attrs->proto->core_state != FS_HAPPY)
          {
-           rte_discard(e);
+           rte_discard(tab, e);
            rdel++;
            goto rescan;
          }
@@ -437,3 +451,39 @@ again:
   FIB_ITERATE_END(f);
   DBG("Pruned %d of %d routes and %d of %d networks\n", rcnt, rdel, ncnt, ndel);
 }
+
+void
+rt_prune_all(void)
+{
+  rtable *t;
+
+  WALK_LIST(t, routing_tables)
+    rt_prune(t);
+}
+
+void
+rt_preconfig(struct config *c)
+{
+  struct symbol *s = cf_find_symbol("master");
+  struct rtable_config *r = cfg_allocz(sizeof(struct rtable_config));
+
+  cf_define_symbol(s, SYM_TABLE, r);
+  r->name = s->name;
+  init_list(&c->tables);
+  add_tail(&c->tables, &r->n);
+  c->master_rtc = r;
+}
+
+void
+rt_commit(struct config *c)
+{
+  struct rtable_config *r;
+
+  WALK_LIST(r, c->tables)
+    {
+      rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
+      rt_setup(rt_table_pool, t, r->name);
+      add_tail(&routing_tables, &t->n);
+      r->table = t;
+    }
+}