summaryrefslogtreecommitdiffstats
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/protocol.h1
-rw-r--r--nest/route.h19
-rw-r--r--nest/rt-table.c143
3 files changed, 113 insertions, 50 deletions
diff --git a/nest/protocol.h b/nest/protocol.h
index 70999f0..e36219a 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -192,6 +192,7 @@ struct proto {
struct fib_iterator *feed_iterator; /* Routing table iterator used during protocol feeding */
struct announce_hook *feed_ahook; /* Announce hook we currently feed */
+ int feed_cast; /* Are we feeding unicast or multicast routes? */
/* Hic sunt protocol-specific data */
};
diff --git a/nest/route.h b/nest/route.h
index a849bf0..0634ab7 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -124,7 +124,8 @@ struct rtable_config {
typedef struct rtable {
node n; /* Node in list of all tables */
- struct fib fib;
+ struct fib fib_unicast;
+ struct fib fib_multicast;
char *name; /* Name of this table */
list hooks; /* List of announcement hooks */
int pipe_busy; /* Pipe loop detection */
@@ -140,8 +141,10 @@ typedef struct rtable {
bird_clock_t gc_time; /* Time of last GC */
byte gc_scheduled; /* GC is scheduled */
byte hcu_scheduled; /* Hostcache update is scheduled */
- byte nhu_state; /* Next Hop Update state */
- struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */
+ byte nhu_state_unicast; /* Next Hop Update state */
+ byte nhu_state_multicast; /* Next Hop Update state (multicast) */
+ struct fib_iterator nhu_fit_unicast; /* Next Hop Update FIB iterator */
+ struct fib_iterator nhu_fit_multicast; /* Next Hop Update FIB iterator (multicast) */
} rtable;
typedef struct network {
@@ -225,8 +228,6 @@ void rt_commit(struct config *new, struct config *old);
void rt_lock_table(rtable *);
void rt_unlock_table(rtable *);
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
-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(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
@@ -245,6 +246,7 @@ struct rtable_config *rt_new_table(struct symbol *s);
struct rt_show_data {
ip_addr prefix;
unsigned pxlen;
+ int cast;
rtable *table;
struct filter *filter;
int verbose;
@@ -316,6 +318,13 @@ typedef struct rta {
#define IGP_METRIC_UNKNOWN 0x80000000 /* Default igp_metric used when no other
protocol-specific metric is availabe */
+static inline struct fib *rt_fib(rtable *tab, int cast) { return (cast == RTC_MULTICAST) ? &tab->fib_multicast : &tab->fib_unicast; }
+static inline net *net_find2(rtable *tab, ip_addr addr, unsigned len, int cast) { return (net *) fib_find(rt_fib(tab, cast), &addr, len); }
+static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return net_find2(tab, addr, len, RTC_UNICAST); }
+static inline net *net_get2(rtable *tab, ip_addr addr, unsigned len, int cast) { return (net *) fib_get(rt_fib(tab, cast), &addr, len); }
+static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return net_get2(tab, addr, len, RTC_UNICAST); }
+
+
/*
* Extended Route Attributes
*/
diff --git a/nest/rt-table.c b/nest/rt-table.c
index a4976f0..5d17ca0 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -54,14 +54,14 @@ static void rt_format_via(rte *e, byte *via);
static void rt_free_hostcache(rtable *tab);
static void rt_notify_hostcache(rtable *tab, net *net);
static void rt_update_hostcache(rtable *tab);
-static void rt_next_hop_update(rtable *tab);
-static void rt_prune(rtable *tab);
+static void rt_next_hop_update(rtable *tab, int cast);
+static void rt_prune(rtable *tab, int cast);
static inline void rt_schedule_gc(rtable *tab);
/* Like fib_route(), but skips empty net entries */
static net *
-net_route(rtable *tab, ip_addr a, int len)
+net_route(rtable *tab, ip_addr a, int len, int cast)
{
ip_addr a0;
net *n;
@@ -69,7 +69,7 @@ net_route(rtable *tab, ip_addr a, int len)
while (len >= 0)
{
a0 = ipa_and(a, ipa_mkmask(len));
- n = fib_find(&tab->fib, &a0, len);
+ n = fib_find(rt_fib(tab, cast), &a0, len);
if (n && n->routes)
return n;
len--;
@@ -775,9 +775,17 @@ rt_dump(rtable *t)
debug("Dump of routing table <%s>\n", t->name);
#ifdef DEBUGGING
- fib_check(&t->fib);
+ fib_check(rt_fib(t, RTC_UNICAST));
+ fib_check(rt_fib(t, RTC_MULTICAST));
#endif
- FIB_WALK(&t->fib, fn)
+ FIB_WALK(rt_fib(t, RTC_UNICAST), fn)
+ {
+ n = (net *) fn;
+ for(e=n->routes; e; e=e->next)
+ rte_dump(e);
+ }
+ FIB_WALK_END;
+ FIB_WALK(rt_fib(t, RTC_MULTICAST), fn)
{
n = (net *) fn;
for(e=n->routes; e; e=e->next)
@@ -826,11 +834,12 @@ rt_schedule_hcu(rtable *tab)
static inline void
rt_schedule_nhu(rtable *tab)
{
- if (tab->nhu_state == 0)
+ if (tab->nhu_state_unicast == 0 || tab->nhu_state_multicast == 0)
ev_schedule(tab->rt_event);
/* state change 0->1, 2->3 */
- tab->nhu_state |= 1;
+ tab->nhu_state_unicast |= 1;
+ tab->nhu_state_multicast |= 1;
}
static void
@@ -841,18 +850,25 @@ rt_event(void *ptr)
if (tab->hcu_scheduled)
rt_update_hostcache(tab);
- if (tab->nhu_state)
- rt_next_hop_update(tab);
+ if (tab->nhu_state_unicast)
+ rt_next_hop_update(tab, RTC_UNICAST);
+
+ if (tab->nhu_state_multicast)
+ rt_next_hop_update(tab, RTC_MULTICAST);
if (tab->gc_scheduled)
- rt_prune(tab);
+ {
+ rt_prune(tab, RTC_UNICAST);
+ rt_prune(tab, RTC_MULTICAST);
+ }
}
void
rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{
bzero(t, sizeof(*t));
- fib_init(&t->fib, p, sizeof(net), 0, rte_init);
+ fib_init(&t->fib_unicast, p, sizeof(net), 0, rte_init);
+ fib_init(&t->fib_multicast, p, sizeof(net), 0, rte_init);
t->name = name;
t->config = cf;
init_list(&t->hooks);
@@ -890,18 +906,18 @@ rt_init(void)
* protocols and also stale network entries.
*/
static void
-rt_prune(rtable *tab)
+rt_prune(rtable *tab, int cast)
{
struct fib_iterator fit;
int rcnt = 0, rdel = 0, ncnt = 0, ndel = 0;
- DBG("Pruning route table %s\n", tab->name);
+ DBG("Pruning route table %s%s\n", tab->name, (cast == RTC_MULTICAST) ? ", multicast" : "");
#ifdef DEBUGGING
- fib_check(&tab->fib);
+ fib_check(rt_fib(tab, cast));
#endif
- FIB_ITERATE_INIT(&fit, &tab->fib);
+ FIB_ITERATE_INIT(&fit, rt_fib(tab, cast));
again:
- FIB_ITERATE_START(&tab->fib, &fit, f)
+ FIB_ITERATE_START(rt_fib(tab, cast), &fit, f)
{
net *n = (net *) f;
rte *e;
@@ -918,7 +934,7 @@ again:
if (!n->routes) /* Orphaned FIB entry? */
{
FIB_ITERATE_PUT(&fit, f);
- fib_delete(&tab->fib, f);
+ fib_delete(rt_fib(tab, cast), f);
ndel++;
goto again;
}
@@ -926,7 +942,7 @@ again:
FIB_ITERATE_END(f);
DBG("Pruned %d of %d routes and %d of %d networks\n", rdel, rcnt, ndel, ncnt);
#ifdef DEBUGGING
- fib_check(&tab->fib);
+ fib_check(rt_fib(tab, cast));
#endif
tab->gc_counter = 0;
tab->gc_time = now;
@@ -944,7 +960,10 @@ rt_prune_all(void)
rtable *t;
WALK_LIST(t, routing_tables)
- rt_prune(t);
+ {
+ rt_prune(t, RTC_UNICAST);
+ rt_prune(t, RTC_MULTICAST);
+ }
}
void
@@ -1061,21 +1080,23 @@ rt_next_hop_update_net(rtable *tab, net *n)
}
static void
-rt_next_hop_update(rtable *tab)
+rt_next_hop_update(rtable *tab, int cast)
{
- struct fib_iterator *fit = &tab->nhu_fit;
+ struct fib *fib = rt_fib(tab, cast);
+ struct fib_iterator *fit = (cast == RTC_MULTICAST) ? &tab->nhu_fit_multicast : &tab->nhu_fit_unicast;
+ byte *state = (cast == RTC_MULTICAST) ? &tab->nhu_state_multicast : &tab->nhu_state_unicast;
int max_feed = 32;
- if (tab->nhu_state == 0)
+ if (*state == 0)
return;
- if (tab->nhu_state == 1)
+ if (*state == 1)
{
- FIB_ITERATE_INIT(fit, &tab->fib);
- tab->nhu_state = 2;
+ FIB_ITERATE_INIT(fit, fib);
+ *state = 2;
}
- FIB_ITERATE_START(&tab->fib, fit, fn)
+ FIB_ITERATE_START(fib, fit, fn)
{
if (max_feed <= 0)
{
@@ -1088,9 +1109,9 @@ rt_next_hop_update(rtable *tab)
FIB_ITERATE_END(fn);
/* state change 2->0, 3->1 */
- tab->nhu_state &= 1;
+ *state &= 1;
- if (tab->nhu_state > 0)
+ if (*state > 0)
ev_schedule(tab->rt_event);
}
@@ -1140,7 +1161,8 @@ rt_unlock_table(rtable *r)
if (r->hostcache)
rt_free_hostcache(r);
rem_node(&r->n);
- fib_free(&r->fib);
+ fib_free(&r->fib_multicast);
+ fib_free(&r->fib_unicast);
rfree(r->rt_event);
mb_free(r);
config_del_obstacle(conf);
@@ -1240,13 +1262,14 @@ rt_feed_baby(struct proto *p)
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));
+ p->feed_cast = RTC_UNICAST;
goto next_hook;
}
fit = p->feed_iterator;
again:
h = p->feed_ahook;
- FIB_ITERATE_START(&h->table->fib, fit, fn)
+ FIB_ITERATE_START(rt_fib(h->table, p->feed_cast), fit, fn)
{
net *n = (net *) fn;
rte *e = n->routes;
@@ -1275,7 +1298,18 @@ again:
}
}
FIB_ITERATE_END(fn);
- p->feed_ahook = h->next;
+
+
+ if (p->feed_cast == RTC_UNICAST) /* If we were feeding unicast routes, proceed with multicast */
+ {
+ p->feed_cast = RTC_MULTICAST;
+ }
+ else /* Otherwise, continue with next hook */
+ {
+ p->feed_cast = RTC_UNICAST;
+ p->feed_ahook = h->next;
+ }
+
if (!p->feed_ahook)
{
mb_free(p->feed_iterator);
@@ -1285,7 +1319,7 @@ again:
next_hook:
h = p->feed_ahook;
- FIB_ITERATE_INIT(fit, &h->table->fib);
+ FIB_ITERATE_INIT(fit, rt_fib(h->table, p->feed_cast));
goto again;
}
@@ -1303,7 +1337,7 @@ 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);
+ fit_get(rt_fib(p->feed_ahook->table, p->feed_cast), p->feed_iterator);
p->feed_ahook = NULL;
}
}
@@ -1503,7 +1537,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
u32 old_metric = he->igp_metric;
int pxlen = 0;
- net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
+ net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH, RTC_UNICAST);
if (n)
{
rta *a = n->routes->attrs;
@@ -1641,6 +1675,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
rta *a = e->attrs;
int primary = (e->net->routes == e);
+ int multicast = (a->cast == RTC_MULTICAST);
rt_format_via(e, via);
tm_format_datetime(tm, &config->tf_route, e->lastmod);
@@ -1661,8 +1696,8 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
a->proto->proto->get_route_info(e, info, tmpa);
else
bsprintf(info, " (%d)", e->pref);
- cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
- tm, from, primary ? " *" : "", info);
+ cli_printf(c, -1007, "%-18s %s%s [%s %s%s]%s%s", ia, via, multicast ? " MC" : "",
+ a->proto->name, tm, from, primary ? " *" : "", info);
if (d->verbose)
rta_show(c, a, tmpa);
}
@@ -1730,7 +1765,7 @@ rt_show_cont(struct cli *c)
#else
unsigned max = 64;
#endif
- struct fib *fib = &d->table->fib;
+ struct fib *fib = rt_fib(d->table, d->cast);
struct fib_iterator *it = &d->fit;
FIB_ITERATE_START(fib, it, f)
@@ -1756,6 +1791,14 @@ rt_show_cont(struct cli *c)
rt_show_net(c, n, d);
}
FIB_ITERATE_END(f);
+
+ if (d->cast == RTC_UNICAST)
+ {
+ FIB_ITERATE_INIT(&d->fit, rt_fib(d->table, RTC_MULTICAST));
+ d->cast = RTC_MULTICAST;
+ return;
+ }
+
if (d->stats)
cli_printf(c, 14, "%d of %d routes for %d networks", d->show_counter, d->rt_counter, d->net_counter);
else
@@ -1770,30 +1813,40 @@ rt_show_cleanup(struct cli *c)
struct rt_show_data *d = c->rover;
/* Unlink the iterator */
- fit_get(&d->table->fib, &d->fit);
+ fit_get(rt_fib(d->table, d->cast), &d->fit);
}
void
rt_show(struct rt_show_data *d)
{
- net *n;
+ net *n, *n2;
if (d->pxlen == 256)
{
- FIB_ITERATE_INIT(&d->fit, &d->table->fib);
+ FIB_ITERATE_INIT(&d->fit, rt_fib(d->table, RTC_UNICAST));
this_cli->cont = rt_show_cont;
this_cli->cleanup = rt_show_cleanup;
this_cli->rover = d;
+ d->cast = RTC_UNICAST;
}
else
{
if (d->show_for)
- n = net_route(d->table, d->prefix, d->pxlen);
+ {
+ n = net_route(d->table, d->prefix, d->pxlen, RTC_UNICAST);
+ n2 = net_route(d->table, d->prefix, d->pxlen, RTC_MULTICAST);
+ }
else
- n = net_find(d->table, d->prefix, d->pxlen);
- if (n)
+ {
+ n = net_find2(d->table, d->prefix, d->pxlen, RTC_UNICAST);
+ n2 = net_find2(d->table, d->prefix, d->pxlen, RTC_MULTICAST);
+ }
+ if (n || n2)
{
- rt_show_net(this_cli, n, d);
+ if (n)
+ rt_show_net(this_cli, n, d);
+ if (n2)
+ rt_show_net(this_cli, n2, d);
cli_msg(0, "");
}
else