summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>1998-10-17 13:05:18 +0200
committerMartin Mares <mj@ucw.cz>1998-10-17 13:05:18 +0200
commit47b793064c25c8adcab48cacc018be1675f2448a (patch)
treec6924c3fb31bf8cd7d650ad8e6c52c395457eca9
parentd92882be9b1bfcc1a8e8a7bd552bdec4831694aa (diff)
downloadbird-47b793064c25c8adcab48cacc018be1675f2448a.tar
bird-47b793064c25c8adcab48cacc018be1675f2448a.zip
Solve chicken-and-egg problems with protocol startup. We now queue all inactive
protocols and don't send route/interface updates to them and when they come up, we resend the whole route/interface tables privately. Removed the "scan interface list after protocol start" work-around.
-rw-r--r--nest/iface.c12
-rw-r--r--nest/iface.h3
-rw-r--r--nest/proto.c25
-rw-r--r--nest/protocol.h3
-rw-r--r--nest/route.h1
-rw-r--r--nest/rt-table.c22
-rw-r--r--sysdep/unix/main.c4
7 files changed, 62 insertions, 8 deletions
diff --git a/nest/iface.c b/nest/iface.c
index 591733a..f6f33a9 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -313,6 +313,18 @@ if_end_update(void)
}
void
+if_feed_baby(struct proto *p)
+{
+ struct iface *i;
+
+ if (!p->if_notify)
+ return;
+ debug("Announcing interfaces to new protocol %s\n", p->name);
+ WALK_LIST(i, iface_list)
+ p->if_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), NULL, i);
+}
+
+void
if_init(void)
{
if_pool = rp_new(&root_pool, "Interfaces");
diff --git a/nest/iface.h b/nest/iface.h
index b1984b3..101e028 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -13,6 +13,8 @@
extern list iface_list;
+struct proto;
+
struct iface {
node n;
char name[16];
@@ -51,6 +53,7 @@ void if_dump(struct iface *);
void if_dump_all(void);
void if_update(struct iface *);
void if_end_update(void);
+void if_feed_baby(struct proto *);
/*
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
diff --git a/nest/proto.c b/nest/proto.c
index 478eb77..6db5a0e 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -15,9 +15,12 @@
#include "lib/resource.h"
#include "lib/lists.h"
#include "nest/confile.h"
+#include "nest/route.h"
+#include "nest/iface.h"
list protocol_list;
list proto_list;
+list inactive_proto_list;
void *
proto_new(struct protocol *pr, unsigned size)
@@ -30,7 +33,7 @@ proto_new(struct protocol *pr, unsigned size)
p->name = pr->name;
p->debug = pr->debug;
p->pool = rp_new(&root_pool, pr->name);
- add_tail(&proto_list, &p->n);
+ add_tail(&inactive_proto_list, &p->n);
return p;
}
@@ -40,6 +43,7 @@ protos_preconfig(void)
struct protocol *p;
init_list(&proto_list);
+ init_list(&inactive_proto_list);
debug("Protocol preconfig\n");
WALK_LIST(p, protocol_list)
{
@@ -61,18 +65,27 @@ protos_postconfig(void)
}
}
+static void
+proto_start(struct proto *p)
+{
+ rem_node(&p->n);
+ if (p->start)
+ p->start(p);
+ if_feed_baby(p);
+ rt_feed_baby(p);
+ add_tail(&proto_list, &p->n);
+}
void
protos_start(void)
{
- struct proto *p;
+ struct proto *p, *n;
debug("Protocol start\n");
- WALK_LIST(p, proto_list)
+ WALK_LIST_DELSAFE(p, n, inactive_proto_list)
{
debug("...%s\n", p->name);
- if (p->start)
- p->start(p);
+ proto_start(p);
}
}
@@ -89,6 +102,8 @@ protos_dump_all(void)
if (p->dump)
p->dump(p);
}
+ WALK_LIST(p, inactive_proto_list)
+ debug(" inactive %s\n", p->name);
}
void
diff --git a/nest/protocol.h b/nest/protocol.h
index 92bcbbe..ec4408f 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -58,6 +58,7 @@ struct proto {
unsigned debug; /* Debugging flags */
pool *pool; /* Local objects */
unsigned preference; /* Default route preference */
+ int ready; /* Already initialized */
void (*if_notify)(struct proto *, unsigned flags, struct iface *new, struct iface *old);
void (*rt_notify)(struct proto *, struct network *net, struct rte *new, struct rte *old);
@@ -79,6 +80,6 @@ struct proto {
void *proto_new(struct protocol *, unsigned size);
-extern list proto_list;
+extern list proto_list, inactive_proto_list;
#endif
diff --git a/nest/route.h b/nest/route.h
index 8e335b2..1bd20b6 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -126,6 +126,7 @@ void rte_update(net *net, struct proto *p, rte *new);
void rte_dump(net *, rte *);
void rt_dump(rtable *);
void rt_dump_all(void);
+void rt_feed_baby(struct proto *p);
/*
* Route Attributes
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 1d0c29c..dc72c6b 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -116,6 +116,28 @@ rte_announce(net *net, rte *new, rte *old)
p->rt_notify(p, net, new, old);
}
+void
+rt_feed_baby(struct proto *p)
+{
+ rtable *t = &master_table;
+
+ if (!p->rt_notify)
+ return;
+ debug("Announcing routes to new protocol %s\n", p->name);
+ while (t)
+ {
+ FIB_WALK(&t->fib, fn)
+ {
+ net *n = (net *) fn;
+ rte *e;
+ for(e=n->routes; e; e=e->next)
+ p->rt_notify(p, n, e, NULL);
+ }
+ FIB_WALK_END;
+ t = t->sibling;
+ }
+}
+
static inline void
rte_free(rte *e)
{
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index ce3768c..b57e94e 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -82,10 +82,10 @@ main(void)
signal_init();
- protos_start();
-
scan_if_init();
+ protos_start();
+
handle_sigusr(0);
debug("Entering I/O loop.\n");