diff --git a/filter/filter.c b/filter/filter.c index 6381550e..6290e74a 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -538,14 +538,23 @@ val_format(struct f_val v, buffer *buf) static struct rte **f_rte; static struct rta *f_old_rta; -static struct ea_list **f_tmp_attrs; +static struct ea_list **f_eattrs; static struct linpool *f_pool; static struct buffer f_buf; static int f_flags; +static inline void f_cache_eattrs(void) +{ + f_eattrs = &((*f_rte)->attrs->eattrs); +} + static inline void f_rte_cow(void) { - *f_rte = rte_cow(*f_rte); + if (!((*f_rte)->flags & REF_COW)) + return; + + *f_rte = rte_do_cow(*f_rte); + f_eattrs = NULL; } /* @@ -570,6 +579,9 @@ f_rta_cow(void) * suppose hostentry is not changed by filters). */ (*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool); + + /* Re-cache the ea_list */ + f_cache_eattrs(); } static char * @@ -603,7 +615,10 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; return val; #define ACCESS_RTE \ - do { if (!f_rte) runtime("No route to access"); } while (0) + do { if (!f_rte) runtime("No route to access"); else f_cache_eattrs(); } while (0) + +#define ACCESS_EATTRS \ + do { if (!f_eattrs) f_cache_eattrs(); } while (0) #define BITFIELD_MASK(what) \ (1u << (what->a2.i >> 24)) @@ -995,17 +1010,11 @@ interpret(struct f_inst *what) break; case FI_EA_GET: /* Access to extended attributes */ ACCESS_RTE; + ACCESS_EATTRS; { - eattr *e = NULL; u16 code = what->a2.i; int f_type = what->aux >> 8; - - if (!(f_flags & FF_FORCE_TMPATTR)) - e = ea_find((*f_rte)->attrs->eattrs, code); - if (!e) - e = ea_find((*f_tmp_attrs), code); - if ((!e) && (f_flags & FF_FORCE_TMPATTR)) - e = ea_find((*f_rte)->attrs->eattrs, code); + eattr *e = ea_find(*f_eattrs, code); if (!e) { /* A special case: undefined as_path looks like empty as_path */ @@ -1089,6 +1098,7 @@ interpret(struct f_inst *what) break; case FI_EA_SET: ACCESS_RTE; + ACCESS_EATTRS; ARG_ANY(1); { struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr)); @@ -1143,13 +1153,7 @@ interpret(struct f_inst *what) runtime( "Setting bit in bitfield attribute to non-bool value" ); { /* First, we have to find the old value */ - eattr *e = NULL; - if (!(f_flags & FF_FORCE_TMPATTR)) - e = ea_find((*f_rte)->attrs->eattrs, code); - if (!e) - e = ea_find((*f_tmp_attrs), code); - if ((!e) && (f_flags & FF_FORCE_TMPATTR)) - e = ea_find((*f_rte)->attrs->eattrs, code); + eattr *e = ea_find(*f_eattrs, code); u32 data = e ? e->u.data : 0; if (v1.val.i) @@ -1181,14 +1185,9 @@ interpret(struct f_inst *what) default: bug("Unknown type in e,S"); } - if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) { - f_rta_cow(); - l->next = (*f_rte)->attrs->eattrs; - (*f_rte)->attrs->eattrs = l; - } else { - l->next = (*f_tmp_attrs); - (*f_tmp_attrs) = l; - } + f_rta_cow(); + l->next = *f_eattrs; + *f_eattrs = l; } break; case FI_PREF_GET: @@ -1518,11 +1517,12 @@ interpret(struct f_inst *what) else { ACCESS_RTE; + ACCESS_EATTRS; v1.val.net = (*f_rte)->net->n.addr; /* We ignore temporary attributes, probably not a problem here */ /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */ - eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(PROTOCOL_BGP, 0x02)); + eattr *e = ea_find(*f_eattrs, EA_CODE(PROTOCOL_BGP, 0x02)); if (!e || e->type != EAF_TYPE_AS_PATH) runtime("Missing AS_PATH attribute"); @@ -1720,7 +1720,6 @@ i_same(struct f_inst *f1, struct f_inst *f2) * f_run - run a filter for a route * @filter: filter to run * @rte: route being filtered, may be modified - * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run() * @tmp_pool: all filter allocations go from this pool * @flags: flags * @@ -1742,7 +1741,7 @@ i_same(struct f_inst *f1, struct f_inst *f2) * modified in place, old cached rta is possibly freed. */ int -f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags) +f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags) { if (filter == FILTER_ACCEPT) return F_ACCEPT; @@ -1755,7 +1754,6 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc f_rte = rte; f_old_rta = NULL; - f_tmp_attrs = tmp_attrs; f_pool = tmp_pool; f_flags = flags; @@ -1797,11 +1795,9 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool) { - struct ea_list *tmp_attrs = NULL; f_rte = rte; f_old_rta = NULL; - f_tmp_attrs = &tmp_attrs; f_pool = tmp_pool; f_flags = 0; @@ -1810,9 +1806,6 @@ f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool) /* Note that in this function we assume that rte->attrs is private / uncached */ struct f_val res = interpret(expr); - /* Hack to include EAF_TEMP attributes to the main list */ - (*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs); - return res; } @@ -1820,7 +1813,6 @@ struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool) { f_flags = 0; - f_tmp_attrs = NULL; f_rte = NULL; f_pool = tmp_pool; diff --git a/filter/filter.h b/filter/filter.h index 909d09b1..febfdc65 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -175,7 +175,7 @@ void trie_format(struct f_trie *t, buffer *buf); struct ea_list; struct rte; -int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags); +int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags); struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool); struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool); uint f_eval_int(struct f_inst *expr); @@ -285,7 +285,6 @@ struct f_trie #define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); -#define FF_FORCE_TMPATTR 1 /* Force all attributes to be temporary */ #define FF_SILENT 2 /* Silent filter execution */ /* Bird Tests */ 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; icount; i++) + + for(ea_list *eal = a->eattrs; eal; eal=eal->next) + for(int i=0; icount; 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) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 83986cb9..d9e3aad2 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -1829,7 +1829,7 @@ babel_dump(struct proto *P) } static void -babel_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED) +babel_get_route_info(rte *rte, byte *buf) { buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id); } @@ -2087,12 +2087,13 @@ babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router static int -babel_import_control(struct proto *P, struct rte **new, struct ea_list **attrs UNUSED, struct linpool *pool UNUSED) +babel_import_control(struct proto *P, struct rte **new, struct linpool *pool) { - rte *e = *new; + struct babel_proto *p = (void *) P; + struct rta *a = (*new)->attrs; /* Reject our own unreachable routes */ - if ((e->attrs->dest == RTD_UNREACHABLE) && (e->attrs->src->proto == P)) + if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P)) return -1; return 0; @@ -2105,9 +2106,9 @@ babel_make_tmp_attrs(struct rte *rt, struct linpool *pool) } static void -babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) +babel_store_tmp_attrs(struct rte *rt) { - rt->u.babel.metric = ea_get_int(attrs, EA_BABEL_METRIC, 0); + rt->u.babel.metric = ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, 0); } /* @@ -2116,7 +2117,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) */ static void babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, - struct rte *new, struct rte *old UNUSED, struct ea_list *attrs UNUSED) + struct rte *new, struct rte *old UNUSED) { struct babel_proto *p = (void *) P; struct babel_entry *e; @@ -2126,7 +2127,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, /* Update */ uint internal = (new->attrs->src->proto == P); uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno; - uint rt_metric = ea_get_int(attrs, EA_BABEL_METRIC, 0); + uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0); u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id; if (rt_metric > BABEL_INFINITY) diff --git a/proto/babel/config.Y b/proto/babel/config.Y index 205b4e4f..2b20c43f 100644 --- a/proto/babel/config.Y +++ b/proto/babel/config.Y @@ -125,7 +125,7 @@ babel_iface_opt_list: babel_iface: babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish; -CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_BABEL_METRIC); }) +CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_BABEL_METRIC); }) CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]); diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 5695e1c1..d65f6334 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1372,7 +1372,7 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) */ int -bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +bgp_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED) { rte *e = *new; struct proto *SRC = e->attrs->src->proto; @@ -1536,7 +1536,7 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at } void -bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea_list *attrs) +bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old) { struct bgp_proto *p = (void *) P; struct bgp_channel *c = (void *) C; @@ -1546,7 +1546,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea if (new) { - attrs = bgp_update_attrs(p, c, new, attrs, bgp_linpool2); + struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2); /* If attributes are invalid, we fail back to withdraw */ buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c); @@ -2007,10 +2007,10 @@ bgp_get_attr(eattr *a, byte *buf, int buflen) } void -bgp_get_route_info(rte *e, byte *buf, ea_list *attrs) +bgp_get_route_info(rte *e, byte *buf) { - eattr *p = ea_find(attrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); - eattr *o = ea_find(attrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); + eattr *p = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH)); + eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN)); u32 origas; buf += bsprintf(buf, " (%d", e->pref); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index de05dcfb..1235ee78 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -505,10 +505,10 @@ void bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *bp); int bgp_rte_better(struct rte *, struct rte *); int bgp_rte_mergable(rte *pri, rte *sec); int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best); -void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea_list *attrs); -int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *); +void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old); +int bgp_import_control(struct proto *, struct rte **, struct linpool *); int bgp_get_attr(struct eattr *e, byte *buf, int buflen); -void bgp_get_route_info(struct rte *, byte *buf, struct ea_list *attrs); +void bgp_get_route_info(struct rte *, byte *buf); /* packets.c */ diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 0b09966d..c439a614 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -497,10 +497,10 @@ ospf_iface: ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); } ; -CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); }) -CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); }) -CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); }) -CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID | EAF_TEMP, T_QUAD, EA_OSPF_ROUTER_ID); }) +CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC1); }) +CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC2); }) +CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_TAG); }) +CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_OSPF_ROUTER_ID); }) CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]); CF_CLI(SHOW OSPF, optsym, [], [[Show information about OSPF protocol]]) diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index d9edc3e7..fa122f01 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -101,9 +101,9 @@ #include #include "ospf.h" -static int ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool); +static int ospf_import_control(struct proto *P, rte **new, struct linpool *pool); static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); -static void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs); +static void ospf_store_tmp_attrs(struct rte *rt); static void ospf_reload_routes(struct channel *C); static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); @@ -446,7 +446,7 @@ ospf_disp(timer * timer) * import to the filters. */ static int -ospf_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +ospf_import_control(struct proto *P, rte **new, struct linpool *pool) { struct ospf_proto *p = (struct ospf_proto *) P; struct ospf_area *oa = ospf_main_area(p); @@ -471,12 +471,12 @@ ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool) } static void -ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) +ospf_store_tmp_attrs(struct rte *rt) { - rt->u.ospf.metric1 = ea_get_int(attrs, EA_OSPF_METRIC1, LSINFINITY); - rt->u.ospf.metric2 = ea_get_int(attrs, EA_OSPF_METRIC2, 10000); - rt->u.ospf.tag = ea_get_int(attrs, EA_OSPF_TAG, 0); - rt->u.ospf.router_id = ea_get_int(attrs, EA_OSPF_ROUTER_ID, 0); + rt->u.ospf.metric1 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY); + rt->u.ospf.metric2 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC2, 10000); + rt->u.ospf.tag = ea_get_int(rt->attrs->eattrs, EA_OSPF_TAG, 0); + rt->u.ospf.router_id = ea_get_int(rt->attrs->eattrs, EA_OSPF_ROUTER_ID, 0); } /** @@ -535,7 +535,7 @@ ospf_get_status(struct proto *P, byte * buf) } static void -ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED) +ospf_get_route_info(rte * rte, byte * buf) { char *type = ""; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index e909bbe9..54b255c9 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -1243,11 +1243,12 @@ find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa) } void -ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *ea) +ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED) { struct ospf_proto *p = (struct ospf_proto *) P; struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */ ort *nf; + struct ea_list *ea = new->attrs->eattrs; /* * There are several posibilities: diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index ac87334b..54ec9ccf 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -188,7 +188,7 @@ void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options); void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit); -void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old, ea_list *attrs); +void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old); void ospf_update_topology(struct ospf_proto *p); struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type); diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index ffc677f4..7aada37e 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -44,7 +44,7 @@ #include "pipe.h" static void -pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs) +pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old) { struct pipe_proto *p = (void *) P; struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri; @@ -69,7 +69,6 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o memcpy(a, new->attrs, rta_size(new->attrs)); a->aflags = 0; - a->eattrs = attrs; a->hostentry = NULL; e = rte_get_temp(a); e->pflags = 0; @@ -93,7 +92,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o } static int -pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED) +pipe_import_control(struct proto *P, rte **ee, struct linpool *p UNUSED) { struct proto *pp = (*ee)->sender->proto; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 2f5f1c27..ce88c7cc 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -395,7 +395,7 @@ radv_net_match_trigger(struct radv_config *cf, net *n) } int -radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +radv_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED) { // struct radv_proto *p = (struct radv_proto *) P; struct radv_config *cf = (struct radv_config *) (P->cf); @@ -410,7 +410,7 @@ radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct l } static void -radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs) +radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED) { struct radv_proto *p = (struct radv_proto *) P; struct radv_config *cf = (struct radv_config *) (P->cf); @@ -448,11 +448,11 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte { /* Update */ - ea = ea_find(attrs, EA_RA_PREFERENCE); + ea = ea_find(new->attrs->eattrs, EA_RA_PREFERENCE); uint preference = ea ? ea->u.data : RA_PREF_MEDIUM; uint preference_set = !!ea; - ea = ea_find(attrs, EA_RA_LIFETIME); + ea = ea_find(new->attrs->eattrs, EA_RA_LIFETIME); uint lifetime = ea ? ea->u.data : 0; uint lifetime_set = !!ea; diff --git a/proto/rip/config.Y b/proto/rip/config.Y index aff63f03..c46cf00c 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -186,8 +186,8 @@ rip_iface: rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish; -CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_METRIC); }) -CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_TAG); }) +CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_METRIC); }) +CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_TAG); }) CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]); diff --git a/proto/rip/rip.c b/proto/rip/rip.c index adc2b471..90bf8e5c 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -298,7 +298,7 @@ rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from) */ static void rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, struct rte *new, - struct rte *old UNUSED, struct ea_list *attrs) + struct rte *old UNUSED) { struct rip_proto *p = (struct rip_proto *) P; struct rip_entry *en; @@ -307,8 +307,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s if (new) { /* Update */ - u32 rt_metric = ea_get_int(attrs, EA_RIP_METRIC, 1); - u32 rt_tag = ea_get_int(attrs, EA_RIP_TAG, 0); + u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1); + u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0); if (rt_metric > p->infinity) { @@ -1040,10 +1040,10 @@ rip_make_tmp_attrs(struct rte *rt, struct linpool *pool) } static void -rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs) +rip_store_tmp_attrs(struct rte *rt) { - rt->u.rip.metric = ea_get_int(attrs, EA_RIP_METRIC, 1); - rt->u.rip.tag = ea_get_int(attrs, EA_RIP_TAG, 0); + rt->u.rip.metric = ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, 1); + rt->u.rip.tag = ea_get_int(rt->attrs->eattrs, EA_RIP_TAG, 0); } static int @@ -1081,7 +1081,6 @@ rip_init(struct proto_config *CF) P->if_notify = rip_if_notify; P->rt_notify = rip_rt_notify; P->neigh_notify = rip_neigh_notify; - // P->import_control = rip_import_control; P->reload_routes = rip_reload_routes; P->make_tmp_attrs = rip_make_tmp_attrs; P->store_tmp_attrs = rip_store_tmp_attrs; @@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF) } static void -rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED) +rip_get_route_info(rte *rte, byte *buf) { buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric); diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index e56dd616..8522e415 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -347,8 +347,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e) } void -krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, - struct ea_list *eattrs UNUSED) +krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) { int err = 0; diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index f5db1575..73f77147 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -1177,11 +1177,12 @@ nh_bufsize(struct nexthop *nh) } static int -nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int dest, struct nexthop *nh) +nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh) { eattr *ea; net *net = e->net; rta *a = e->attrs; + ea_list *eattrs = a->eattrs; int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh)); u32 priority = 0; @@ -1328,7 +1329,7 @@ dest: } static inline int -nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs) +nl_add_rte(struct krt_proto *p, rte *e) { rta *a = e->attrs; int err = 0; @@ -1337,34 +1338,34 @@ nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs) { struct nexthop *nh = &(a->nh); - err = nl_send_route(p, e, eattrs, NL_OP_ADD, RTD_UNICAST, nh); + err = nl_send_route(p, e, NL_OP_ADD, RTD_UNICAST, nh); if (err < 0) return err; for (nh = nh->next; nh; nh = nh->next) - err += nl_send_route(p, e, eattrs, NL_OP_APPEND, RTD_UNICAST, nh); + err += nl_send_route(p, e, NL_OP_APPEND, RTD_UNICAST, nh); return err; } - return nl_send_route(p, e, eattrs, NL_OP_ADD, a->dest, &(a->nh)); + return nl_send_route(p, e, NL_OP_ADD, a->dest, &(a->nh)); } static inline int -nl_delete_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs) +nl_delete_rte(struct krt_proto *p, rte *e) { int err = 0; /* For IPv6, we just repeatedly request DELETE until we get error */ do - err = nl_send_route(p, e, eattrs, NL_OP_DELETE, RTD_NONE, NULL); + err = nl_send_route(p, e, NL_OP_DELETE, RTD_NONE, NULL); while (krt_ecmp6(p) && !err); return err; } void -krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs) +krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old) { int err = 0; @@ -1380,10 +1381,10 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list */ if (old) - nl_delete_rte(p, old, eattrs); + nl_delete_rte(p, old); if (new) - err = nl_add_rte(p, new, eattrs); + err = nl_add_rte(p, new); if (err < 0) n->n.flags |= KRF_SYNC_ERROR; diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index 9aac8668..98740b70 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -122,8 +122,8 @@ kif_iface: kif_iface_start iface_patt_list_nopx kif_iface_opt_list; -CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); }) -CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); }) +CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); }) +CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_METRIC); }) CF_CODE diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index ae51927e..a79df54e 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -551,7 +551,7 @@ krt_flush_routes(struct krt_proto *p) if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED)) { /* FIXME: this does not work if gw is changed in export filter */ - krt_replace_rte(p, e->net, NULL, e, NULL); + krt_replace_rte(p, e->net, NULL, e); n->n.flags &= ~KRF_INSTALLED; } } @@ -559,14 +559,14 @@ krt_flush_routes(struct krt_proto *p) } static struct rte * -krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) +krt_export_net(struct krt_proto *p, net *net, rte **rt_free) { struct channel *c = p->p.main_channel; struct filter *filter = c->out_filter; rte *rt; if (c->ra_mode == RA_MERGED) - return rt_export_merged(c, net, rt_free, tmpa, krt_filter_lp, 1); + return rt_export_merged(c, net, rt_free, krt_filter_lp, 1); rt = net->routes; *rt_free = NULL; @@ -577,15 +577,14 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa) if (filter == FILTER_REJECT) return NULL; - struct proto *src = rt->attrs->src->proto; - *tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, krt_filter_lp) : NULL; + rte_make_tmp_attrs(&rt, krt_filter_lp); /* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */ if (filter == FILTER_ACCEPT) goto accept; - if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT) + if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT) goto reject; @@ -667,9 +666,8 @@ krt_got_route(struct krt_proto *p, rte *e) if (net->n.flags & KRF_INSTALLED) { rte *new, *rt_free; - ea_list *tmpa; - new = krt_export_net(p, net, &rt_free, &tmpa); + new = krt_export_net(p, net, &rt_free); /* TODO: There also may be changes in route eattrs, we ignore that for now. */ @@ -714,7 +712,6 @@ krt_prune(struct krt_proto *p) { int verdict = n->n.flags & KRF_VERDICT_MASK; rte *new, *old, *rt_free = NULL; - ea_list *tmpa = NULL; if (verdict == KRF_UPDATE || verdict == KRF_DELETE) { @@ -728,12 +725,10 @@ krt_prune(struct krt_proto *p) if (verdict == KRF_CREATE || verdict == KRF_UPDATE) { /* We have to run export filter to get proper 'new' route */ - new = krt_export_net(p, n, &rt_free, &tmpa); + new = krt_export_net(p, n, &rt_free); if (!new) verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE; - else - tmpa = ea_append(tmpa, new->attrs->eattrs); } else new = NULL; @@ -744,7 +739,7 @@ krt_prune(struct krt_proto *p) if (new && (n->n.flags & KRF_INSTALLED)) { krt_trace_in(p, new, "reinstalling"); - krt_replace_rte(p, n, new, NULL, tmpa); + krt_replace_rte(p, n, new, NULL); } break; case KRF_SEEN: @@ -753,11 +748,11 @@ krt_prune(struct krt_proto *p) break; case KRF_UPDATE: krt_trace_in(p, new, "updating"); - krt_replace_rte(p, n, new, old, tmpa); + krt_replace_rte(p, n, new, old); break; case KRF_DELETE: krt_trace_in(p, old, "deleting"); - krt_replace_rte(p, n, NULL, old, NULL); + krt_replace_rte(p, n, NULL, old); break; default: bug("krt_prune: invalid route status"); @@ -795,7 +790,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new) if (new) { krt_trace_in(p, e, "[redirect] deleting"); - krt_replace_rte(p, net, NULL, e, NULL); + krt_replace_rte(p, net, NULL, e); } /* If !new, it is probably echo of our deletion */ break; @@ -937,14 +932,14 @@ krt_make_tmp_attrs(rte *rt, struct linpool *pool) } static void -krt_store_tmp_attrs(rte *rt, struct ea_list *attrs) +krt_store_tmp_attrs(rte *rt) { /* EA_KRT_SOURCE is read-only */ - rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0); + rt->u.krt.metric = ea_get_int(rt->attrs->eattrs, EA_KRT_METRIC, 0); } static int -krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +krt_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED) { // struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; @@ -975,7 +970,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li static void krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net, - rte *new, rte *old, struct ea_list *eattrs) + rte *new, rte *old) { struct krt_proto *p = (struct krt_proto *) P; @@ -988,7 +983,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net, else net->n.flags &= ~KRF_INSTALLED; if (p->initialized) /* Before first scan we don't touch the routes */ - krt_replace_rte(p, net, new, old, eattrs); + krt_replace_rte(p, net, new, old); } static void diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index ff27bcf5..6ace2a86 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -139,7 +139,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *); int krt_capable(rte *e); void krt_do_scan(struct krt_proto *); -void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs); +void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old); int krt_sys_get_attr(eattr *a, byte *buf, int buflen);