1
0
mirror of https://gitlab.labs.nic.cz/labs/bird.git synced 2024-05-11 16:54:54 +00:00

Nest: Removing separate tmpa from route propagation

This is a fundamental change of an original (1999) concept of route
processing inside BIRD. During import/export, there was a temporary
ea_list created which was to be used instead of the another one inside
the route itself.

This led to some confusion, quirks, and strange filter code that handled
extended route attributes. Dropping it now.

The protocol interface has changed in an uniform way -- the
`struct ea_list *attrs` argument has been removed from store_tmp_attrs(),
import_control(), rt_notify() and get_route_info().
This commit is contained in:
Jan Maria Matejka
2018-05-29 12:08:12 +02:00
parent ee7e2ffd26
commit 13c0be19d3
24 changed files with 220 additions and 242 deletions

View File

@@ -317,11 +317,11 @@ rte_cow_rta(rte *r, linpool *lp)
if (!rta_is_cached(r->attrs))
return r;
rte *e = rte_cow(r);
r = rte_cow(r);
rta *a = rta_do_cow(r->attrs, lp);
rta_free(e->attrs);
e->attrs = a;
return e;
rta_free(r->attrs);
r->attrs = a;
return r;
}
static int /* Actually better or at least as good as */
@@ -393,24 +393,20 @@ rte_trace_out(uint flag, struct proto *p, rte *e, char *msg)
}
static rte *
export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent)
{
struct proto *p = c->proto;
struct filter *filter = c->out_filter;
struct proto_stats *stats = &c->stats;
ea_list *tmpb = NULL;
rte *rt;
int v;
rt = rt0;
*rt_free = NULL;
if (!tmpa)
tmpa = &tmpb;
rte_make_tmp_attrs(&rt, pool);
*tmpa = rte_make_tmp_attrs(rt, pool);
v = p->import_control ? p->import_control(p, &rt, tmpa, pool) : 0;
v = p->import_control ? p->import_control(p, &rt, pool) : 0;
if (v < 0)
{
if (silent)
@@ -429,8 +425,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
}
v = filter && ((filter == FILTER_REJECT) ||
(f_run(filter, &rt, tmpa, pool,
FF_FORCE_TMPATTR | (silent ? FF_SILENT : 0)) > F_ACCEPT));
(f_run(filter, &rt, pool,
(silent ? FF_SILENT : 0)) > F_ACCEPT));
if (v)
{
if (silent)
@@ -454,13 +450,13 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
}
static inline rte *
export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int silent)
export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
{
return export_filter_(c, rt0, rt_free, tmpa, rte_update_pool, silent);
return export_filter_(c, rt0, rt_free, rte_update_pool, silent);
}
static void
do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed)
{
struct proto *p = c->proto;
struct proto_stats *stats = &c->stats;
@@ -533,19 +529,7 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int
else if (old)
rte_trace_out(D_ROUTES, p, old, "removed");
}
if (!new)
p->rt_notify(p, c, 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, c, net, new, old, tmpa);
t->next = NULL;
}
else
p->rt_notify(p, c, net, new, old, new->attrs->eattrs);
p->rt_notify(p, c, net, new, old);
}
static void
@@ -557,7 +541,6 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
rte *old = old0;
rte *new_free = NULL;
rte *old_free = NULL;
ea_list *tmpa = NULL;
if (new)
c->stats.exp_updates_received++;
@@ -585,10 +568,10 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
*/
if (new)
new = export_filter(c, new, &new_free, &tmpa, 0);
new = export_filter(c, new, &new_free, 0);
if (old && !refeed)
old = export_filter(c, old, &old_free, NULL, 1);
old = export_filter(c, old, &old_free, 1);
if (!new && !old)
{
@@ -605,13 +588,13 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
#ifdef CONFIG_PIPE
if ((p->proto == &proto_pipe) && !new0 && (p != old0->sender->proto))
p->rt_notify(p, c, net, NULL, old0, NULL);
p->rt_notify(p, c, net, NULL, old0);
#endif
return;
}
do_rt_notify(c, net, new, old, tmpa, refeed);
do_rt_notify(c, net, new, old, refeed);
/* Discard temporary rte's */
if (new_free)
@@ -630,7 +613,6 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
rte *old_best = NULL;
rte *new_free = NULL;
rte *old_free = NULL;
ea_list *tmpa = NULL;
/* Used to track whether we met old_changed position. If before_old is NULL
old_changed was the first and we met it implicitly before current best route. */
@@ -648,7 +630,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* First, find the new_best route - first accepted by filters */
for (r=net->routes; rte_is_valid(r); r=r->next)
{
if (new_best = export_filter(c, r, &new_free, &tmpa, 0))
if (new_best = export_filter(c, r, &new_free, 0))
break;
/* Note if we walked around the position of old_changed route */
@@ -699,7 +681,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* First case */
if (old_meet)
if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
if (old_best = export_filter(c, old_changed, &old_free, 1))
goto found;
/* Second case */
@@ -717,18 +699,18 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
/* Fourth case */
for (r=r->next; rte_is_valid(r); r=r->next)
{
if (old_best = export_filter(c, r, &old_free, NULL, 1))
if (old_best = export_filter(c, r, &old_free, 1))
goto found;
if (r == before_old)
if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
if (old_best = export_filter(c, old_changed, &old_free, 1))
goto found;
}
/* Implicitly, old_best is NULL and new_best is non-NULL */
found:
do_rt_notify(c, net, new_best, old_best, tmpa, (feed == 2));
do_rt_notify(c, net, new_best, old_best, (feed == 2));
/* Discard temporary rte's */
if (new_free)
@@ -745,7 +727,7 @@ nexthop_merge_rta(struct nexthop *nhs, rta *a, linpool *pool, int max)
}
rte *
rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent)
{
// struct proto *p = c->proto;
struct nexthop *nhs = NULL;
@@ -757,7 +739,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
if (!rte_is_valid(best0))
return NULL;
best = export_filter_(c, best0, rt_free, tmpa, pool, silent);
best = export_filter_(c, best0, rt_free, pool, silent);
if (!best || !rte_is_reachable(best))
return best;
@@ -767,7 +749,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
if (!rte_mergable(best0, rt0))
continue;
rt = export_filter_(c, rt0, &tmp, NULL, pool, 1);
rt = export_filter_(c, rt0, &tmp, pool, 1);
if (!rt)
continue;
@@ -807,7 +789,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
rte *old_best_free = NULL;
rte *new_changed_free = NULL;
rte *old_changed_free = NULL;
ea_list *tmpa = NULL;
/* We assume that all rte arguments are either NULL or rte_is_valid() */
@@ -819,10 +800,10 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
if ((new_best == old_best) && !refeed)
{
new_changed = rte_mergable(new_best, new_changed) ?
export_filter(c, new_changed, &new_changed_free, NULL, 1) : NULL;
export_filter(c, new_changed, &new_changed_free, 1) : NULL;
old_changed = rte_mergable(old_best, old_changed) ?
export_filter(c, old_changed, &old_changed_free, NULL, 1) : NULL;
export_filter(c, old_changed, &old_changed_free, 1) : NULL;
if (!new_changed && !old_changed)
return;
@@ -835,15 +816,15 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
/* Prepare new merged route */
if (new_best)
new_best = rt_export_merged(c, net, &new_best_free, &tmpa, rte_update_pool, 0);
new_best = rt_export_merged(c, net, &new_best_free, rte_update_pool, 0);
/* Prepare old merged route (without proper merged next hops) */
/* There are some issues with running filter on old route - see rt_notify_basic() */
if (old_best && !refeed)
old_best = export_filter(c, old_best, &old_best_free, NULL, 1);
old_best = export_filter(c, old_best, &old_best_free, 1);
if (new_best || old_best)
do_rt_notify(c, net, new_best, old_best, tmpa, refeed);
do_rt_notify(c, net, new_best, old_best, refeed);
/* Discard temporary rte's */
if (new_best_free)
@@ -1341,7 +1322,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
struct proto *p = c->proto;
struct proto_stats *stats = &c->stats;
struct filter *filter = c->in_filter;
ea_list *tmpa = NULL;
rte *dummy = NULL;
net *nn;
@@ -1379,11 +1359,11 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
}
else
{
tmpa = rte_make_tmp_attrs(new, rte_update_pool);
rte_make_tmp_attrs(&new, rte_update_pool);
if (filter && (filter != FILTER_REJECT))
{
ea_list *old_tmpa = tmpa;
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
ea_list *oldea = new->attrs->eattrs;
int fr = f_run(filter, &new, rte_update_pool, 0);
if (fr > F_ACCEPT)
{
stats->imp_updates_filtered++;
@@ -1394,8 +1374,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
new->flags |= REF_FILTERED;
}
if (tmpa != old_tmpa && src->proto->store_tmp_attrs)
src->proto->store_tmp_attrs(new, tmpa);
if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs)
src->proto->store_tmp_attrs(new);
}
}
if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
@@ -1459,11 +1439,10 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
rte_update_lock();
/* Rest is stripped down export_filter() */
ea_list *tmpa = rte_make_tmp_attrs(rt, rte_update_pool);
int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0;
rte_make_tmp_attrs(&rt, rte_update_pool);
int v = p->import_control ? p->import_control(p, &rt, rte_update_pool) : 0;
if (v == RIC_PROCESS)
v = (f_run(filter, &rt, &tmpa, rte_update_pool,
FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
/* Discard temporary rte */
if (rt != n->routes)