summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter/filter.c64
-rw-r--r--filter/filter.h3
-rw-r--r--nest/protocol.h24
-rw-r--r--nest/route.h13
-rw-r--r--nest/rt-attr.c60
-rw-r--r--nest/rt-show.c34
-rw-r--r--nest/rt-table.c97
-rw-r--r--proto/babel/babel.c17
-rw-r--r--proto/babel/config.Y2
-rw-r--r--proto/bgp/attrs.c12
-rw-r--r--proto/bgp/bgp.h6
-rw-r--r--proto/ospf/config.Y8
-rw-r--r--proto/ospf/ospf.c18
-rw-r--r--proto/ospf/topology.c3
-rw-r--r--proto/ospf/topology.h2
-rw-r--r--proto/pipe/pipe.c5
-rw-r--r--proto/radv/radv.c8
-rw-r--r--proto/rip/config.Y4
-rw-r--r--proto/rip/rip.c15
-rw-r--r--sysdep/bsd/krt-sock.c3
-rw-r--r--sysdep/linux/netlink.c21
-rw-r--r--sysdep/unix/krt.Y4
-rw-r--r--sysdep/unix/krt.c37
-rw-r--r--sysdep/unix/krt.h2
24 files changed, 220 insertions, 242 deletions
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; 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)
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, [<name>], [[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 <stdlib.h>
#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 = "<bug>";
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);