diff options
Diffstat (limited to 'nest')
-rw-r--r-- | nest/protocol.h | 24 | ||||
-rw-r--r-- | nest/route.h | 13 | ||||
-rw-r--r-- | nest/rt-attr.c | 60 | ||||
-rw-r--r-- | nest/rt-show.c | 34 | ||||
-rw-r--r-- | nest/rt-table.c | 97 |
5 files changed, 110 insertions, 118 deletions
diff --git a/nest/protocol.h b/nest/protocol.h index d790e90e..dd942c10 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -77,7 +77,7 @@ struct protocol { int (*shutdown)(struct proto *); /* Stop the instance */ void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */ void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ - void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */ + void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */ void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */ void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */ @@ -191,7 +191,7 @@ struct proto { * rt_notify Notify protocol about routing table updates. * neigh_notify Notify protocol about neighbor cache events. * make_tmp_attrs Construct ea_list from private attrs stored in rte. - * store_tmp_attrs Store private attrs back to the rte. + * store_tmp_attrs Store private attrs back to rta. The route MUST NOT be cached. * import_control Called as the first step of the route importing process. * It can construct a new rte, add private attributes and * decide whether the route shall be imported: 1=yes, -1=no, @@ -205,11 +205,11 @@ struct proto { void (*if_notify)(struct proto *, unsigned flags, struct iface *i); void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); - void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs); + void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old); void (*neigh_notify)(struct neighbor *neigh); struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool); - void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs); - int (*import_control)(struct proto *, struct rte **rt, struct ea_list **attrs, struct linpool *pool); + void (*store_tmp_attrs)(struct rte *rt); + int (*import_control)(struct proto *, struct rte **rt, struct linpool *pool); void (*reload_routes)(struct channel *); void (*feed_begin)(struct channel *, int initial); void (*feed_end)(struct channel *); @@ -292,12 +292,16 @@ proto_get_router_id(struct proto_config *pc) return pc->router_id ? pc->router_id : pc->global->router_id; } -static inline struct ea_list * -rte_make_tmp_attrs(struct rte *rt, struct linpool *pool) +static inline void +rte_make_tmp_attrs(struct rte **rt, struct linpool *pool) { struct ea_list *(*mta)(struct rte *rt, struct linpool *pool); - mta = rt->attrs->src->proto->make_tmp_attrs; - return mta ? mta(rt, pool) : NULL; + mta = (*rt)->attrs->src->proto->make_tmp_attrs; + if (!mta) return; + *rt = rte_cow_rta(*rt, pool); + struct ea_list *ea = mta(*rt, pool); + ea->next = (*rt)->attrs->eattrs; + (*rt)->attrs->eattrs = ea; } /* Moved from route.h to avoid dependency conflicts */ @@ -466,7 +470,7 @@ struct channel_class { void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */ void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ - void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */ + void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */ int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */ void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */ diff --git a/nest/route.h b/nest/route.h index 1391b357..cad15440 100644 --- a/nest/route.h +++ b/nest/route.h @@ -294,7 +294,7 @@ rte *rte_get_temp(struct rta *); void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); /* rte_update() moved to protocol.h to avoid dependency conflicts */ int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); -rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent); +rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent); void rt_refresh_begin(rtable *t, struct channel *c); void rt_refresh_end(rtable *t, struct channel *c); void rt_schedule_prune(rtable *t); @@ -546,6 +546,15 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */ ea_list *ea_append(ea_list *to, ea_list *what); void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max); +#define ea_normalize(ea) do { \ + if (ea->next) { \ + ea_list *t = alloca(ea_scan(ea)); \ + ea_merge(ea, t); \ + ea = t; \ + } \ + ea_sort(ea); \ +} while(0) \ + static inline eattr * ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val) { @@ -611,7 +620,7 @@ rta *rta_do_cow(rta *o, linpool *lp); static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; } void rta_dump(rta *); void rta_dump_all(void); -void rta_show(struct cli *, rta *, ea_list *); +void rta_show(struct cli *, rta *); struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep); void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls); diff --git a/nest/rt-attr.c b/nest/rt-attr.c index f92efc2e..73ca4748 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -550,29 +550,47 @@ ea_do_sort(ea_list *e) while (ss); } +/** + * In place discard duplicates, undefs and temporary attributes in sorted + * ea_list. We use stable sort for this reason. + **/ static inline void ea_do_prune(ea_list *e) { eattr *s, *d, *l, *s0; int i = 0; - /* Discard duplicates and undefs. Do you remember sorting was stable? */ - s = d = e->attrs; - l = e->attrs + e->count; + s = d = e->attrs; /* Beginning of the list. @s is source, @d is destination. */ + l = e->attrs + e->count; /* End of the list */ + + /* Walk from begin to end. */ while (s < l) { s0 = s++; + /* Find a consecutive block of the same attribute */ while (s < l && s->id == s[-1].id) s++; - /* s0 is the most recent version, s[-1] the oldest one */ - if ((s0->type & EAF_TYPE_MASK) != EAF_TYPE_UNDEF) - { - *d = *s0; - d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED); - d++; - i++; - } + + /* Now s0 is the most recent version, s[-1] the oldest one */ + /* Drop undefs */ + if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + continue; + + /* Drop temporary attributes */ + if (s0->type & EAF_TEMP) + continue; + + /* Copy the newest version to destination */ + *d = *s0; + + /* Preserve info whether it originated locally */ + d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED); + + /* Next destination */ + d++; + i++; } + e->count = i; } @@ -1128,15 +1146,7 @@ rta_lookup(rta *o) ASSERT(!(o->aflags & RTAF_CACHED)); if (o->eattrs) - { - if (o->eattrs->next) /* Multiple ea_list's, need to merge them */ - { - ea_list *ml = alloca(ea_scan(o->eattrs)); - ea_merge(o->eattrs, ml); - o->eattrs = ml; - } - ea_sort(o->eattrs); - } + ea_normalize(o->eattrs); h = rta_hash(o); for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next) @@ -1250,17 +1260,15 @@ rta_dump_all(void) } void -rta_show(struct cli *c, rta *a, ea_list *eal) +rta_show(struct cli *c, rta *a) { static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect", "RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" }; - int i; cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope)); - if (!eal) - eal = a->eattrs; - for(; eal; eal=eal->next) - for(i=0; i<eal->count; i++) + + for(ea_list *eal = a->eattrs; eal; eal=eal->next) + for(int i=0; i<eal->count; i++) ea_show(c, &eal->attrs[i]); } diff --git a/nest/rt-show.c b/nest/rt-show.c index 1f1b73d2..90165c57 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -29,14 +29,14 @@ rt_show_table(struct cli *c, struct rt_show_data *d) } static void -rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa) +rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d) { byte from[IPA_MAX_TEXT_LENGTH+8]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; rta *a = e->attrs; int primary = (e->net->routes == e); int sync_error = (e->net->n.flags & KRF_SYNC_ERROR); - void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); + void (*get_route_info)(struct rte *, byte *buf); struct nexthop *nh; tm_format_time(tm, &config->tf_route, e->lastmod); @@ -46,17 +46,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm from[0] = 0; get_route_info = a->src->proto->proto->get_route_info; - if (get_route_info || d->verbose) - { - /* Need to normalize the extended attributes */ - ea_list *t = tmpa; - t = ea_append(t, a->eattrs); - tmpa = alloca(ea_scan(t)); - ea_merge(t, tmpa); - ea_sort(tmpa); - } + /* Need to normalize the extended attributes */ + if ((get_route_info || d->verbose) && !rta_is_cached(a)) + ea_normalize(a->eattrs); if (get_route_info) - get_route_info(e, info, tmpa); + get_route_info(e, info); else bsprintf(info, " (%d)", e->pref); @@ -93,7 +87,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm } if (d->verbose) - rta_show(c, a, tmpa); + rta_show(c, a); } static void @@ -101,7 +95,6 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) { rte *e, *ee; byte ia[NET_MAX_TEXT_LENGTH+1]; - struct ea_list *tmpa; struct channel *ec = d->tab->export_channel; int first = 1; int pass = 0; @@ -121,7 +114,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) continue; ee = e; - tmpa = rte_make_tmp_attrs(e, c->show_pool); + rte_make_tmp_attrs(&e, c->show_pool); /* Export channel is down, do not try to export routes to it */ if (ec && (ec->export_state == ES_DOWN)) @@ -131,7 +124,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED)) { rte *rt_free; - e = rt_export_merged(ec, n, &rt_free, &tmpa, c->show_pool, 1); + e = rt_export_merged(ec, n, &rt_free, c->show_pool, 1); pass = 1; if (!e) @@ -140,7 +133,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) else if (d->export_mode) { struct proto *ep = ec->proto; - int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, c->show_pool) : 0; + int ic = ep->import_control ? ep->import_control(ep, &e, c->show_pool) : 0; if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED) pass = 1; @@ -156,8 +149,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) * command may change the export filter and do not update routes. */ int do_export = (ic > 0) || - (f_run(ec->out_filter, &e, &tmpa, c->show_pool, - FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT); + (f_run(ec->out_filter, &e, c->show_pool, FF_SILENT) <= F_ACCEPT); if (do_export != (d->export_mode == RSEM_EXPORT)) goto skip; @@ -170,11 +162,11 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) if (d->show_protocol && (d->show_protocol != e->attrs->src->proto)) goto skip; - if (f_run(d->filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) > F_ACCEPT) + if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT) goto skip; if (d->stats < 2) - rt_show_rte(c, ia, e, d, tmpa); + rt_show_rte(c, ia, e, d); d->show_counter++; ia[0] = 0; diff --git a/nest/rt-table.c b/nest/rt-table.c index b885c6e3..de7b05fc 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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) |