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.
This commit is contained in:
parent
d92882be9b
commit
47b793064c
7 changed files with 62 additions and 8 deletions
12
nest/iface.c
12
nest/iface.c
|
@ -312,6 +312,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
|
void
|
||||||
if_init(void)
|
if_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
extern list iface_list;
|
extern list iface_list;
|
||||||
|
|
||||||
|
struct proto;
|
||||||
|
|
||||||
struct iface {
|
struct iface {
|
||||||
node n;
|
node n;
|
||||||
char name[16];
|
char name[16];
|
||||||
|
@ -51,6 +53,7 @@ void if_dump(struct iface *);
|
||||||
void if_dump_all(void);
|
void if_dump_all(void);
|
||||||
void if_update(struct iface *);
|
void if_update(struct iface *);
|
||||||
void if_end_update(void);
|
void if_end_update(void);
|
||||||
|
void if_feed_baby(struct proto *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
|
* Neighbor Cache. We hold (direct neighbor, protocol) pairs we've seen
|
||||||
|
|
25
nest/proto.c
25
nest/proto.c
|
@ -15,9 +15,12 @@
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/lists.h"
|
#include "lib/lists.h"
|
||||||
#include "nest/confile.h"
|
#include "nest/confile.h"
|
||||||
|
#include "nest/route.h"
|
||||||
|
#include "nest/iface.h"
|
||||||
|
|
||||||
list protocol_list;
|
list protocol_list;
|
||||||
list proto_list;
|
list proto_list;
|
||||||
|
list inactive_proto_list;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
proto_new(struct protocol *pr, unsigned size)
|
proto_new(struct protocol *pr, unsigned size)
|
||||||
|
@ -30,7 +33,7 @@ proto_new(struct protocol *pr, unsigned size)
|
||||||
p->name = pr->name;
|
p->name = pr->name;
|
||||||
p->debug = pr->debug;
|
p->debug = pr->debug;
|
||||||
p->pool = rp_new(&root_pool, pr->name);
|
p->pool = rp_new(&root_pool, pr->name);
|
||||||
add_tail(&proto_list, &p->n);
|
add_tail(&inactive_proto_list, &p->n);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +43,7 @@ protos_preconfig(void)
|
||||||
struct protocol *p;
|
struct protocol *p;
|
||||||
|
|
||||||
init_list(&proto_list);
|
init_list(&proto_list);
|
||||||
|
init_list(&inactive_proto_list);
|
||||||
debug("Protocol preconfig\n");
|
debug("Protocol preconfig\n");
|
||||||
WALK_LIST(p, protocol_list)
|
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
|
void
|
||||||
protos_start(void)
|
protos_start(void)
|
||||||
{
|
{
|
||||||
struct proto *p;
|
struct proto *p, *n;
|
||||||
|
|
||||||
debug("Protocol start\n");
|
debug("Protocol start\n");
|
||||||
WALK_LIST(p, proto_list)
|
WALK_LIST_DELSAFE(p, n, inactive_proto_list)
|
||||||
{
|
{
|
||||||
debug("...%s\n", p->name);
|
debug("...%s\n", p->name);
|
||||||
if (p->start)
|
proto_start(p);
|
||||||
p->start(p);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +102,8 @@ protos_dump_all(void)
|
||||||
if (p->dump)
|
if (p->dump)
|
||||||
p->dump(p);
|
p->dump(p);
|
||||||
}
|
}
|
||||||
|
WALK_LIST(p, inactive_proto_list)
|
||||||
|
debug(" inactive %s\n", p->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct proto {
|
||||||
unsigned debug; /* Debugging flags */
|
unsigned debug; /* Debugging flags */
|
||||||
pool *pool; /* Local objects */
|
pool *pool; /* Local objects */
|
||||||
unsigned preference; /* Default route preference */
|
unsigned preference; /* Default route preference */
|
||||||
|
int ready; /* Already initialized */
|
||||||
|
|
||||||
void (*if_notify)(struct proto *, unsigned flags, struct iface *new, struct iface *old);
|
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);
|
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);
|
void *proto_new(struct protocol *, unsigned size);
|
||||||
|
|
||||||
extern list proto_list;
|
extern list proto_list, inactive_proto_list;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -126,6 +126,7 @@ void rte_update(net *net, struct proto *p, rte *new);
|
||||||
void rte_dump(net *, rte *);
|
void rte_dump(net *, rte *);
|
||||||
void rt_dump(rtable *);
|
void rt_dump(rtable *);
|
||||||
void rt_dump_all(void);
|
void rt_dump_all(void);
|
||||||
|
void rt_feed_baby(struct proto *p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Route Attributes
|
* Route Attributes
|
||||||
|
|
|
@ -116,6 +116,28 @@ rte_announce(net *net, rte *new, rte *old)
|
||||||
p->rt_notify(p, net, new, 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
|
static inline void
|
||||||
rte_free(rte *e)
|
rte_free(rte *e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,10 +82,10 @@ main(void)
|
||||||
|
|
||||||
signal_init();
|
signal_init();
|
||||||
|
|
||||||
protos_start();
|
|
||||||
|
|
||||||
scan_if_init();
|
scan_if_init();
|
||||||
|
|
||||||
|
protos_start();
|
||||||
|
|
||||||
handle_sigusr(0);
|
handle_sigusr(0);
|
||||||
|
|
||||||
debug("Entering I/O loop.\n");
|
debug("Entering I/O loop.\n");
|
||||||
|
|
Loading…
Reference in a new issue