diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2012-03-15 11:58:08 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2012-03-15 12:13:04 +0100 |
commit | c0adf7e9fc0bb920175a639c6f56ed7b4190f3e4 (patch) | |
tree | 8bc6ac9e4c9288d7e7009a80a04d7278325ff05c /nest/rt-table.c | |
parent | 46c1a583a5c1ea81e8d8f372bd7f614506a63938 (diff) |
Better support for multitable protocols.
The nest-protocol interaction is changed to better handle multitable
protocols. Multitable protocols now declare that by 'multitable' field,
which tells nest that a protocol handles things related to proto-rtable
interaction (table locking, announce hook adding, reconfiguration of
filters) itself.
Filters and stats are moved to announce hooks, a protocol could have
different filters and stats to different tables.
The patch is based on one from Alexander V. Chernikov, thanks.
Diffstat (limited to 'nest/rt-table.c')
-rw-r--r-- | nest/rt-table.c | 82 |
1 files changed, 31 insertions, 51 deletions
diff --git a/nest/rt-table.c b/nest/rt-table.c index 377687de..3807ef8d 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -184,24 +184,16 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg) } static inline void -do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed) +do_rte_announce(struct announce_hook *ah, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed) { - struct proto *p = a->proto; - struct filter *filter = p->out_filter; - struct proto_stats *stats = &p->stats; + struct proto *p = ah->proto; + struct filter *filter = ah->out_filter; + struct proto_stats *stats = ah->stats; + rte *new0 = new; rte *old0 = old; int ok; -#ifdef CONFIG_PIPE - /* The secondary direction of the pipe */ - if (proto_is_pipe(p) && (p->table != a->table)) - { - filter = p->in_filter; - stats = pipe_get_peer_stats(p); - } -#endif - if (new) { stats->exp_updates_received++; @@ -294,18 +286,18 @@ do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rt rte_trace_out(D_ROUTES, p, old, "removed"); } if (!new) - p->rt_notify(p, a->table, net, NULL, old, NULL); + p->rt_notify(p, ah->table, net, NULL, old, NULL); else if (tmpa) { ea_list *t = tmpa; while (t->next) t = t->next; t->next = new->attrs->eattrs; - p->rt_notify(p, a->table, net, new, old, tmpa); + p->rt_notify(p, ah->table, net, new, old, tmpa); t->next = NULL; } else - p->rt_notify(p, a->table, net, new, old, new->attrs->eattrs); + p->rt_notify(p, ah->table, net, new, old, new->attrs->eattrs); if (new && new != new0) /* Discard temporary rte's */ rte_free(new); if (old && old != old0) @@ -375,7 +367,7 @@ rte_validate(rte *e) if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen)) { log(L_WARN "Ignoring bogus prefix %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->name); + n->n.prefix, n->n.pxlen, e->sender->proto->name); return 0; } @@ -383,7 +375,7 @@ rte_validate(rte *e) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) { log(L_WARN "Ignoring bogus route %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->name); + n->n.prefix, n->n.pxlen, e->sender->proto->name); return 0; } @@ -423,18 +415,15 @@ rte_same(rte *x, rte *y) } static void -rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte *new, ea_list *tmpa) +rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, struct proto *src) { - struct proto_stats *stats = &p->stats; + struct proto *p = ah->proto; + struct rtable *table = ah->table; + struct proto_stats *stats = ah->stats; rte *old_best = net->routes; rte *old = NULL; rte **k, *r, *s; -#ifdef CONFIG_PIPE - if (proto_is_pipe(p) && (p->table == table)) - stats = pipe_get_peer_stats(p); -#endif - k = &net->routes; /* Find and remove original route from the same protocol */ while (old = *k) { @@ -449,7 +438,7 @@ rte_recalculate(rtable *table, net *net, struct proto *p, struct proto *src, rte * ignore it completely (there might be 'spurious withdraws', * see FIXME in do_rte_announce()) */ - if (old->sender != p) + if (old->sender->proto != p) { if (new) { @@ -613,6 +602,7 @@ rte_update_unlock(void) /** * rte_update - enter a new update to a routing table * @table: table to be updated + * @ah: pointer to table announce hook * @net: network node * @p: protocol submitting the update * @src: protocol originating the update @@ -652,28 +642,17 @@ rte_update_unlock(void) */ void -rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new) +rte_update2(struct announce_hook *ah, net *net, rte *new, struct proto *src) { + struct proto *p = ah->proto; + struct proto_stats *stats = ah->stats; + struct filter *filter = ah->in_filter; ea_list *tmpa = NULL; - struct proto_stats *stats = &p->stats; - -#ifdef CONFIG_PIPE - if (proto_is_pipe(p) && (p->table == table)) - stats = pipe_get_peer_stats(p); -#endif rte_update_lock(); if (new) { - new->sender = p; - struct filter *filter = p->in_filter; - - /* Do not filter routes going through the pipe, - they are filtered in the export filter only. */ -#ifdef CONFIG_PIPE - if (proto_is_pipe(p)) - filter = FILTER_ACCEPT; -#endif + new->sender = ah; stats->imp_updates_received++; if (!rte_validate(new)) @@ -710,13 +689,13 @@ rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new else stats->imp_withdraws_received++; - rte_recalculate(table, net, p, src, new, tmpa); + rte_recalculate(ah, net, new, tmpa, src); rte_update_unlock(); return; drop: rte_free(new); - rte_recalculate(table, net, p, src, NULL, NULL); + rte_recalculate(ah, net, NULL, NULL, src); rte_update_unlock(); } @@ -739,7 +718,7 @@ void rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during garbage collection */ { rte_update_lock(); - rte_recalculate(t, old->net, old->sender, old->attrs->proto, NULL, NULL); + rte_recalculate(old->sender, old->net, NULL, NULL, old->attrs->proto); rte_update_unlock(); } @@ -912,8 +891,8 @@ again: ncnt++; rescan: for (e=n->routes; e; e=e->next, rcnt++) - if (e->sender->core_state != FS_HAPPY && - e->sender->core_state != FS_FEEDING) + if (e->sender->proto->core_state != FS_HAPPY && + e->sender->proto->core_state != FS_FEEDING) { rte_discard(tab, e); rdel++; @@ -1026,7 +1005,7 @@ rt_next_hop_update_net(rtable *tab, net *n) *k = new; rte_announce_i(tab, RA_ANY, n, new, e); - rte_trace_in(D_ROUTES, new->sender, new, "updated"); + rte_trace_in(D_ROUTES, new->sender->proto, new, "updated"); /* Call a pre-comparison hook */ /* Not really an efficient way to compute this */ @@ -1066,7 +1045,7 @@ rt_next_hop_update_net(rtable *tab, net *n) if (new != old_best) { rte_announce_i(tab, RA_OPTIMAL, n, new, old_best); - rte_trace_in(D_ROUTES, new->sender, new, "updated [best]"); + rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]"); } if (free_old_best) @@ -1693,6 +1672,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) { rte *e, *ee; byte ia[STD_ADDRESS_P_LENGTH+8]; + struct announce_hook *a; int ok; bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); @@ -1722,8 +1702,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) 'configure soft' command may change the export filter and do not update routes */ - if ((p1->out_filter == FILTER_REJECT) || - (p1->out_filter && f_run(p1->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)) + if ((a = proto_find_announce_hook(p1, d->table)) && ((a->out_filter == FILTER_REJECT) || + (a->out_filter && f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))) ok = 0; } } |