diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2010-11-14 05:49:56 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2010-11-14 05:49:56 +0100 |
commit | 2ef9177a47e7137dd09b06a353a6e5f6e671c951 (patch) | |
tree | 3fb8f3e25eec4dd513cb87399caf7c0e6ff5f955 /nest | |
parent | 9d35f8c51f1062ddd8e2f41cf535d8a8d69ec6be (diff) | |
download | bird-2ef9177a47e7137dd09b06a353a6e5f6e671c951.tar bird-2ef9177a47e7137dd09b06a353a6e5f6e671c951.zip |
Add multicast support to static protocol and generic route handling.
Diffstat (limited to 'nest')
-rw-r--r-- | nest/protocol.h | 1 | ||||
-rw-r--r-- | nest/route.h | 19 | ||||
-rw-r--r-- | nest/rt-table.c | 143 |
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 |