From now we support multiple tables. The master_table variable is
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.
This commit is contained in:
parent
4107df1d1b
commit
0e02abfd57
8 changed files with 175 additions and 42 deletions
|
@ -10,6 +10,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
@ -49,6 +50,7 @@ config_parse(struct config *c)
|
||||||
cf_lex_init(1);
|
cf_lex_init(1);
|
||||||
cf_lex_init_tables();
|
cf_lex_init_tables();
|
||||||
protos_preconfig(c);
|
protos_preconfig(c);
|
||||||
|
rt_preconfig(c);
|
||||||
cf_parse();
|
cf_parse();
|
||||||
filters_postconfig(); /* FIXME: Do we really need this? */
|
filters_postconfig(); /* FIXME: Do we really need this? */
|
||||||
protos_postconfig(c);
|
protos_postconfig(c);
|
||||||
|
@ -65,6 +67,7 @@ void
|
||||||
config_commit(struct config *c)
|
config_commit(struct config *c)
|
||||||
{
|
{
|
||||||
config = c;
|
config = c;
|
||||||
|
rt_commit(c);
|
||||||
protos_commit(c);
|
protos_commit(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ CF_DECLS
|
||||||
ip_addr a;
|
ip_addr a;
|
||||||
struct symbol *s;
|
struct symbol *s;
|
||||||
char *t;
|
char *t;
|
||||||
|
struct rtable_config *r;
|
||||||
struct f_inst *x;
|
struct f_inst *x;
|
||||||
struct filter *f;
|
struct filter *f;
|
||||||
struct f_tree *e;
|
struct f_tree *e;
|
||||||
|
@ -78,8 +79,7 @@ expr:
|
||||||
CF_ADDTO(conf, definition)
|
CF_ADDTO(conf, definition)
|
||||||
definition:
|
definition:
|
||||||
DEFINE SYM '=' expr ';' {
|
DEFINE SYM '=' expr ';' {
|
||||||
if ($2->class != SYM_VOID) cf_error("Symbol already defined");
|
cf_define_symbol($2, SYM_NUMBER, NULL);
|
||||||
$2->class = SYM_NUMBER;
|
|
||||||
$2->aux = $4;
|
$2->aux = $4;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#filter sink { reject; }
|
#filter sink { reject; }
|
||||||
#filter okay { accept; }
|
#filter okay { accept; }
|
||||||
|
|
||||||
|
#table testable;
|
||||||
|
|
||||||
#protocol rip MyRIP_test {
|
#protocol rip MyRIP_test {
|
||||||
# preference xyzzy;
|
# preference xyzzy;
|
||||||
# debug all;
|
# debug all;
|
||||||
|
@ -38,6 +40,7 @@ protocol device {
|
||||||
|
|
||||||
protocol static {
|
protocol static {
|
||||||
# disabled;
|
# disabled;
|
||||||
|
# table testable;
|
||||||
# route 0.0.0.0/0 via 62.168.0.13;
|
# route 0.0.0.0/0 via 62.168.0.13;
|
||||||
# route 62.168.0.0/25 reject;
|
# route 62.168.0.0/25 reject;
|
||||||
# route 10.0.0.0/8 reject;
|
# route 10.0.0.0/8 reject;
|
||||||
|
|
|
@ -17,16 +17,18 @@ void rt_dev_add_iface(char *);
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
|
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 <i> idval
|
||||||
%type <f> imexport
|
%type <f> imexport
|
||||||
|
%type <r> rtable
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
/* Setting of router ID */
|
/* Setting of router ID */
|
||||||
|
|
||||||
CF_ADDTO(conf, rtrid)
|
CF_ADDTO(conf, rtrid)
|
||||||
|
|
||||||
rtrid: ROUTER ID idval ';' {
|
rtrid: ROUTER ID idval ';' {
|
||||||
new_config->router_id = $3;
|
new_config->router_id = $3;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +39,19 @@ idval:
|
||||||
| IPA { $$ = ipa_to_u32($1); }
|
| 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 */
|
/* Definition of protocols */
|
||||||
|
|
||||||
CF_ADDTO(conf, proto)
|
CF_ADDTO(conf, proto)
|
||||||
|
@ -51,9 +66,7 @@ proto_name:
|
||||||
this_proto->name = s->name;
|
this_proto->name = s->name;
|
||||||
}
|
}
|
||||||
| SYM {
|
| SYM {
|
||||||
if ($1->class) cf_error("Symbol already defined");
|
cf_define_symbol($1, SYM_PROTO, this_proto);
|
||||||
$1->class = SYM_PROTO;
|
|
||||||
$1->def = this_proto;
|
|
||||||
this_proto->name = $1->name;
|
this_proto->name = $1->name;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -70,6 +83,7 @@ proto_item:
|
||||||
| DEBUG OFF { this_proto->debug = 0; }
|
| DEBUG OFF { this_proto->debug = 0; }
|
||||||
| IMPORT imexport { this_proto->in_filter = $2; }
|
| IMPORT imexport { this_proto->in_filter = $2; }
|
||||||
| EXPORT imexport { this_proto->out_filter = $2; }
|
| EXPORT imexport { this_proto->out_filter = $2; }
|
||||||
|
| TABLE rtable { this_proto->table = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
imexport:
|
imexport:
|
||||||
|
@ -78,6 +92,13 @@ imexport:
|
||||||
| NONE { $$ = FILTER_REJECT; }
|
| NONE { $$ = FILTER_REJECT; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
rtable:
|
||||||
|
SYM {
|
||||||
|
if ($1->class != SYM_TABLE) cf_error("Table name expected");
|
||||||
|
$$ = $1->def;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
/* Direct device route protocol */
|
/* Direct device route protocol */
|
||||||
|
|
||||||
CF_ADDTO(proto, dev_proto '}')
|
CF_ADDTO(proto, dev_proto '}')
|
||||||
|
|
33
nest/proto.c
33
nest/proto.c
|
@ -86,7 +86,7 @@ proto_new(struct proto_config *c, unsigned size)
|
||||||
p->preference = c->preference;
|
p->preference = c->preference;
|
||||||
p->disabled = c->disabled;
|
p->disabled = c->disabled;
|
||||||
p->proto = pr;
|
p->proto = pr;
|
||||||
p->table = &master_table;
|
p->table = (c->table ? : c->global->master_rtc)->table;
|
||||||
p->in_filter = c->in_filter;
|
p->in_filter = c->in_filter;
|
||||||
p->out_filter = c->out_filter;
|
p->out_filter = c->out_filter;
|
||||||
return p;
|
return p;
|
||||||
|
@ -101,6 +101,33 @@ proto_init_instance(struct proto *p)
|
||||||
p->attn->data = 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 *
|
void *
|
||||||
proto_config_new(struct protocol *pr, unsigned size)
|
proto_config_new(struct protocol *pr, unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -296,6 +323,7 @@ proto_feed(void *P)
|
||||||
struct proto *p = P;
|
struct proto *p = P;
|
||||||
|
|
||||||
DBG("Feeding protocol %s\n", p->name);
|
DBG("Feeding protocol %s\n", p->name);
|
||||||
|
proto_add_announce_hook(p, p->table);
|
||||||
if_feed_baby(p);
|
if_feed_baby(p);
|
||||||
rt_feed_baby(p);
|
rt_feed_baby(p);
|
||||||
p->core_state = FS_HAPPY;
|
p->core_state = FS_HAPPY;
|
||||||
|
@ -365,11 +393,12 @@ proto_flush_all(void *unused)
|
||||||
{
|
{
|
||||||
struct proto *p;
|
struct proto *p;
|
||||||
|
|
||||||
rt_prune(&master_table);
|
rt_prune_all();
|
||||||
neigh_prune();
|
neigh_prune();
|
||||||
while ((p = HEAD(flush_proto_list))->n.next)
|
while ((p = HEAD(flush_proto_list))->n.next)
|
||||||
{
|
{
|
||||||
DBG("Flushing protocol %s\n", p->name);
|
DBG("Flushing protocol %s\n", p->name);
|
||||||
|
proto_flush_hooks(p);
|
||||||
rfree(p->pool);
|
rfree(p->pool);
|
||||||
p->pool = NULL;
|
p->pool = NULL;
|
||||||
p->core_state = FS_HUNGRY;
|
p->core_state = FS_HUNGRY;
|
||||||
|
|
|
@ -73,6 +73,7 @@ struct proto_config {
|
||||||
struct protocol *proto; /* Protocol */
|
struct protocol *proto; /* Protocol */
|
||||||
char *name;
|
char *name;
|
||||||
unsigned debug, preference, disabled; /* Generic parameters */
|
unsigned debug, preference, disabled; /* Generic parameters */
|
||||||
|
struct rtable_config *table; /* Table we're attached to */
|
||||||
struct filter *in_filter, *out_filter; /* Attached filters */
|
struct filter *in_filter, *out_filter; /* Attached filters */
|
||||||
|
|
||||||
/* Protocol-specific data follow... */
|
/* Protocol-specific data follow... */
|
||||||
|
@ -128,9 +129,10 @@ struct proto {
|
||||||
void (*rte_insert)(struct network *, struct rte *);
|
void (*rte_insert)(struct network *, struct rte *);
|
||||||
void (*rte_remove)(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 *in_filter; /* Input filter */
|
||||||
struct filter *out_filter; /* Output filter */
|
struct filter *out_filter; /* Output filter */
|
||||||
|
struct announce_hook *ahooks; /* Announcement hooks for this protocol */
|
||||||
|
|
||||||
/* Hic sunt protocol-specific data */
|
/* 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;
|
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
|
* Callback to sysdep code when shutdown is finished
|
||||||
*/
|
*/
|
||||||
|
|
18
nest/route.h
18
nest/route.h
|
@ -9,6 +9,7 @@
|
||||||
#ifndef _BIRD_ROUTE_H_
|
#ifndef _BIRD_ROUTE_H_
|
||||||
#define _BIRD_ROUTE_H_
|
#define _BIRD_ROUTE_H_
|
||||||
|
|
||||||
|
#include "lib/lists.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/timer.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.
|
* 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 {
|
typedef struct rtable {
|
||||||
|
node n; /* Node in list of all tables */
|
||||||
struct fib fib;
|
struct fib fib;
|
||||||
char *name; /* Name of this table */
|
char *name; /* Name of this table */
|
||||||
|
list hooks; /* List of announcement hooks */
|
||||||
} rtable;
|
} rtable;
|
||||||
|
|
||||||
typedef struct network {
|
typedef struct network {
|
||||||
|
@ -152,16 +161,18 @@ typedef struct rte {
|
||||||
|
|
||||||
#define REF_COW 1 /* Copy this rte on write */
|
#define REF_COW 1 /* Copy this rte on write */
|
||||||
|
|
||||||
extern rtable master_table;
|
struct config;
|
||||||
|
|
||||||
void rt_init(void);
|
void rt_init(void);
|
||||||
|
void rt_preconfig(struct config *);
|
||||||
|
void rt_commit(struct config *);
|
||||||
void rt_setup(pool *, rtable *, char *);
|
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_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); }
|
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_find(net *net, struct proto *p);
|
||||||
rte *rte_get_temp(struct rta *);
|
rte *rte_get_temp(struct rta *);
|
||||||
void rte_update(net *net, struct proto *p, rte *new);
|
void rte_update(rtable *tab, net *net, struct proto *p, rte *new);
|
||||||
void rte_discard(rte *old);
|
void rte_discard(rtable *tab, rte *old);
|
||||||
void rte_dump(rte *);
|
void rte_dump(rte *);
|
||||||
void rte_free(rte *);
|
void rte_free(rte *);
|
||||||
rte *rte_do_cow(rte *);
|
rte *rte_do_cow(rte *);
|
||||||
|
@ -170,6 +181,7 @@ void rt_dump(rtable *);
|
||||||
void rt_dump_all(void);
|
void rt_dump_all(void);
|
||||||
void rt_feed_baby(struct proto *p);
|
void rt_feed_baby(struct proto *p);
|
||||||
void rt_prune(rtable *tab);
|
void rt_prune(rtable *tab);
|
||||||
|
void rt_prune_all(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Route Attributes
|
* Route Attributes
|
||||||
|
|
110
nest/rt-table.c
110
nest/rt-table.c
|
@ -15,9 +15,9 @@
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/event.h"
|
#include "lib/event.h"
|
||||||
|
#include "conf/conf.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
rtable master_table;
|
|
||||||
static slab *rte_slab;
|
static slab *rte_slab;
|
||||||
static linpool *rte_update_pool;
|
static linpool *rte_update_pool;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ static linpool *rte_update_pool;
|
||||||
#define RT_GC_MIN_COUNT 100
|
#define RT_GC_MIN_COUNT 100
|
||||||
|
|
||||||
static pool *rt_table_pool;
|
static pool *rt_table_pool;
|
||||||
|
static list routing_tables;
|
||||||
static event *rt_gc_event;
|
static event *rt_gc_event;
|
||||||
static bird_clock_t rt_last_gc;
|
static bird_clock_t rt_last_gc;
|
||||||
static int rt_gc_counter;
|
static int rt_gc_counter;
|
||||||
|
@ -44,6 +45,7 @@ rt_setup(pool *p, rtable *t, char *name)
|
||||||
bzero(t, sizeof(*t));
|
bzero(t, sizeof(*t));
|
||||||
fib_init(&t->fib, p, sizeof(rte), 0, rte_init);
|
fib_init(&t->fib, p, sizeof(rte), 0, rte_init);
|
||||||
t->name = name;
|
t->name = name;
|
||||||
|
init_list(&t->hooks);
|
||||||
}
|
}
|
||||||
|
|
||||||
rte *
|
rte *
|
||||||
|
@ -97,8 +99,9 @@ rte_better(rte *new, rte *old)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
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 *new0 = new;
|
||||||
rte *old0 = old;
|
rte *old0 = old;
|
||||||
if (new)
|
if (new)
|
||||||
|
@ -132,39 +135,42 @@ do_rte_announce(struct proto *p, net *net, rte *new, rte *old, ea_list *tmpa)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
ASSERT(a->proto->core_state == FS_HAPPY);
|
||||||
if (p->rt_notify)
|
do_rte_announce(a, net, new, old, tmpa);
|
||||||
do_rte_announce(p, net, new, old, tmpa);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rt_feed_baby(struct proto *p)
|
rt_feed_baby(struct proto *p)
|
||||||
{
|
{
|
||||||
rtable *t = &master_table;
|
struct announce_hook *h;
|
||||||
|
|
||||||
if (!p->rt_notify)
|
if (!p->ahooks)
|
||||||
return;
|
return;
|
||||||
debug("Announcing routes to new protocol %s\n", p->name);
|
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;
|
rtable *t = h->table;
|
||||||
rte *e;
|
FIB_WALK(&t->fib, fn)
|
||||||
for(e=n->routes; e; e=e->next)
|
|
||||||
{
|
{
|
||||||
struct proto *q = e->attrs->proto;
|
net *n = (net *) fn;
|
||||||
ea_list *tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
rte *e;
|
||||||
do_rte_announce(p, n, e, NULL, tmpa);
|
for(e=n->routes; e; e=e->next)
|
||||||
lp_flush(rte_update_pool);
|
{
|
||||||
|
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
|
static inline int
|
||||||
|
@ -215,7 +221,7 @@ rte_free_quick(rte *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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_best = net->routes;
|
||||||
rte *old = NULL;
|
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 */
|
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;
|
new->next = net->routes;
|
||||||
net->routes = new;
|
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)
|
for(s=net->routes; s; s=s->next)
|
||||||
if (rte_better(s, r))
|
if (rte_better(s, r))
|
||||||
r = s;
|
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 */
|
if (r) /* Re-link the new optimal route */
|
||||||
{
|
{
|
||||||
k = &net->routes;
|
k = &net->routes;
|
||||||
|
@ -301,7 +307,7 @@ rte_update_unlock(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
ea_list *tmpa = NULL;
|
||||||
|
|
||||||
|
@ -324,7 +330,7 @@ rte_update(net *net, struct proto *p, rte *new)
|
||||||
new->attrs = rta_lookup(new->attrs);
|
new->attrs = rta_lookup(new->attrs);
|
||||||
new->flags |= REF_COW;
|
new->flags |= REF_COW;
|
||||||
}
|
}
|
||||||
rte_recalculate(net, p, new, tmpa);
|
rte_recalculate(table, net, p, new, tmpa);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -334,10 +340,10 @@ drop:
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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_update_lock();
|
||||||
rte_recalculate(old->net, old->attrs->proto, NULL, NULL);
|
rte_recalculate(t, old->net, old->attrs->proto, NULL, NULL);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +367,7 @@ rt_dump(rtable *t)
|
||||||
{
|
{
|
||||||
rte *e;
|
rte *e;
|
||||||
net *n;
|
net *n;
|
||||||
|
struct announce_hook *a;
|
||||||
|
|
||||||
debug("Dump of routing table <%s>\n", t->name);
|
debug("Dump of routing table <%s>\n", t->name);
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
|
@ -373,20 +380,27 @@ rt_dump(rtable *t)
|
||||||
rte_dump(e);
|
rte_dump(e);
|
||||||
}
|
}
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
|
WALK_LIST(a, t->hooks)
|
||||||
|
debug("\tAnnounces routes to protocol %s\n", a->proto->name);
|
||||||
debug("\n");
|
debug("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rt_dump_all(void)
|
rt_dump_all(void)
|
||||||
{
|
{
|
||||||
rt_dump(&master_table);
|
rtable *t;
|
||||||
|
|
||||||
|
WALK_LIST(t, routing_tables)
|
||||||
|
rt_dump(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rt_gc(void *unused)
|
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);
|
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_last_gc = now;
|
||||||
rt_gc_counter = 0;
|
rt_gc_counter = 0;
|
||||||
}
|
}
|
||||||
|
@ -397,11 +411,11 @@ rt_init(void)
|
||||||
rta_init();
|
rta_init();
|
||||||
rt_table_pool = rp_new(&root_pool, "Routing tables");
|
rt_table_pool = rp_new(&root_pool, "Routing tables");
|
||||||
rte_update_pool = lp_new(rt_table_pool, 4080);
|
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));
|
rte_slab = sl_new(rt_table_pool, sizeof(rte));
|
||||||
rt_last_gc = now;
|
rt_last_gc = now;
|
||||||
rt_gc_event = ev_new(rt_table_pool);
|
rt_gc_event = ev_new(rt_table_pool);
|
||||||
rt_gc_event->hook = rt_gc;
|
rt_gc_event->hook = rt_gc;
|
||||||
|
init_list(&routing_tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -422,7 +436,7 @@ again:
|
||||||
for (e=n->routes; e; e=e->next, rcnt++)
|
for (e=n->routes; e; e=e->next, rcnt++)
|
||||||
if (e->attrs->proto->core_state != FS_HAPPY)
|
if (e->attrs->proto->core_state != FS_HAPPY)
|
||||||
{
|
{
|
||||||
rte_discard(e);
|
rte_discard(tab, e);
|
||||||
rdel++;
|
rdel++;
|
||||||
goto rescan;
|
goto rescan;
|
||||||
}
|
}
|
||||||
|
@ -437,3 +451,39 @@ again:
|
||||||
FIB_ITERATE_END(f);
|
FIB_ITERATE_END(f);
|
||||||
DBG("Pruned %d of %d routes and %d of %d networks\n", rcnt, rdel, ncnt, ndel);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue