summaryrefslogtreecommitdiff
path: root/nest/rt-table.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2012-03-15 11:58:08 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2012-03-15 12:13:04 +0100
commitc0adf7e9fc0bb920175a639c6f56ed7b4190f3e4 (patch)
tree8bc6ac9e4c9288d7e7009a80a04d7278325ff05c /nest/rt-table.c
parent46c1a583a5c1ea81e8d8f372bd7f614506a63938 (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.c82
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;
}
}