From c0adf7e9fc0bb920175a639c6f56ed7b4190f3e4 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 15 Mar 2012 11:58:08 +0100 Subject: 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. --- nest/rt-table.c | 82 ++++++++++++++++++++++----------------------------------- 1 file changed, 31 insertions(+), 51 deletions(-) (limited to 'nest/rt-table.c') 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; } } -- cgit v1.2.3