0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Merge commit '938742decc6e1d6d3a0375dd012b75172e747bbc' into haugesund

This commit is contained in:
Maria Matejka 2022-06-08 15:31:28 +02:00
commit 4364ee9b6f
27 changed files with 337 additions and 503 deletions

View File

@ -212,7 +212,6 @@
* m4_dnl NEVER_CONSTANT-> don't generate pre-interpretation code at all * m4_dnl NEVER_CONSTANT-> don't generate pre-interpretation code at all
* m4_dnl ACCESS_RTE -> check that route is available, also NEVER_CONSTANT * m4_dnl ACCESS_RTE -> check that route is available, also NEVER_CONSTANT
* m4_dnl ACCESS_EATTRS -> pre-cache the eattrs; use only with ACCESS_RTE * m4_dnl ACCESS_EATTRS -> pre-cache the eattrs; use only with ACCESS_RTE
* m4_dnl f_rta_cow(fs) -> function to call before any change to route should be done
* *
* m4_dnl If you are stymied, see FI_CALL or FI_CONSTANT or just search for * m4_dnl If you are stymied, see FI_CALL or FI_CONSTANT or just search for
* m4_dnl the mentioned macros in this file to see what is happening there in wild. * m4_dnl the mentioned macros in this file to see what is happening there in wild.
@ -577,8 +576,6 @@
ARG_ANY(1); ARG_ANY(1);
STATIC_ATTR; STATIC_ATTR;
ARG_TYPE(1, sa.type); ARG_TYPE(1, sa.type);
f_rta_cow(fs);
{ {
union { union {
struct nexthop_adata nha; struct nexthop_adata nha;
@ -741,8 +738,6 @@
if (da->type >= EAF_TYPE__MAX) if (da->type >= EAF_TYPE__MAX)
bug("Unsupported attribute type"); bug("Unsupported attribute type");
f_rta_cow(fs);
switch (da->type) { switch (da->type) {
case T_OPAQUE: case T_OPAQUE:
case T_IFACE: case T_IFACE:
@ -770,7 +765,6 @@
ACCESS_RTE; ACCESS_RTE;
ACCESS_EATTRS; ACCESS_EATTRS;
f_rta_cow(fs);
ea_unset_attr(fs->eattrs, 1, da); ea_unset_attr(fs->eattrs, 1, da);
} }

View File

@ -96,28 +96,7 @@ void (*bt_assert_hook)(int result, const struct f_line_item *assert);
static inline void f_cache_eattrs(struct filter_state *fs) static inline void f_cache_eattrs(struct filter_state *fs)
{ {
fs->eattrs = &(fs->rte->attrs->eattrs); fs->eattrs = &(fs->rte->attrs);
}
/*
* rta_cow - prepare rta for modification by filter
*/
static void
f_rta_cow(struct filter_state *fs)
{
if (!rta_is_cached(fs->rte->attrs))
return;
/*
* Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
* with fs->old_rta (they will be copied when the cached rta will be obtained
* at the end of f_run()), also the lock of hostentry is inherited (we
* suppose hostentry is not changed by filters).
*/
fs->rte->attrs = rta_do_cow(fs->rte->attrs, tmp_linpool);
/* Re-cache the ea_list */
f_cache_eattrs(fs);
} }
static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;

View File

@ -18,7 +18,7 @@ struct cli;
typedef struct rte { typedef struct rte {
struct rta *attrs; /* Attributes of this route */ struct ea_list *attrs; /* Attributes of this route */
const net_addr *net; /* Network this RTE belongs to */ const net_addr *net; /* Network this RTE belongs to */
struct rte_src *src; /* Route source that created the route */ struct rte_src *src; /* Route source that created the route */
struct rt_import_hook *sender; /* Import hook used to send the route to the routing table */ struct rt_import_hook *sender; /* Import hook used to send the route to the routing table */
@ -92,14 +92,6 @@ struct nexthop_adata {
#define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */ #define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */
typedef struct rta {
struct rta *next, **pprev; /* Hash chain */
u32 uc; /* Use count */
u32 hash_key; /* Hash over important fields */
struct ea_list *eattrs; /* Extended Attribute chain */
u16 cached:1; /* Are attributes cached? */
} rta;
#define RTS_STATIC 1 /* Normal static route */ #define RTS_STATIC 1 /* Normal static route */
#define RTS_INHERIT 2 /* Route inherited from kernel */ #define RTS_INHERIT 2 /* Route inherited from kernel */
#define RTS_DEVICE 3 /* Device route */ #define RTS_DEVICE 3 /* Device route */
@ -155,6 +147,10 @@ typedef struct eattr {
#define EA_BIT_GET(ea) ((ea) >> 24) #define EA_BIT_GET(ea) ((ea) >> 24)
typedef struct ea_list { typedef struct ea_list {
struct ea_list *next_hash; /* Next in hash chain */
struct ea_list **pprev_hash; /* Previous in hash chain */
u32 uc; /* Use count */
u32 hash_key; /* List hash */
struct ea_list *next; /* In case we have an override list */ struct ea_list *next; /* In case we have an override list */
byte flags; /* Flags: EALF_... */ byte flags; /* Flags: EALF_... */
byte rfu; byte rfu;
@ -164,7 +160,7 @@ typedef struct ea_list {
#define EALF_SORTED 1 /* Attributes are sorted by code */ #define EALF_SORTED 1 /* Attributes are sorted by code */
#define EALF_BISECT 2 /* Use interval bisection for searching */ #define EALF_BISECT 2 /* Use interval bisection for searching */
#define EALF_CACHED 4 /* Attributes belonging to cached rta */ #define EALF_CACHED 4 /* List is cached */
struct ea_class { struct ea_class {
#define EA_CLASS_INSIDE \ #define EA_CLASS_INSIDE \
@ -319,7 +315,7 @@ ea_copy_attr(ea_list **to, ea_list *from, const struct ea_class *def)
/* Preference: first-order comparison */ /* Preference: first-order comparison */
extern struct ea_class ea_gen_preference; extern struct ea_class ea_gen_preference;
static inline u32 rt_get_preference(rte *rt) static inline u32 rt_get_preference(rte *rt)
{ return ea_get_int(rt->attrs->eattrs, &ea_gen_preference, 0); } { return ea_get_int(rt->attrs, &ea_gen_preference, 0); }
/* IGP metric: second-order comparison */ /* IGP metric: second-order comparison */
extern struct ea_class ea_gen_igp_metric; extern struct ea_class ea_gen_igp_metric;
@ -334,7 +330,7 @@ extern struct ea_class ea_gen_from;
* To be superseded in a near future by something more informative. */ * To be superseded in a near future by something more informative. */
extern struct ea_class ea_gen_source; extern struct ea_class ea_gen_source;
static inline u32 rt_get_source_attr(const rte *rt) static inline u32 rt_get_source_attr(const rte *rt)
{ return ea_get_int(rt->attrs->eattrs, &ea_gen_source, 0); } { return ea_get_int(rt->attrs, &ea_gen_source, 0); }
/* Flowspec validation result */ /* Flowspec validation result */
enum flowspec_valid { enum flowspec_valid {
@ -350,7 +346,7 @@ static inline const char *flowspec_valid_name(enum flowspec_valid v)
extern struct ea_class ea_gen_flowspec_valid; extern struct ea_class ea_gen_flowspec_valid;
static inline enum flowspec_valid rt_get_flowspec_valid(rte *rt) static inline enum flowspec_valid rt_get_flowspec_valid(rte *rt)
{ return ea_get_int(rt->attrs->eattrs, &ea_gen_flowspec_valid, FLOWSPEC_UNKNOWN); } { return ea_get_int(rt->attrs, &ea_gen_flowspec_valid, FLOWSPEC_UNKNOWN); }
/* Next hop: For now, stored as adata */ /* Next hop: For now, stored as adata */
extern struct ea_class ea_gen_nexthop; extern struct ea_class ea_gen_nexthop;
@ -391,7 +387,7 @@ int nexthop_is_sorted(struct nexthop_adata *x);
/* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */ /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
static inline int rte_is_reachable(rte *r) static inline int rte_is_reachable(rte *r)
{ {
eattr *nhea = ea_find(r->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(r->attrs, &ea_gen_nexthop);
if (!nhea) if (!nhea)
return 0; return 0;
@ -413,21 +409,23 @@ static inline int nhea_dest(eattr *nhea)
static inline int rte_dest(const rte *r) static inline int rte_dest(const rte *r)
{ {
return nhea_dest(ea_find(r->attrs->eattrs, &ea_gen_nexthop)); return nhea_dest(ea_find(r->attrs, &ea_gen_nexthop));
} }
void rta_init(void); void rta_init(void);
#define rta_size(...) (sizeof(rta)) ea_list *ea_lookup(ea_list *); /* Get a cached (and normalized) variant of this attribute list */
#define RTA_MAX_SIZE (sizeof(rta)) static inline int ea_is_cached(ea_list *r) { return r->flags & EALF_CACHED; }
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ static inline ea_list *ea_clone(ea_list *r) { r->uc++; return r; }
static inline int rta_is_cached(rta *r) { return r->cached; } void ea__free(ea_list *r);
static inline rta *rta_clone(rta *r) { r->uc++; return r; } static inline void ea_free(ea_list *r) { if (r && !--r->uc) ea__free(r); }
void rta__free(rta *r);
static inline void rta_free(rta *r) { if (r && !--r->uc) rta__free(r); } void ea_dump(ea_list *);
rta *rta_do_cow(rta *o, linpool *lp); void ea_dump_all(void);
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; } void ea_show_list(struct cli *, ea_list *);
void rta_dump(rta *);
void rta_dump_all(void); #define rta_lookup ea_lookup
void rta_show(struct cli *, rta *); #define rta_is_cached ea_is_cached
#define rta_clone ea_clone
#define rta_free ea_free
#endif #endif

View File

@ -850,7 +850,7 @@ CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]]) CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
{ neigh_dump_all(); cli_msg(0, ""); } ; { neigh_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]]) CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
{ rta_dump_all(); cli_msg(0, ""); } ; { ea_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP ROUTES,,, [[Dump routes]]) CF_CLI(DUMP ROUTES,,, [[Dump routes]])
{ rt_dump_all(); cli_msg(0, ""); } ; { rt_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP TABLES,,, [[Dump table connections]]) CF_CLI(DUMP TABLES,,, [[Dump table connections]])

View File

@ -180,7 +180,6 @@ const char * flowspec_valid_names[FLOWSPEC__MAX] = {
pool *rta_pool; pool *rta_pool;
static slab *rta_slab;
static slab *rte_src_slab; static slab *rte_src_slab;
static struct idm src_ids; static struct idm src_ids;
@ -949,17 +948,6 @@ ea_list_unref(ea_list *l)
} }
} }
static inline void
ea_free(ea_list *o)
{
if (o)
{
ea_list_unref(o);
ASSERT(!o->next);
mb_free(o);
}
}
void void
ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max) ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max)
{ {
@ -1056,7 +1044,7 @@ ea_show_lc_set(struct cli *c, const struct adata *ad, byte *pos, byte *buf, byte
* If the protocol defining the attribute provides its own * If the protocol defining the attribute provides its own
* get_attr() hook, it's consulted first. * get_attr() hook, it's consulted first.
*/ */
void static void
ea_show(struct cli *c, const eattr *e) ea_show(struct cli *c, const eattr *e)
{ {
const struct adata *ad = (e->type & EAF_EMBEDDED) ? NULL : e->u.ptr; const struct adata *ad = (e->type & EAF_EMBEDDED) ? NULL : e->u.ptr;
@ -1147,10 +1135,11 @@ ea_dump(ea_list *e)
} }
while (e) while (e)
{ {
debug("[%c%c%c]", debug("[%c%c%c] uc=%d h=%08x",
(e->flags & EALF_SORTED) ? 'S' : 's', (e->flags & EALF_SORTED) ? 'S' : 's',
(e->flags & EALF_BISECT) ? 'B' : 'b', (e->flags & EALF_BISECT) ? 'B' : 'b',
(e->flags & EALF_CACHED) ? 'C' : 'c'); (e->flags & EALF_CACHED) ? 'C' : 'c',
e->uc, e->hash_key);
for(i=0; i<e->count; i++) for(i=0; i<e->count; i++)
{ {
eattr *a = &e->attrs[i]; eattr *a = &e->attrs[i];
@ -1242,12 +1231,12 @@ static uint rta_cache_count;
static uint rta_cache_size = 32; static uint rta_cache_size = 32;
static uint rta_cache_limit; static uint rta_cache_limit;
static uint rta_cache_mask; static uint rta_cache_mask;
static rta **rta_hash_table; static ea_list **rta_hash_table;
static void static void
rta_alloc_hash(void) rta_alloc_hash(void)
{ {
rta_hash_table = mb_allocz(rta_pool, sizeof(rta *) * rta_cache_size); rta_hash_table = mb_allocz(rta_pool, sizeof(ea_list *) * rta_cache_size);
if (rta_cache_size < 32768) if (rta_cache_size < 32768)
rta_cache_limit = rta_cache_size * 2; rta_cache_limit = rta_cache_size * 2;
else else
@ -1255,44 +1244,14 @@ rta_alloc_hash(void)
rta_cache_mask = rta_cache_size - 1; rta_cache_mask = rta_cache_size - 1;
} }
static inline uint
rta_hash(rta *a)
{
return ea_hash(a->eattrs);
}
static inline int
rta_same(rta *x, rta *y)
{
return ea_same(x->eattrs, y->eattrs);
}
static rta *
rta_copy(rta *o)
{
rta *r = sl_alloc(rta_slab);
memcpy(r, o, rta_size(o));
r->uc = 1;
if (!r->eattrs)
return r;
uint elen = ea_list_size(o->eattrs);
r->eattrs = mb_alloc(rta_pool, elen);
ea_list_copy(r->eattrs, o->eattrs, elen);
ea_list_ref(r->eattrs);
r->eattrs->flags |= EALF_CACHED;
return r;
}
static inline void static inline void
rta_insert(rta *r) rta_insert(ea_list *r)
{ {
uint h = r->hash_key & rta_cache_mask; uint h = r->hash_key & rta_cache_mask;
r->next = rta_hash_table[h]; r->next_hash = rta_hash_table[h];
if (r->next) if (r->next_hash)
r->next->pprev = &r->next; r->next_hash->pprev_hash = &r->next_hash;
r->pprev = &rta_hash_table[h]; r->pprev_hash = &rta_hash_table[h];
rta_hash_table[h] = r; rta_hash_table[h] = r;
} }
@ -1301,8 +1260,8 @@ rta_rehash(void)
{ {
uint ohs = rta_cache_size; uint ohs = rta_cache_size;
uint h; uint h;
rta *r, *n; ea_list *r, *n;
rta **oht = rta_hash_table; ea_list **oht = rta_hash_table;
rta_cache_size = 2*rta_cache_size; rta_cache_size = 2*rta_cache_size;
DBG("Rehashing rta cache from %d to %d entries.\n", ohs, rta_cache_size); DBG("Rehashing rta cache from %d to %d entries.\n", ohs, rta_cache_size);
@ -1310,7 +1269,7 @@ rta_rehash(void)
for(h=0; h<ohs; h++) for(h=0; h<ohs; h++)
for(r=oht[h]; r; r=n) for(r=oht[h]; r; r=n)
{ {
n = r->next; n = r->next_hash;
rta_insert(r); rta_insert(r);
} }
mb_free(oht); mb_free(oht);
@ -1329,24 +1288,29 @@ rta_rehash(void)
* The extended attribute lists attached to the &rta are automatically * The extended attribute lists attached to the &rta are automatically
* converted to the normalized form. * converted to the normalized form.
*/ */
rta * ea_list *
rta_lookup(rta *o) ea_lookup(ea_list *o)
{ {
rta *r; ea_list *r;
uint h; uint h;
ASSERT(!o->cached); ASSERT(!ea_is_cached(o));
if (o->eattrs) o = ea_normalize(o);
o->eattrs = ea_normalize(o->eattrs); h = ea_hash(o);
h = rta_hash(o); for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next_hash)
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next) if (r->hash_key == h && ea_same(r, o))
if (r->hash_key == h && rta_same(r, o)) return ea_clone(r);
return rta_clone(r);
r = rta_copy(o); uint elen = ea_list_size(o);
r = mb_alloc(rta_pool, elen);
ea_list_copy(r, o, elen);
ea_list_ref(r);
r->flags |= EALF_CACHED;
r->hash_key = h; r->hash_key = h;
r->cached = 1; r->uc = 1;
rta_insert(r); rta_insert(r);
if (++rta_cache_count > rta_cache_limit) if (++rta_cache_count > rta_cache_limit)
@ -1356,46 +1320,17 @@ rta_lookup(rta *o)
} }
void void
rta__free(rta *a) ea__free(ea_list *a)
{ {
ASSERT(rta_cache_count && a->cached); ASSERT(rta_cache_count && ea_is_cached(a));
rta_cache_count--; rta_cache_count--;
*a->pprev = a->next; *a->pprev_hash = a->next_hash;
if (a->next) if (a->next_hash)
a->next->pprev = a->pprev; a->next_hash->pprev_hash = a->pprev_hash;
ea_free(a->eattrs);
a->cached = 0;
sl_free(a);
}
rta * ASSERT(!a->next);
rta_do_cow(rta *o, linpool *lp) ea_list_unref(a);
{ mb_free(a);
rta *r = lp_alloc(lp, rta_size(o));
memcpy(r, o, rta_size(o));
r->cached = 0;
r->uc = 0;
return r;
}
/**
* rta_dump - dump route attributes
* @a: attribute structure to dump
*
* This function takes a &rta and dumps its contents to the debug output.
*/
void
rta_dump(rta *a)
{
debug("uc=%d h=%04x",
a->uc, a->hash_key);
if (!a->cached)
debug(" !CACHED");
if (a->eattrs)
{
debug(" EA: ");
ea_dump(a->eattrs);
}
} }
/** /**
@ -1405,26 +1340,23 @@ rta_dump(rta *a)
* to the debug output. * to the debug output.
*/ */
void void
rta_dump_all(void) ea_dump_all(void)
{ {
rta *a;
uint h;
debug("Route attribute cache (%d entries, rehash at %d):\n", rta_cache_count, rta_cache_limit); debug("Route attribute cache (%d entries, rehash at %d):\n", rta_cache_count, rta_cache_limit);
for(h=0; h<rta_cache_size; h++) for (uint h=0; h < rta_cache_size; h++)
for(a=rta_hash_table[h]; a; a=a->next) for (ea_list *a = rta_hash_table[h]; a; a = a->next_hash)
{ {
debug("%p ", a); debug("%p ", a);
rta_dump(a); ea_dump(a);
debug("\n"); debug("\n");
} }
debug("\n"); debug("\n");
} }
void void
rta_show(struct cli *c, rta *a) ea_show_list(struct cli *c, ea_list *eal)
{ {
for(ea_list *eal = a->eattrs; eal; eal=eal->next) for( ; eal; eal=eal->next)
for(int i=0; i<eal->count; i++) for(int i=0; i<eal->count; i++)
ea_show(c, &eal->attrs[i]); ea_show(c, &eal->attrs[i]);
} }
@ -1440,8 +1372,6 @@ rta_init(void)
{ {
rta_pool = rp_new(&root_pool, "Attributes"); rta_pool = rp_new(&root_pool, "Attributes");
rta_slab = sl_new(rta_pool, sizeof(rta));
rta_alloc_hash(); rta_alloc_hash();
rte_src_init(); rte_src_init();
ea_class_init(); ea_class_init();

View File

@ -79,18 +79,18 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
/* Use iface ID as local source ID */ /* Use iface ID as local source ID */
struct rte_src *src = rt_get_source(P, ad->iface->index); struct rte_src *src = rt_get_source(P, ad->iface->index);
rta a0 = {}; ea_list *ea = NULL;
struct nexthop_adata nhad = { struct nexthop_adata nhad = {
.nh = { .iface = ad->iface, }, .nh = { .iface = ad->iface, },
.ad = { .length = (void *) NEXTHOP_NEXT(&nhad.nh) - (void *) nhad.ad.data, }, .ad = { .length = (void *) NEXTHOP_NEXT(&nhad.nh) - (void *) nhad.ad.data, },
}; };
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, c->preference); ea_set_attr_u32(&ea, &ea_gen_preference, 0, c->preference);
ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_DEVICE); ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_DEVICE);
ea_set_attr_data(&a0.eattrs, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length); ea_set_attr_data(&ea, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length);
rte e0 = { rte e0 = {
.attrs = rta_lookup(&a0), .attrs = ea,
.src = src, .src = src,
}; };

View File

@ -42,25 +42,25 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
{ {
byte from[IPA_MAX_TEXT_LENGTH+8]; byte from[IPA_MAX_TEXT_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
rta *a = e->attrs; ea_list *a = e->attrs;
int sync_error = d->kernel ? krt_get_sync_error(d->kernel, e) : 0; int sync_error = d->kernel ? krt_get_sync_error(d->kernel, e) : 0;
void (*get_route_info)(struct rte *, byte *buf); void (*get_route_info)(struct rte *, byte *buf);
eattr *nhea = net_type_match(e->net, NB_DEST) ? eattr *nhea = net_type_match(e->net, NB_DEST) ?
ea_find(a->eattrs, &ea_gen_nexthop) : NULL; ea_find(a, &ea_gen_nexthop) : NULL;
struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL;
int dest = nhad ? (NEXTHOP_IS_REACHABLE(nhad) ? RTD_UNICAST : nhad->dest) : RTD_NONE; int dest = nhad ? (NEXTHOP_IS_REACHABLE(nhad) ? RTD_UNICAST : nhad->dest) : RTD_NONE;
int flowspec_valid = net_is_flow(e->net) ? rt_get_flowspec_valid(e) : FLOWSPEC_UNKNOWN; int flowspec_valid = net_is_flow(e->net) ? rt_get_flowspec_valid(e) : FLOWSPEC_UNKNOWN;
tm_format_time(tm, &config->tf_route, e->lastmod); tm_format_time(tm, &config->tf_route, e->lastmod);
ip_addr a_from = ea_get_ip(a->eattrs, &ea_gen_from, IPA_NONE); ip_addr a_from = ea_get_ip(a, &ea_gen_from, IPA_NONE);
if (ipa_nonzero(a_from) && (!nhad || !ipa_equal(a_from, nhad->nh.gw))) if (ipa_nonzero(a_from) && (!nhad || !ipa_equal(a_from, nhad->nh.gw)))
bsprintf(from, " from %I", a_from); bsprintf(from, " from %I", a_from);
else else
from[0] = 0; from[0] = 0;
/* Need to normalize the extended attributes */ /* Need to normalize the extended attributes */
if (d->verbose && !rta_is_cached(a) && a->eattrs) if (d->verbose && !rta_is_cached(a) && a)
a->eattrs = ea_normalize(a->eattrs); a = ea_normalize(a);
get_route_info = e->src->proto->proto->get_route_info; get_route_info = e->src->proto->proto->get_route_info;
if (get_route_info) if (get_route_info)
@ -102,7 +102,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
} }
if (d->verbose) if (d->verbose)
rta_show(c, a); ea_show_list(c, a);
} }
static uint static uint

View File

@ -603,7 +603,7 @@ rte_store(const rte *r, net *net, rtable *tab)
rt_lock_source(e->rte.src); rt_lock_source(e->rte.src);
if (e->rte.attrs->cached) if (ea_is_cached(e->rte.attrs))
e->rte.attrs = rta_clone(e->rte.attrs); e->rte.attrs = rta_clone(e->rte.attrs);
else else
e->rte.attrs = rta_lookup(e->rte.attrs); e->rte.attrs = rta_lookup(e->rte.attrs);
@ -986,7 +986,7 @@ rt_export_merged(struct channel *c, struct rte **feed, uint count, linpool *pool
if (!tmp || !rte_is_reachable(tmp)) if (!tmp || !rte_is_reachable(tmp))
continue; continue;
eattr *nhea = ea_find(tmp->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(tmp->attrs, &ea_gen_nexthop);
ASSERT_DIE(nhea); ASSERT_DIE(nhea);
if (nhs) if (nhs)
@ -997,13 +997,12 @@ rt_export_merged(struct channel *c, struct rte **feed, uint count, linpool *pool
if (nhs) if (nhs)
{ {
eattr *nhea = ea_find(best->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(best->attrs, &ea_gen_nexthop);
ASSERT_DIE(nhea); ASSERT_DIE(nhea);
nhs = nexthop_merge(nhs, (struct nexthop_adata *) nhea->u.ptr, c->merge_limit, pool); nhs = nexthop_merge(nhs, (struct nexthop_adata *) nhea->u.ptr, c->merge_limit, pool);
best->attrs = rta_cow(best->attrs, pool); ea_set_attr(&best->attrs,
ea_set_attr(&best->attrs->eattrs,
EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nhs->ad)); EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nhs->ad));
} }
@ -1228,7 +1227,7 @@ rte_validate(struct channel *ch, rte *e)
if (net_type_match(n, NB_DEST)) if (net_type_match(n, NB_DEST))
{ {
eattr *nhea = ea_find(e->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(e->attrs, &ea_gen_nexthop);
int dest = nhea_dest(nhea); int dest = nhea_dest(nhea);
if (dest == RTD_NONE) if (dest == RTD_NONE)
@ -1246,7 +1245,7 @@ rte_validate(struct channel *ch, rte *e)
return 0; return 0;
} }
} }
else if (ea_find(e->attrs->eattrs, &ea_gen_nexthop)) else if (ea_find(e->attrs, &ea_gen_nexthop))
{ {
log(L_WARN "Ignoring route %N having a nexthop attribute received via %s", log(L_WARN "Ignoring route %N having a nexthop attribute received via %s",
n, ch->proto->name); n, ch->proto->name);
@ -1884,7 +1883,7 @@ rte_dump(struct rte_storage *e)
{ {
debug("%-1N ", e->rte.net); debug("%-1N ", e->rte.net);
debug("PF=%02x ", e->rte.pflags); debug("PF=%02x ", e->rte.pflags);
rta_dump(e->rte.attrs); ea_dump(e->rte.attrs);
debug("\n"); debug("\n");
} }
@ -2541,21 +2540,21 @@ ea_set_hostentry(ea_list **to, struct rtable *dep, struct rtable *tab, ip_addr g
static void static void
rta_apply_hostentry(rta *a, struct hostentry_adata *head) rta_apply_hostentry(ea_list **to, struct hostentry_adata *head)
{ {
struct hostentry *he = head->he; struct hostentry *he = head->he;
u32 *labels = head->labels; u32 *labels = head->labels;
u32 lnum = (u32 *) (head->ad.data + head->ad.length) - labels; u32 lnum = (u32 *) (head->ad.data + head->ad.length) - labels;
ea_set_attr_u32(&a->eattrs, &ea_gen_igp_metric, 0, he->igp_metric); ea_set_attr_u32(to, &ea_gen_igp_metric, 0, he->igp_metric);
if (!he->src) if (!he->src)
{ {
ea_set_dest(&a->eattrs, 0, RTD_UNREACHABLE); ea_set_dest(to, 0, RTD_UNREACHABLE);
return; return;
} }
eattr *he_nh_ea = ea_find(he->src->eattrs, &ea_gen_nexthop); eattr *he_nh_ea = ea_find(he->src, &ea_gen_nexthop);
ASSERT_DIE(he_nh_ea); ASSERT_DIE(he_nh_ea);
struct nexthop_adata *nhad = (struct nexthop_adata *) he_nh_ea->u.ptr; struct nexthop_adata *nhad = (struct nexthop_adata *) he_nh_ea->u.ptr;
@ -2564,7 +2563,7 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head)
if ((idest != RTD_UNICAST) || if ((idest != RTD_UNICAST) ||
!lnum && he->nexthop_linkable) !lnum && he->nexthop_linkable)
{ /* Just link the nexthop chain, no label append happens. */ { /* Just link the nexthop chain, no label append happens. */
ea_copy_attr(&a->eattrs, he->src->eattrs, &ea_gen_nexthop); ea_copy_attr(to, he->src, &ea_gen_nexthop);
return; return;
} }
@ -2591,7 +2590,7 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head)
.dest = RTD_UNREACHABLE, .dest = RTD_UNREACHABLE,
}; };
ea_set_attr_data(&a->eattrs, &ea_gen_nexthop, 0, &nha.ad.data, nha.ad.length); ea_set_attr_data(to, &ea_gen_nexthop, 0, &nha.ad.data, nha.ad.length);
return; return;
} }
@ -2625,22 +2624,22 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head)
/* Fix final length */ /* Fix final length */
new->ad.length = (void *) dest - (void *) new->ad.data; new->ad.length = (void *) dest - (void *) new->ad.data;
ea_set_attr(&a->eattrs, EA_LITERAL_DIRECT_ADATA( ea_set_attr(to, EA_LITERAL_DIRECT_ADATA(
&ea_gen_nexthop, 0, &new->ad)); &ea_gen_nexthop, 0, &new->ad));
} }
static inline struct hostentry_adata * static inline struct hostentry_adata *
rta_next_hop_outdated(rta *a) rta_next_hop_outdated(ea_list *a)
{ {
/* First retrieve the hostentry */ /* First retrieve the hostentry */
eattr *heea = ea_find(a->eattrs, &ea_gen_hostentry); eattr *heea = ea_find(a, &ea_gen_hostentry);
if (!heea) if (!heea)
return NULL; return NULL;
struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr; struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr;
/* If no nexthop is present, we have to create one */ /* If no nexthop is present, we have to create one */
eattr *a_nh_ea = ea_find(a->eattrs, &ea_gen_nexthop); eattr *a_nh_ea = ea_find(a, &ea_gen_nexthop);
if (!a_nh_ea) if (!a_nh_ea)
return head; return head;
@ -2651,10 +2650,10 @@ rta_next_hop_outdated(rta *a)
return NEXTHOP_IS_REACHABLE(nhad) ? head : NULL; return NEXTHOP_IS_REACHABLE(nhad) ? head : NULL;
/* Comparing our nexthop with the hostentry nexthop */ /* Comparing our nexthop with the hostentry nexthop */
eattr *he_nh_ea = ea_find(head->he->src->eattrs, &ea_gen_nexthop); eattr *he_nh_ea = ea_find(head->he->src, &ea_gen_nexthop);
return ( return (
(ea_get_int(a->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN) != head->he->igp_metric) || (ea_get_int(a, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN) != head->he->igp_metric) ||
(!head->he->nexthop_linkable) || (!head->he->nexthop_linkable) ||
(!he_nh_ea != !a_nh_ea) || (!he_nh_ea != !a_nh_ea) ||
(he_nh_ea && a_nh_ea && !adata_same(he_nh_ea->u.ptr, a_nh_ea->u.ptr))) (he_nh_ea && a_nh_ea && !adata_same(he_nh_ea->u.ptr, a_nh_ea->u.ptr)))
@ -2668,12 +2667,8 @@ rt_next_hop_update_rte(rtable *tab, net *n, rte *old)
if (!head) if (!head)
return NULL; return NULL;
rta a = *old->attrs;
a.cached = 0;
rta_apply_hostentry(&a, head);
rte e0 = *old; rte e0 = *old;
e0.attrs = &a; rta_apply_hostentry(&e0.attrs, head);
return rte_store(&e0, n, tab); return rte_store(&e0, n, tab);
} }
@ -2681,21 +2676,13 @@ rt_next_hop_update_rte(rtable *tab, net *n, rte *old)
static inline void static inline void
rt_next_hop_resolve_rte(rte *r) rt_next_hop_resolve_rte(rte *r)
{ {
eattr *heea = ea_find(r->attrs->eattrs, &ea_gen_hostentry); eattr *heea = ea_find(r->attrs, &ea_gen_hostentry);
if (!heea) if (!heea)
return; return;
struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr; struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr;
if (r->attrs->cached) rta_apply_hostentry(&r->attrs, head);
{
rta *a = tmp_alloc(RTA_MAX_SIZE);
*a = *r->attrs;
a->cached = 0;
r->attrs = a;
}
rta_apply_hostentry(r->attrs, head);
} }
#ifdef CONFIG_BGP #ifdef CONFIG_BGP
@ -2721,23 +2708,23 @@ net_flow_has_dst_prefix(const net_addr *n)
} }
static inline int static inline int
rta_as_path_is_empty(rta *a) rta_as_path_is_empty(ea_list *a)
{ {
eattr *e = ea_find(a->eattrs, "bgp_path"); eattr *e = ea_find(a, "bgp_path");
return !e || (as_path_getlen(e->u.ptr) == 0); return !e || (as_path_getlen(e->u.ptr) == 0);
} }
static inline u32 static inline u32
rta_get_first_asn(rta *a) rta_get_first_asn(ea_list *a)
{ {
eattr *e = ea_find(a->eattrs, "bgp_path"); eattr *e = ea_find(a, "bgp_path");
u32 asn; u32 asn;
return (e && as_path_get_first_regular(e->u.ptr, &asn)) ? asn : 0; return (e && as_path_get_first_regular(e->u.ptr, &asn)) ? asn : 0;
} }
static inline enum flowspec_valid static inline enum flowspec_valid
rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, int interior) rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, ea_list *a, int interior)
{ {
ASSERT(rt_is_ip(tab_ip)); ASSERT(rt_is_ip(tab_ip));
ASSERT(rt_is_flow(tab_flow)); ASSERT(rt_is_flow(tab_flow));
@ -2774,13 +2761,13 @@ rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, i
return FLOWSPEC_INVALID; return FLOWSPEC_INVALID;
/* Find ORIGINATOR_ID values */ /* Find ORIGINATOR_ID values */
u32 orig_a = ea_get_int(a->eattrs, "bgp_originator_id", 0); u32 orig_a = ea_get_int(a, "bgp_originator_id", 0);
u32 orig_b = ea_get_int(rb->attrs->eattrs, "bgp_originator_id", 0); u32 orig_b = ea_get_int(rb->attrs, "bgp_originator_id", 0);
/* Originator is either ORIGINATOR_ID (if present), or BGP neighbor address (if not) */ /* Originator is either ORIGINATOR_ID (if present), or BGP neighbor address (if not) */
if ((orig_a != orig_b) || (!orig_a && !orig_b && !ipa_equal( if ((orig_a != orig_b) || (!orig_a && !orig_b && !ipa_equal(
ea_get_ip(a->eattrs, &ea_gen_from, IPA_NONE), ea_get_ip(a, &ea_gen_from, IPA_NONE),
ea_get_ip(rb->attrs->eattrs, &ea_gen_from, IPA_NONE) ea_get_ip(rb->attrs, &ea_gen_from, IPA_NONE)
))) )))
return FLOWSPEC_INVALID; return FLOWSPEC_INVALID;
@ -2834,15 +2821,8 @@ rt_flowspec_update_rte(rtable *tab, net *n, rte *r)
if (old == valid) if (old == valid)
return NULL; return NULL;
rta *a = alloca(RTA_MAX_SIZE); rte new = *r;
*a = *r->attrs; ea_set_attr_u32(&new.attrs, &ea_gen_flowspec_valid, 0, valid);
a->cached = 0;
ea_set_attr_u32(&a->eattrs, &ea_gen_flowspec_valid, 0, valid);
rte new;
memcpy(&new, r, sizeof(rte));
new.attrs = a;
return rte_store(&new, n, tab); return rte_store(&new, n, tab);
#else #else
@ -2873,18 +2853,10 @@ rt_flowspec_resolve_rte(rte *r, struct channel *c)
if (valid == old) if (valid == old)
return; return;
if (r->attrs->cached)
{
rta *a = tmp_alloc(RTA_MAX_SIZE);
*a = *r->attrs;
a->cached = 0;
r->attrs = a;
}
if (valid == FLOWSPEC_UNKNOWN) if (valid == FLOWSPEC_UNKNOWN)
ea_unset_attr(&r->attrs->eattrs, 0, &ea_gen_flowspec_valid); ea_unset_attr(&r->attrs, 0, &ea_gen_flowspec_valid);
else else
ea_set_attr_u32(&r->attrs->eattrs, &ea_gen_flowspec_valid, 0, valid); ea_set_attr_u32(&r->attrs, &ea_gen_flowspec_valid, 0, valid);
#endif #endif
} }
@ -3652,7 +3624,7 @@ if_local_addr(ip_addr a, struct iface *i)
u32 u32
rt_get_igp_metric(const rte *rt) rt_get_igp_metric(const rte *rt)
{ {
eattr *ea = ea_find(rt->attrs->eattrs, "igp_metric"); eattr *ea = ea_find(rt->attrs, "igp_metric");
if (ea) if (ea)
return ea->u.data; return ea->u.data;
@ -3669,7 +3641,7 @@ rt_get_igp_metric(const rte *rt)
static int static int
rt_update_hostentry(rtable *tab, struct hostentry *he) rt_update_hostentry(rtable *tab, struct hostentry *he)
{ {
rta *old_src = he->src; ea_list *old_src = he->src;
int direct = 0; int direct = 0;
int pxlen = 0; int pxlen = 0;
@ -3684,10 +3656,10 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
if (n) if (n)
{ {
struct rte_storage *e = n->routes; struct rte_storage *e = n->routes;
rta *a = e->rte.attrs; ea_list *a = e->rte.attrs;
pxlen = n->n.addr->pxlen; pxlen = n->n.addr->pxlen;
if (ea_find(a->eattrs, &ea_gen_hostentry)) if (ea_find(a, &ea_gen_hostentry))
{ {
/* Recursive route should not depend on another recursive route */ /* Recursive route should not depend on another recursive route */
log(L_WARN "Next hop address %I resolvable through recursive route for %N", log(L_WARN "Next hop address %I resolvable through recursive route for %N",
@ -3695,7 +3667,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
goto done; goto done;
} }
eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(a, &ea_gen_nexthop);
ASSERT_DIE(nhea); ASSERT_DIE(nhea);
struct nexthop_adata *nhad = (void *) nhea->u.ptr; struct nexthop_adata *nhad = (void *) nhea->u.ptr;

View File

@ -147,7 +147,7 @@ struct hostentry {
struct hostentry *next; /* Next in hash chain */ struct hostentry *next; /* Next in hash chain */
unsigned hash_key; /* Hash key */ unsigned hash_key; /* Hash key */
unsigned uc; /* Use count */ unsigned uc; /* Use count */
struct rta *src; /* Source rta entry */ ea_list *src; /* Source attributes */
byte nexthop_linkable; /* Nexthop list is completely non-device */ byte nexthop_linkable; /* Nexthop list is completely non-device */
u32 igp_metric; /* Chosen route IGP metric */ u32 igp_metric; /* Chosen route IGP metric */
}; };
@ -448,16 +448,6 @@ struct hostentry_adata {
void void
ea_set_hostentry(ea_list **to, struct rtable *dep, struct rtable *tab, ip_addr gw, ip_addr ll, u32 lnum, u32 labels[lnum]); ea_set_hostentry(ea_list **to, struct rtable *dep, struct rtable *tab, ip_addr gw, ip_addr ll, u32 lnum, u32 labels[lnum]);
/*
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
void rta_apply_hostentry(rta *a, struct hostentry *he, u32 lnum, u32 labels[lnum]);
static inline void
rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, u32 lnum, u32 labels[lnum])
{
rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), lnum, labels);
}
*/
/* /*
* Default protocol preferences * Default protocol preferences

View File

@ -677,10 +677,8 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
} }
}; };
rta a0 = { .eattrs = &eattrs.l, };
rte e0 = { rte e0 = {
.attrs = &a0, .attrs = &eattrs.l,
.src = p->p.main_source, .src = p->p.main_source,
}; };
@ -690,14 +688,14 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
else if (e->valid && (e->router_id != p->router_id)) else if (e->valid && (e->router_id != p->router_id))
{ {
/* Unreachable */ /* Unreachable */
rta a0 = {}; ea_list *ea = NULL;
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, 1); ea_set_attr_u32(&ea, &ea_gen_preference, 0, 1);
ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_BABEL); ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_BABEL);
ea_set_dest(&a0.eattrs, 0, RTD_UNREACHABLE); ea_set_dest(&ea, 0, RTD_UNREACHABLE);
rte e0 = { rte e0 = {
.attrs = &a0, .attrs = ea,
.src = p->p.main_source, .src = p->p.main_source,
}; };
@ -2028,13 +2026,13 @@ static void
babel_get_route_info(rte *rte, byte *buf) babel_get_route_info(rte *rte, byte *buf)
{ {
u64 rid = 0; u64 rid = 0;
eattr *e = ea_find(rte->attrs->eattrs, &ea_babel_router_id); eattr *e = ea_find(rte->attrs, &ea_babel_router_id);
if (e) if (e)
memcpy(&rid, e->u.ptr->data, sizeof(u64)); memcpy(&rid, e->u.ptr->data, sizeof(u64));
buf += bsprintf(buf, " (%d/%d) [%lR]", buf += bsprintf(buf, " (%d/%d) [%lR]",
rt_get_preference(rte), rt_get_preference(rte),
ea_get_int(rte->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY), rid); ea_get_int(rte->attrs, &ea_babel_metric, BABEL_INFINITY), rid);
} }
static void static void
@ -2266,7 +2264,7 @@ babel_preexport(struct channel *c, struct rte *new)
return 0; return 0;
/* Reject our own unreachable routes */ /* Reject our own unreachable routes */
eattr *ea = ea_find(new->attrs->eattrs, &ea_gen_nexthop); eattr *ea = ea_find(new->attrs, &ea_gen_nexthop);
struct nexthop_adata *nhad = (void *) ea->u.ptr; struct nexthop_adata *nhad = (void *) ea->u.ptr;
if (!NEXTHOP_IS_REACHABLE(nhad)) if (!NEXTHOP_IS_REACHABLE(nhad))
return -1; return -1;
@ -2289,13 +2287,13 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
{ {
/* Update */ /* Update */
uint rt_seqno; uint rt_seqno;
uint rt_metric = ea_get_int(new->attrs->eattrs, &ea_babel_metric, 0); uint rt_metric = ea_get_int(new->attrs, &ea_babel_metric, 0);
u64 rt_router_id = 0; u64 rt_router_id = 0;
if (new->src->proto == P) if (new->src->proto == P)
{ {
rt_seqno = ea_get_int(new->attrs->eattrs, &ea_babel_seqno, 0); rt_seqno = ea_get_int(new->attrs, &ea_babel_seqno, 0);
eattr *e = ea_find(new->attrs->eattrs, &ea_babel_router_id); eattr *e = ea_find(new->attrs, &ea_babel_router_id);
if (e) if (e)
memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64)); memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64));
} }
@ -2346,8 +2344,8 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
static int static int
babel_rte_better(struct rte *new, struct rte *old) babel_rte_better(struct rte *new, struct rte *old)
{ {
uint new_metric = ea_get_int(new->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY); uint new_metric = ea_get_int(new->attrs, &ea_babel_metric, BABEL_INFINITY);
uint old_metric = ea_get_int(old->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY); uint old_metric = ea_get_int(old->attrs, &ea_babel_metric, BABEL_INFINITY);
return new_metric < old_metric; return new_metric < old_metric;
} }
@ -2355,7 +2353,7 @@ babel_rte_better(struct rte *new, struct rte *old)
static u32 static u32
babel_rte_igp_metric(const rte *rt) babel_rte_igp_metric(const rte *rt)
{ {
return ea_get_int(rt->attrs->eattrs, &ea_babel_metric, BABEL_INFINITY); return ea_get_int(rt->attrs, &ea_babel_metric, BABEL_INFINITY);
} }

View File

@ -374,26 +374,24 @@ bgp_aigp_set_metric(struct linpool *pool, const struct adata *ad, u64 metric)
int int
bgp_total_aigp_metric_(const rte *e, u64 *metric, const struct adata **ad) bgp_total_aigp_metric_(const rte *e, u64 *metric, const struct adata **ad)
{ {
rta *a = e->attrs; eattr *a = ea_find(e->attrs, BGP_EA_ID(BA_AIGP));
if (!a)
eattr *ea = ea_find(a->eattrs, BGP_EA_ID(BA_AIGP));
if (!ea)
return 0; return 0;
const byte *b = bgp_aigp_get_tlv(ea->u.ptr, BGP_AIGP_METRIC); const byte *b = bgp_aigp_get_tlv(a->u.ptr, BGP_AIGP_METRIC);
if (!b) if (!b)
return 0; return 0;
u64 aigp = get_u64(b + 3); u64 aigp = get_u64(b + 3);
u64 step = rt_get_igp_metric(e); u64 step = rt_get_igp_metric(e);
if (!rta_resolvable(a) || (step >= IGP_METRIC_UNKNOWN)) if (!rte_resolvable(e) || (step >= IGP_METRIC_UNKNOWN))
step = BGP_AIGP_MAX; step = BGP_AIGP_MAX;
if (!step) if (!step)
step = 1; step = 1;
*ad = ea->u.ptr; *ad = a->u.ptr;
*metric = aigp + step; *metric = aigp + step;
if (*metric < aigp) if (*metric < aigp)
*metric = BGP_AIGP_MAX; *metric = BGP_AIGP_MAX;
@ -1494,13 +1492,13 @@ loop:
} }
void void
bgp_finish_attrs(struct bgp_parse_state *s, rta *a) bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to)
{ {
/* AIGP test here instead of in bgp_decode_aigp() - we need to know channel */ /* AIGP test here instead of in bgp_decode_aigp() - we need to know channel */
if (BIT32_TEST(s->attrs_seen, BA_AIGP) && !s->channel->cf->aigp) if (BIT32_TEST(s->attrs_seen, BA_AIGP) && !s->channel->cf->aigp)
{ {
REPORT("Discarding AIGP attribute received on non-AIGP session"); REPORT("Discarding AIGP attribute received on non-AIGP session");
bgp_unset_attr(&a->eattrs, BA_AIGP); bgp_unset_attr(to, BA_AIGP);
} }
} }
@ -1739,14 +1737,14 @@ bgp_preexport(struct channel *c, rte *e)
/* Generally, this should be handled when path is received, but we check it /* Generally, this should be handled when path is received, but we check it
also here as rr_cluster_id may be undefined or different in src. */ also here as rr_cluster_id may be undefined or different in src. */
if (p->rr_cluster_id && bgp_cluster_list_loopy(p, e->attrs->eattrs)) if (p->rr_cluster_id && bgp_cluster_list_loopy(p, e->attrs))
return -1; return -1;
} }
/* Handle well-known communities, RFC 1997 */ /* Handle well-known communities, RFC 1997 */
struct eattr *com; struct eattr *com;
if (p->cf->interpret_communities && if (p->cf->interpret_communities &&
(com = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY)))) (com = ea_find(e->attrs, BGP_EA_ID(BA_COMMUNITY))))
{ {
const struct adata *d = com->u.ptr; const struct adata *d = com->u.ptr;
@ -1897,7 +1895,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c
if (new) if (new)
{ {
struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, tmp_linpool); struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs, tmp_linpool);
/* Error during attribute processing */ /* Error during attribute processing */
if (!attrs) if (!attrs)
@ -1923,7 +1921,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, c
static inline u32 static inline u32
bgp_get_neighbor(rte *r) bgp_get_neighbor(rte *r)
{ {
eattr *e = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); eattr *e = ea_find(r->attrs, BGP_EA_ID(BA_AS_PATH));
u32 as; u32 as;
if (e && as_path_get_first_regular(e->u.ptr, &as)) if (e && as_path_get_first_regular(e->u.ptr, &as))
@ -1944,7 +1942,7 @@ rte_stale(rte *r)
return 0; return 0;
/* If staleness is unknown, compute and cache it */ /* If staleness is unknown, compute and cache it */
eattr *a = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY)); eattr *a = ea_find(r->attrs, BGP_EA_ID(BA_COMMUNITY));
if (a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE)) if (a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE))
{ {
r->pflags |= BGP_REF_STALE; r->pflags |= BGP_REF_STALE;
@ -1974,8 +1972,8 @@ bgp_rte_better(rte *new, rte *old)
return 1; return 1;
/* RFC 4271 9.1.2.1. Route resolvability test */ /* RFC 4271 9.1.2.1. Route resolvability test */
n = rta_resolvable(new->attrs); n = rte_resolvable(new);
o = rta_resolvable(old->attrs); o = rte_resolvable(old);
if (n > o) if (n > o)
return 1; return 1;
if (n < o) if (n < o)
@ -1990,8 +1988,8 @@ bgp_rte_better(rte *new, rte *old)
return 1; return 1;
/* Start with local preferences */ /* Start with local preferences */
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF)); x = ea_find(new->attrs, BGP_EA_ID(BA_LOCAL_PREF));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF)); y = ea_find(old->attrs, BGP_EA_ID(BA_LOCAL_PREF));
n = x ? x->u.data : new_bgp->cf->default_local_pref; n = x ? x->u.data : new_bgp->cf->default_local_pref;
o = y ? y->u.data : old_bgp->cf->default_local_pref; o = y ? y->u.data : old_bgp->cf->default_local_pref;
if (n > o) if (n > o)
@ -2010,8 +2008,8 @@ bgp_rte_better(rte *new, rte *old)
/* RFC 4271 9.1.2.2. a) Use AS path lengths */ /* RFC 4271 9.1.2.2. a) Use AS path lengths */
if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths) if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths)
{ {
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); x = ea_find(new->attrs, BGP_EA_ID(BA_AS_PATH));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); y = ea_find(old->attrs, BGP_EA_ID(BA_AS_PATH));
n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN; n = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN; o = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
if (n < o) if (n < o)
@ -2021,8 +2019,8 @@ bgp_rte_better(rte *new, rte *old)
} }
/* RFC 4271 9.1.2.2. b) Use origins */ /* RFC 4271 9.1.2.2. b) Use origins */
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_ORIGIN)); x = ea_find(new->attrs, BGP_EA_ID(BA_ORIGIN));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_ORIGIN)); y = ea_find(old->attrs, BGP_EA_ID(BA_ORIGIN));
n = x ? x->u.data : ORIGIN_INCOMPLETE; n = x ? x->u.data : ORIGIN_INCOMPLETE;
o = y ? y->u.data : ORIGIN_INCOMPLETE; o = y ? y->u.data : ORIGIN_INCOMPLETE;
if (n < o) if (n < o)
@ -2044,8 +2042,8 @@ bgp_rte_better(rte *new, rte *old)
if (new_bgp->cf->med_metric || old_bgp->cf->med_metric || if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
(bgp_get_neighbor(new) == bgp_get_neighbor(old))) (bgp_get_neighbor(new) == bgp_get_neighbor(old)))
{ {
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC)); x = ea_find(new->attrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC)); y = ea_find(old->attrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
n = x ? x->u.data : new_bgp->cf->default_med; n = x ? x->u.data : new_bgp->cf->default_med;
o = y ? y->u.data : old_bgp->cf->default_med; o = y ? y->u.data : old_bgp->cf->default_med;
if (n < o) if (n < o)
@ -2070,8 +2068,8 @@ bgp_rte_better(rte *new, rte *old)
/* RFC 4271 9.1.2.2. f) Compare BGP identifiers */ /* RFC 4271 9.1.2.2. f) Compare BGP identifiers */
/* RFC 4456 9. a) Use ORIGINATOR_ID instead of local neighbor ID */ /* RFC 4456 9. a) Use ORIGINATOR_ID instead of local neighbor ID */
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_ORIGINATOR_ID)); x = ea_find(new->attrs, BGP_EA_ID(BA_ORIGINATOR_ID));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_ORIGINATOR_ID)); y = ea_find(old->attrs, BGP_EA_ID(BA_ORIGINATOR_ID));
n = x ? x->u.data : new_bgp->remote_id; n = x ? x->u.data : new_bgp->remote_id;
o = y ? y->u.data : old_bgp->remote_id; o = y ? y->u.data : old_bgp->remote_id;
@ -2088,8 +2086,8 @@ bgp_rte_better(rte *new, rte *old)
return 0; return 0;
/* RFC 4456 9. b) Compare cluster list lengths */ /* RFC 4456 9. b) Compare cluster list lengths */
x = ea_find(new->attrs->eattrs, BGP_EA_ID(BA_CLUSTER_LIST)); x = ea_find(new->attrs, BGP_EA_ID(BA_CLUSTER_LIST));
y = ea_find(old->attrs->eattrs, BGP_EA_ID(BA_CLUSTER_LIST)); y = ea_find(old->attrs, BGP_EA_ID(BA_CLUSTER_LIST));
n = x ? int_set_get_size(x->u.ptr) : 0; n = x ? int_set_get_size(x->u.ptr) : 0;
o = y ? int_set_get_size(y->u.ptr) : 0; o = y ? int_set_get_size(y->u.ptr) : 0;
if (n < o) if (n < o)
@ -2115,7 +2113,7 @@ bgp_rte_mergable(rte *pri, rte *sec)
return 0; return 0;
/* RFC 4271 9.1.2.1. Route resolvability test */ /* RFC 4271 9.1.2.1. Route resolvability test */
if (rta_resolvable(pri->attrs) != rta_resolvable(sec->attrs)) if (rte_resolvable(pri) != rte_resolvable(sec))
return 0; return 0;
/* LLGR draft - depreference stale routes */ /* LLGR draft - depreference stale routes */
@ -2123,8 +2121,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
return 0; return 0;
/* Start with local preferences */ /* Start with local preferences */
x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF)); x = ea_find(pri->attrs, BGP_EA_ID(BA_LOCAL_PREF));
y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_LOCAL_PREF)); y = ea_find(sec->attrs, BGP_EA_ID(BA_LOCAL_PREF));
p = x ? x->u.data : pri_bgp->cf->default_local_pref; p = x ? x->u.data : pri_bgp->cf->default_local_pref;
s = y ? y->u.data : sec_bgp->cf->default_local_pref; s = y ? y->u.data : sec_bgp->cf->default_local_pref;
if (p != s) if (p != s)
@ -2133,8 +2131,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
/* RFC 4271 9.1.2.2. a) Use AS path lengths */ /* RFC 4271 9.1.2.2. a) Use AS path lengths */
if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths) if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths)
{ {
x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); x = ea_find(pri->attrs, BGP_EA_ID(BA_AS_PATH));
y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); y = ea_find(sec->attrs, BGP_EA_ID(BA_AS_PATH));
p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN; p = x ? as_path_getlen(x->u.ptr) : AS_PATH_MAXLEN;
s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN; s = y ? as_path_getlen(y->u.ptr) : AS_PATH_MAXLEN;
@ -2146,8 +2144,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
} }
/* RFC 4271 9.1.2.2. b) Use origins */ /* RFC 4271 9.1.2.2. b) Use origins */
x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_ORIGIN)); x = ea_find(pri->attrs, BGP_EA_ID(BA_ORIGIN));
y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_ORIGIN)); y = ea_find(sec->attrs, BGP_EA_ID(BA_ORIGIN));
p = x ? x->u.data : ORIGIN_INCOMPLETE; p = x ? x->u.data : ORIGIN_INCOMPLETE;
s = y ? y->u.data : ORIGIN_INCOMPLETE; s = y ? y->u.data : ORIGIN_INCOMPLETE;
if (p != s) if (p != s)
@ -2157,8 +2155,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric || if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric ||
(bgp_get_neighbor(pri) == bgp_get_neighbor(sec))) (bgp_get_neighbor(pri) == bgp_get_neighbor(sec)))
{ {
x = ea_find(pri->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC)); x = ea_find(pri->attrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
y = ea_find(sec->attrs->eattrs, BGP_EA_ID(BA_MULTI_EXIT_DISC)); y = ea_find(sec->attrs, BGP_EA_ID(BA_MULTI_EXIT_DISC));
p = x ? x->u.data : pri_bgp->cf->default_med; p = x ? x->u.data : pri_bgp->cf->default_med;
s = y ? y->u.data : sec_bgp->cf->default_med; s = y ? y->u.data : sec_bgp->cf->default_med;
if (p != s) if (p != s)
@ -2323,7 +2321,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
rte * rte *
bgp_rte_modify_stale(struct rte *r, struct linpool *pool) bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
{ {
eattr *ea = ea_find(r->attrs->eattrs, BGP_EA_ID(BA_COMMUNITY)); eattr *ea = ea_find(r->attrs, BGP_EA_ID(BA_COMMUNITY));
const struct adata *ad = ea ? ea->u.ptr : NULL; const struct adata *ad = ea ? ea->u.ptr : NULL;
uint flags = ea ? ea->flags : BAF_PARTIAL; uint flags = ea ? ea->flags : BAF_PARTIAL;
@ -2333,13 +2331,10 @@ bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
if (ad && int_set_contains(ad, BGP_COMM_LLGR_STALE)) if (ad && int_set_contains(ad, BGP_COMM_LLGR_STALE))
return r; return r;
rta *a = rta_do_cow(r->attrs, pool);
_Thread_local static rte e0; _Thread_local static rte e0;
e0 = *r; e0 = *r;
e0.attrs = a;
bgp_set_attr_ptr(&(a->eattrs), BA_COMMUNITY, flags, bgp_set_attr_ptr(&e0.attrs, BA_COMMUNITY, flags,
int_set_add(pool, ad, BGP_COMM_LLGR_STALE)); int_set_add(pool, ad, BGP_COMM_LLGR_STALE));
e0.pflags |= BGP_REF_STALE; e0.pflags |= BGP_REF_STALE;
@ -2396,8 +2391,8 @@ bgp_process_as4_attrs(ea_list **attrs, struct linpool *pool)
void void
bgp_get_route_info(rte *e, byte *buf) bgp_get_route_info(rte *e, byte *buf)
{ {
eattr *p = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_AS_PATH)); eattr *p = ea_find(e->attrs, BGP_EA_ID(BA_AS_PATH));
eattr *o = ea_find(e->attrs->eattrs, BGP_EA_ID(BA_ORIGIN)); eattr *o = ea_find(e->attrs, BGP_EA_ID(BA_ORIGIN));
u32 origas; u32 origas;
buf += bsprintf(buf, " (%d", rt_get_preference(e)); buf += bsprintf(buf, " (%d", rt_get_preference(e));
@ -2417,7 +2412,7 @@ bgp_get_route_info(rte *e, byte *buf)
} }
else if (metric = rt_get_igp_metric(e)) else if (metric = rt_get_igp_metric(e))
{ {
if (!rta_resolvable(e->attrs)) if (!rte_resolvable(e))
buf += bsprintf(buf, "/-"); buf += bsprintf(buf, "/-");
else if (metric >= IGP_METRIC_UNKNOWN) else if (metric >= IGP_METRIC_UNKNOWN)
buf += bsprintf(buf, "/?"); buf += bsprintf(buf, "/?");

View File

@ -67,10 +67,10 @@ struct bgp_af_desc {
u8 no_igp; u8 no_igp;
const char *name; const char *name;
uint (*encode_nlri)(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size); uint (*encode_nlri)(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size);
void (*decode_nlri)(struct bgp_parse_state *s, byte *pos, uint len, rta *a); void (*decode_nlri)(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a);
void (*update_next_hop)(struct bgp_export_state *s, eattr *nh, ea_list **to); void (*update_next_hop)(struct bgp_export_state *s, eattr *nh, ea_list **to);
uint (*encode_next_hop)(struct bgp_write_state *s, eattr *nh, byte *buf, uint size); uint (*encode_next_hop)(struct bgp_write_state *s, eattr *nh, byte *buf, uint size);
void (*decode_next_hop)(struct bgp_parse_state *s, byte *pos, uint len, rta *a); void (*decode_next_hop)(struct bgp_parse_state *s, byte *pos, uint len, ea_list **to);
}; };
@ -461,7 +461,7 @@ struct bgp_parse_state {
/* Cached state for bgp_rte_update() */ /* Cached state for bgp_rte_update() */
u32 last_id; u32 last_id;
struct rte_src *last_src; struct rte_src *last_src;
rta *cached_rta; ea_list *cached_ea;
}; };
#define BGP_PORT 179 #define BGP_PORT 179
@ -517,9 +517,9 @@ struct rte_source *bgp_find_source(struct bgp_proto *p, u32 path_id);
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id); struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
static inline int static inline int
rta_resolvable(rta *a) rte_resolvable(const rte *rt)
{ {
eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(rt->attrs, &ea_gen_nexthop);
struct nexthop_adata *nhad = (void *) nhea->u.ptr; struct nexthop_adata *nhad = (void *) nhea->u.ptr;
return NEXTHOP_IS_REACHABLE(nhad) || (nhad->dest != RTD_UNREACHABLE); return NEXTHOP_IS_REACHABLE(nhad) || (nhad->dest != RTD_UNREACHABLE);
} }
@ -551,7 +551,7 @@ int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint
int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end); int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end);
ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len); ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len);
void bgp_finish_attrs(struct bgp_parse_state *s, rta *a); void bgp_finish_attrs(struct bgp_parse_state *s, ea_list **to);
void bgp_init_bucket_table(struct bgp_channel *c); void bgp_init_bucket_table(struct bgp_channel *c);
void bgp_free_bucket_table(struct bgp_channel *c); void bgp_free_bucket_table(struct bgp_channel *c);

View File

@ -943,7 +943,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
#define MISMATCHED_AF " - mismatched address family (%I for %s)" #define MISMATCHED_AF " - mismatched address family (%I for %s)"
static void static void
bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll) bgp_apply_next_hop(struct bgp_parse_state *s, ea_list **to, ip_addr gw, ip_addr ll)
{ {
struct bgp_proto *p = s->proto; struct bgp_proto *p = s->proto;
struct bgp_channel *c = s->channel; struct bgp_channel *c = s->channel;
@ -966,7 +966,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
if (nbr->scope == SCOPE_HOST) if (nbr->scope == SCOPE_HOST)
WITHDRAW(BAD_NEXT_HOP " - address %I is local", nbr->addr); WITHDRAW(BAD_NEXT_HOP " - address %I is local", nbr->addr);
ea_set_attr_u32(&a->eattrs, &ea_gen_igp_metric, 0, c->cf->cost); ea_set_attr_u32(to, &ea_gen_igp_metric, 0, c->cf->cost);
struct nexthop_adata nhad = { struct nexthop_adata nhad = {
.nh = { .nh = {
@ -977,7 +977,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
.length = sizeof nhad - sizeof nhad.ad, .length = sizeof nhad - sizeof nhad.ad,
}, },
}; };
ea_set_attr_data(&a->eattrs, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length); ea_set_attr_data(to, &ea_gen_nexthop, 0, nhad.ad.data, nhad.ad.length);
} }
else /* GW_RECURSIVE */ else /* GW_RECURSIVE */
{ {
@ -988,21 +988,21 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
if (s->mpls) if (s->mpls)
{ {
u32 labels[BGP_MPLS_MAX]; u32 labels[BGP_MPLS_MAX];
ea_set_hostentry(&a->eattrs, c->c.table, tab, gw, ll, BGP_MPLS_MAX, labels); ea_set_hostentry(to, c->c.table, tab, gw, ll, BGP_MPLS_MAX, labels);
} }
else else
ea_set_hostentry(&a->eattrs, c->c.table, tab, gw, ll, 0, NULL); ea_set_hostentry(to, c->c.table, tab, gw, ll, 0, NULL);
} }
} }
static void static void
bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 lnum, u32 labels[lnum]) bgp_apply_mpls_labels(struct bgp_parse_state *s, ea_list **to, u32 lnum, u32 labels[lnum])
{ {
if (lnum > MPLS_MAX_LABEL_STACK) if (lnum > MPLS_MAX_LABEL_STACK)
{ {
REPORT("Too many MPLS labels ($u)", lnum); REPORT("Too many MPLS labels ($u)", lnum);
ea_set_dest(&a->eattrs, 0, RTD_UNREACHABLE); ea_set_dest(to, 0, RTD_UNREACHABLE);
return; return;
} }
@ -1012,7 +1012,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 lnum, u32 labels[ln
if (s->channel->cf->gw_mode == GW_DIRECT) if (s->channel->cf->gw_mode == GW_DIRECT)
{ {
eattr *e = ea_find(a->eattrs, &ea_gen_nexthop); eattr *e = ea_find(*to, &ea_gen_nexthop);
struct { struct {
struct nexthop_adata nhad; struct nexthop_adata nhad;
u32 labels[MPLS_MAX_LABEL_STACK]; u32 labels[MPLS_MAX_LABEL_STACK];
@ -1025,7 +1025,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 lnum, u32 labels[ln
} }
else /* GW_RECURSIVE */ else /* GW_RECURSIVE */
{ {
eattr *e = ea_find(a->eattrs, &ea_gen_hostentry); eattr *e = ea_find(*to, &ea_gen_hostentry);
ASSERT_DIE(e); ASSERT_DIE(e);
struct hostentry_adata *head = (void *) e->u.ptr; struct hostentry_adata *head = (void *) e->u.ptr;
memcpy(&head->labels, labels, lnum * sizeof(u32)); memcpy(&head->labels, labels, lnum * sizeof(u32));
@ -1084,13 +1084,13 @@ bgp_use_gateway(struct bgp_export_state *s)
{ {
struct bgp_proto *p = s->proto; struct bgp_proto *p = s->proto;
struct bgp_channel *c = s->channel; struct bgp_channel *c = s->channel;
rta *ra = s->route->attrs; ea_list *ra = s->route->attrs;
/* Handle next hop self option - also applies to gateway */ /* Handle next hop self option - also applies to gateway */
if (c->cf->next_hop_self && bgp_match_src(s, c->cf->next_hop_self)) if (c->cf->next_hop_self && bgp_match_src(s, c->cf->next_hop_self))
return NULL; return NULL;
eattr *nhea = ea_find(ra->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(ra, &ea_gen_nexthop);
if (!nhea) if (!nhea)
return NULL; return NULL;
@ -1208,7 +1208,7 @@ bgp_encode_next_hop_ip(struct bgp_write_state *s, eattr *a, byte *buf, uint size
} }
static void static void
bgp_decode_next_hop_ip(struct bgp_parse_state *s, byte *data, uint len, rta *a) bgp_decode_next_hop_ip(struct bgp_parse_state *s, byte *data, uint len, ea_list **to)
{ {
struct bgp_channel *c = s->channel; struct bgp_channel *c = s->channel;
struct adata *ad = lp_alloc_adata(s->pool, 32); struct adata *ad = lp_alloc_adata(s->pool, 32);
@ -1249,8 +1249,8 @@ bgp_decode_next_hop_ip(struct bgp_parse_state *s, byte *data, uint len, rta *a)
// XXXX validate next hop // XXXX validate next hop
bgp_set_attr_ptr(&(a->eattrs), BA_NEXT_HOP, 0, ad); bgp_set_attr_ptr(to, BA_NEXT_HOP, 0, ad);
bgp_apply_next_hop(s, a, nh[0], nh[1]); bgp_apply_next_hop(s, to, nh[0], nh[1]);
} }
static uint static uint
@ -1288,7 +1288,7 @@ bgp_encode_next_hop_vpn(struct bgp_write_state *s, eattr *a, byte *buf, uint siz
} }
static void static void
bgp_decode_next_hop_vpn(struct bgp_parse_state *s, byte *data, uint len, rta *a) bgp_decode_next_hop_vpn(struct bgp_parse_state *s, byte *data, uint len, ea_list **to)
{ {
struct bgp_channel *c = s->channel; struct bgp_channel *c = s->channel;
struct adata *ad = lp_alloc_adata(s->pool, 32); struct adata *ad = lp_alloc_adata(s->pool, 32);
@ -1330,8 +1330,8 @@ bgp_decode_next_hop_vpn(struct bgp_parse_state *s, byte *data, uint len, rta *a)
// XXXX validate next hop // XXXX validate next hop
bgp_set_attr_ptr(&(a->eattrs), BA_NEXT_HOP, 0, ad); bgp_set_attr_ptr(to, BA_NEXT_HOP, 0, ad);
bgp_apply_next_hop(s, a, nh[0], nh[1]); bgp_apply_next_hop(s, to, nh[0], nh[1]);
} }
@ -1343,7 +1343,7 @@ bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte
} }
static void static void
bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED) bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED)
{ {
/* /*
* Although we expect no next hop and RFC 7606 7.11 states that attribute * Although we expect no next hop and RFC 7606 7.11 states that attribute
@ -1368,15 +1368,15 @@ bgp_update_next_hop_none(struct bgp_export_state *s UNUSED, eattr *a, ea_list **
*/ */
static void static void
bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a0) bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, ea_list *a0)
{ {
if (path_id != s->last_id) if (path_id != s->last_id)
{ {
s->last_src = rt_get_source(&s->proto->p, path_id); s->last_src = rt_get_source(&s->proto->p, path_id);
s->last_id = path_id; s->last_id = path_id;
rta_free(s->cached_rta); ea_free(s->cached_ea);
s->cached_rta = NULL; s->cached_ea = NULL;
} }
if (!a0) if (!a0)
@ -1391,16 +1391,11 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a
} }
/* Prepare cached route attributes */ /* Prepare cached route attributes */
if (s->cached_rta == NULL) if (s->cached_ea == NULL)
{ s->cached_ea = ea_lookup(a0);
/* Workaround for rta_lookup() breaking eattrs */
ea_list *ea = a0->eattrs;
s->cached_rta = rta_lookup(a0);
a0->eattrs = ea;
}
rte e0 = { rte e0 = {
.attrs = s->cached_rta, .attrs = s->cached_ea,
.src = s->last_src, .src = s->last_src,
}; };
@ -1427,7 +1422,7 @@ bgp_encode_mpls_labels(struct bgp_write_state *s UNUSED, const adata *mpls, byte
} }
static void static void
bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *pxlen, rta *a) bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *pxlen, ea_list **to)
{ {
u32 labels[BGP_MPLS_MAX]; u32 labels[BGP_MPLS_MAX];
u32 label; u32 label;
@ -1449,15 +1444,15 @@ bgp_decode_mpls_labels(struct bgp_parse_state *s, byte **pos, uint *len, uint *p
} }
while (!(label & BGP_MPLS_BOS)); while (!(label & BGP_MPLS_BOS));
if (!a) if (!*to)
return; return;
/* Update next hop entry in rta */ /* Update next hop entry in rta */
bgp_apply_mpls_labels(s, a, lnum, labels); bgp_apply_mpls_labels(s, to, lnum, labels);
/* Attributes were changed, invalidate cached entry */ /* Attributes were changed, invalidate cached entry */
rta_free(s->cached_rta); rta_free(s->cached_ea);
s->cached_rta = NULL; s->cached_ea = NULL;
return; return;
} }
@ -1500,7 +1495,7 @@ bgp_encode_nlri_ip4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
} }
static void static void
bgp_decode_nlri_ip4(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_ip4(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -1526,7 +1521,7 @@ bgp_decode_nlri_ip4(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
/* Decode MPLS labels */ /* Decode MPLS labels */
if (s->mpls) if (s->mpls)
bgp_decode_mpls_labels(s, &pos, &len, &l, a); bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
if (l > IP4_MAX_PREFIX_LENGTH) if (l > IP4_MAX_PREFIX_LENGTH)
bgp_parse_error(s, 10); bgp_parse_error(s, 10);
@ -1585,7 +1580,7 @@ bgp_encode_nlri_ip6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *bu
} }
static void static void
bgp_decode_nlri_ip6(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_ip6(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -1611,7 +1606,7 @@ bgp_decode_nlri_ip6(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
/* Decode MPLS labels */ /* Decode MPLS labels */
if (s->mpls) if (s->mpls)
bgp_decode_mpls_labels(s, &pos, &len, &l, a); bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
if (l > IP6_MAX_PREFIX_LENGTH) if (l > IP6_MAX_PREFIX_LENGTH)
bgp_parse_error(s, 10); bgp_parse_error(s, 10);
@ -1673,7 +1668,7 @@ bgp_encode_nlri_vpn4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
} }
static void static void
bgp_decode_nlri_vpn4(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_vpn4(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -1699,7 +1694,7 @@ bgp_decode_nlri_vpn4(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
/* Decode MPLS labels */ /* Decode MPLS labels */
if (s->mpls) if (s->mpls)
bgp_decode_mpls_labels(s, &pos, &len, &l, a); bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
/* Decode route distinguisher */ /* Decode route distinguisher */
if (l < 64) if (l < 64)
@ -1770,7 +1765,7 @@ bgp_encode_nlri_vpn6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
} }
static void static void
bgp_decode_nlri_vpn6(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_vpn6(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -1796,7 +1791,7 @@ bgp_decode_nlri_vpn6(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
/* Decode MPLS labels */ /* Decode MPLS labels */
if (s->mpls) if (s->mpls)
bgp_decode_mpls_labels(s, &pos, &len, &l, a); bgp_decode_mpls_labels(s, &pos, &len, &l, &a);
/* Decode route distinguisher */ /* Decode route distinguisher */
if (l < 64) if (l < 64)
@ -1857,7 +1852,7 @@ bgp_encode_nlri_flow4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
} }
static void static void
bgp_decode_nlri_flow4(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_flow4(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -1945,7 +1940,7 @@ bgp_encode_nlri_flow6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *
} }
static void static void
bgp_decode_nlri_flow6(struct bgp_parse_state *s, byte *pos, uint len, rta *a) bgp_decode_nlri_flow6(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
{ {
while (len) while (len)
{ {
@ -2444,7 +2439,6 @@ static inline void
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len) bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
{ {
struct bgp_channel *c = bgp_get_channel(s->proto, afi); struct bgp_channel *c = bgp_get_channel(s->proto, afi);
rta *a = NULL;
if (!c) if (!c)
DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi)); DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
@ -2465,26 +2459,22 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
if (ea) if (ea)
{ {
a = allocz(RTA_MAX_SIZE); ea_set_attr_data(&ea, &ea_gen_from, 0, &s->proto->remote_ip, sizeof(ip_addr));
ea_set_attr_u32(&ea, &ea_gen_preference, 0, c->c.preference);
ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_BGP);
a->eattrs = ea; c->desc->decode_next_hop(s, nh, nh_len, &ea);
bgp_finish_attrs(s, &ea);
ea_set_attr_data(&a->eattrs, &ea_gen_from, 0, &s->proto->remote_ip, sizeof(ip_addr));
ea_set_attr_u32(&a->eattrs, &ea_gen_preference, 0, c->c.preference);
ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_BGP);
c->desc->decode_next_hop(s, nh, nh_len, a);
bgp_finish_attrs(s, a);
/* Handle withdraw during next hop decoding */ /* Handle withdraw during next hop decoding */
if (s->err_withdraw) if (s->err_withdraw)
a = NULL; ea = NULL;
} }
c->desc->decode_nlri(s, nlri, len, a); c->desc->decode_nlri(s, nlri, len, ea);
rta_free(s->cached_rta); rta_free(s->cached_ea);
s->cached_rta = NULL; s->cached_ea = NULL;
} }
static void static void
@ -2589,7 +2579,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
ea, s.mp_next_hop_data, s.mp_next_hop_len); ea, s.mp_next_hop_data, s.mp_next_hop_len);
done: done:
rta_free(s.cached_rta); rta_free(s.cached_ea);
lp_restore(tmp_linpool, &tmpp); lp_restore(tmp_linpool, &tmpp);
return; return;
} }

View File

@ -423,7 +423,7 @@ mrt_rib_table_header(struct mrt_table_dump_state *s, net_addr *n)
static void static void
mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r) mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r)
{ {
struct ea_list *eattrs = r->attrs->eattrs; struct ea_list *eattrs = r->attrs;
buffer *b = &s->buf; buffer *b = &s->buf;
if (!eattrs) if (!eattrs)

View File

@ -387,7 +387,7 @@ ospf_init(struct proto_config *CF)
static int static int
ospf_rte_better(struct rte *new, struct rte *old) ospf_rte_better(struct rte *new, struct rte *old)
{ {
u32 new_metric1 = ea_get_int(new->attrs->eattrs, &ea_ospf_metric1, LSINFINITY); u32 new_metric1 = ea_get_int(new->attrs, &ea_ospf_metric1, LSINFINITY);
if (new_metric1 == LSINFINITY) if (new_metric1 == LSINFINITY)
return 0; return 0;
@ -400,13 +400,13 @@ ospf_rte_better(struct rte *new, struct rte *old)
if (ns == RTS_OSPF_EXT2) if (ns == RTS_OSPF_EXT2)
{ {
u32 old_metric2 = ea_get_int(old->attrs->eattrs, &ea_ospf_metric2, LSINFINITY); u32 old_metric2 = ea_get_int(old->attrs, &ea_ospf_metric2, LSINFINITY);
u32 new_metric2 = ea_get_int(new->attrs->eattrs, &ea_ospf_metric2, LSINFINITY); u32 new_metric2 = ea_get_int(new->attrs, &ea_ospf_metric2, LSINFINITY);
if (new_metric2 < old_metric2) return 1; if (new_metric2 < old_metric2) return 1;
if (new_metric2 > old_metric2) return 0; if (new_metric2 > old_metric2) return 0;
} }
u32 old_metric1 = ea_get_int(old->attrs->eattrs, &ea_ospf_metric1, LSINFINITY); u32 old_metric1 = ea_get_int(old->attrs, &ea_ospf_metric1, LSINFINITY);
if (new_metric1 < old_metric1) if (new_metric1 < old_metric1)
return 1; return 1;
@ -419,7 +419,7 @@ ospf_rte_igp_metric(const rte *rt)
if (rt_get_source_attr(rt) == RTS_OSPF_EXT2) if (rt_get_source_attr(rt) == RTS_OSPF_EXT2)
return IGP_METRIC_UNKNOWN; return IGP_METRIC_UNKNOWN;
return ea_get_int(rt->attrs->eattrs, &ea_ospf_metric1, LSINFINITY); return ea_get_int(rt->attrs, &ea_ospf_metric1, LSINFINITY);
} }
void void
@ -535,7 +535,7 @@ ospf_shutdown(struct proto *P)
/* Cleanup locked rta entries */ /* Cleanup locked rta entries */
FIB_WALK(&p->rtf, ort, nf) FIB_WALK(&p->rtf, ort, nf)
{ {
rta_free(nf->old_rta); ea_free(nf->old_ea);
} }
FIB_WALK_END; FIB_WALK_END;
@ -592,18 +592,18 @@ ospf_get_route_info(rte * rte, byte * buf)
} }
buf += bsprintf(buf, " %s", type); buf += bsprintf(buf, " %s", type);
buf += bsprintf(buf, " (%d/%d", rt_get_preference(rte), ea_get_int(rte->attrs->eattrs, &ea_ospf_metric1, LSINFINITY)); buf += bsprintf(buf, " (%d/%d", rt_get_preference(rte), ea_get_int(rte->attrs, &ea_ospf_metric1, LSINFINITY));
if (source == RTS_OSPF_EXT2) if (source == RTS_OSPF_EXT2)
buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, &ea_ospf_metric2, LSINFINITY)); buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs, &ea_ospf_metric2, LSINFINITY));
buf += bsprintf(buf, ")"); buf += bsprintf(buf, ")");
if (source == RTS_OSPF_EXT1 || source == RTS_OSPF_EXT2) if (source == RTS_OSPF_EXT1 || source == RTS_OSPF_EXT2)
{ {
eattr *ea = ea_find(rte->attrs->eattrs, &ea_ospf_tag); eattr *ea = ea_find(rte->attrs, &ea_ospf_tag);
if (ea && (ea->u.data > 0)) if (ea && (ea->u.data > 0))
buf += bsprintf(buf, " [%x]", ea->u.data); buf += bsprintf(buf, " [%x]", ea->u.data);
} }
eattr *ea = ea_find(rte->attrs->eattrs, &ea_ospf_router_id); eattr *ea = ea_find(rte->attrs, &ea_ospf_router_id);
if (ea) if (ea)
buf += bsprintf(buf, " [%R]", ea->u.data); buf += bsprintf(buf, " [%R]", ea->u.data);
} }

View File

@ -1977,17 +1977,17 @@ add_cand(struct ospf_area *oa, struct top_hash_entry *en, struct top_hash_entry
} }
static inline int static inline int
ort_changed(ort *nf, rta *nr) ort_changed(ort *nf, ea_list *nr)
{ {
rta *or = nf->old_rta; ea_list *or = nf->old_ea;
if (!or || if (!or ||
(nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) || (nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) ||
(nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid)) (nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid))
return 1; return 1;
eattr *nhea_n = ea_find(nr->eattrs, &ea_gen_nexthop); eattr *nhea_n = ea_find(nr, &ea_gen_nexthop);
eattr *nhea_o = ea_find(or->eattrs, &ea_gen_nexthop); eattr *nhea_o = ea_find(or, &ea_gen_nexthop);
if (!nhea_n != !nhea_o) if (!nhea_n != !nhea_o)
return 1; return 1;
@ -2000,8 +2000,8 @@ ort_changed(ort *nf, rta *nr)
return 1; return 1;
} }
if ( ea_get_int(nr->eattrs, &ea_gen_source, 0) if ( ea_get_int(nr, &ea_gen_source, 0)
!= ea_get_int(or->eattrs, &ea_gen_source, 0)) != ea_get_int(or, &ea_gen_source, 0))
return 1; return 1;
return 0; return 0;
@ -2047,9 +2047,6 @@ again1:
if (nf->n.type) /* Add the route */ if (nf->n.type) /* Add the route */
{ {
rta a0 = {
};
struct { struct {
ea_list l; ea_list l;
eattr a[7]; eattr a[7];
@ -2066,7 +2063,7 @@ again1:
eattrs.a[eattrs.l.count++] = eattrs.a[eattrs.l.count++] =
EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nf->n.nhs->ad); EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, &nf->n.nhs->ad);
if (reload || ort_changed(nf, &a0)) if (reload || ort_changed(nf, &eattrs.l))
{ {
nf->old_metric1 = nf->n.metric1; nf->old_metric1 = nf->n.metric1;
nf->old_metric2 = nf->n.metric2; nf->old_metric2 = nf->n.metric2;
@ -2088,27 +2085,29 @@ again1:
EA_LITERAL_EMBEDDED(&ea_ospf_router_id, 0, nf->n.rid); EA_LITERAL_EMBEDDED(&ea_ospf_router_id, 0, nf->n.rid);
ASSERT_DIE(ARRAY_SIZE(eattrs.a) >= eattrs.l.count); ASSERT_DIE(ARRAY_SIZE(eattrs.a) >= eattrs.l.count);
a0.eattrs = &eattrs.l;
rta_free(nf->old_rta); ea_list *eal = ea_lookup(&eattrs.l);
nf->old_rta = rta_lookup(&a0); ea_free(nf->old_ea);
nf->old_ea = eal;
rte e0 = { rte e0 = {
.attrs = nf->old_rta, .attrs = eal,
.src = p->p.main_source, .src = p->p.main_source,
}; };
/*
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n", DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
*/
rte_update(p->p.main_channel, nf->fn.addr, &e0, p->p.main_source); rte_update(p->p.main_channel, nf->fn.addr, &e0, p->p.main_source);
} }
} }
else if (nf->old_rta) else if (nf->old_ea)
{ {
/* Remove the route */ /* Remove the route */
rta_free(nf->old_rta); rta_free(nf->old_ea);
nf->old_rta = NULL; nf->old_ea = NULL;
rte_update(p->p.main_channel, nf->fn.addr, NULL, p->p.main_source); rte_update(p->p.main_channel, nf->fn.addr, NULL, p->p.main_source);
} }

View File

@ -78,7 +78,7 @@ typedef struct ort
*/ */
orta n; orta n;
u32 old_metric1, old_metric2, old_tag, old_rid; u32 old_metric1, old_metric2, old_tag, old_rid;
rta *old_rta; ea_list *old_ea;
u32 lsa_id; u32 lsa_id;
u8 external_rte; u8 external_rte;
u8 area_net; u8 area_net;

View File

@ -1337,9 +1337,9 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
ASSERT(p->asbr); ASSERT(p->asbr);
/* Get route attributes */ /* Get route attributes */
rta *a = new->attrs; ea_list *a = new->attrs;
eattr *m1a = ea_find(a->eattrs, &ea_ospf_metric1); eattr *m1a = ea_find(a, &ea_ospf_metric1);
eattr *m2a = ea_find(a->eattrs, &ea_ospf_metric2); eattr *m2a = ea_find(a, &ea_ospf_metric2);
uint m1 = m1a ? m1a->u.data : 0; uint m1 = m1a ? m1a->u.data : 0;
uint m2 = m2a ? m2a->u.data : 10000; uint m2 = m2a ? m2a->u.data : 10000;
@ -1363,10 +1363,10 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
uint ebit = m2a || !m1a; uint ebit = m2a || !m1a;
uint metric = ebit ? m2 : m1; uint metric = ebit ? m2 : m1;
uint tag = ea_get_int(a->eattrs, &ea_ospf_tag, 0); uint tag = ea_get_int(a, &ea_ospf_tag, 0);
ip_addr fwd = IPA_NONE; ip_addr fwd = IPA_NONE;
eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(a, &ea_gen_nexthop);
struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr; struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr;
if (NEXTHOP_IS_REACHABLE(nhad)) if (NEXTHOP_IS_REACHABLE(nhad))
if (use_gw_for_fwaddr(p, nhad->nh.gw, nhad->nh.iface)) if (use_gw_for_fwaddr(p, nhad->nh.gw, nhad->nh.iface))

View File

@ -85,7 +85,7 @@ random_net_ip4(void)
} }
struct perf_random_routes { struct perf_random_routes {
struct rta *a; ea_list *a;
net_addr net; net_addr net;
}; };
@ -142,10 +142,10 @@ perf_loop(void *data)
*((net_addr_ip4 *) &(p->data[i].net)) = random_net_ip4(); *((net_addr_ip4 *) &(p->data[i].net)) = random_net_ip4();
if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) { if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) {
struct rta a0 = {}; ea_list *ea = NULL;
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, p->p.main_channel->preference); ea_set_attr_u32(&ea, &ea_gen_preference, 0, p->p.main_channel->preference);
ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_PERF); ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_PERF);
struct nexthop_adata nhad = { struct nexthop_adata nhad = {
.nh.iface = p->ifa->iface, .nh.iface = p->ifa->iface,
@ -153,10 +153,10 @@ perf_loop(void *data)
.nh.weight = 1, .nh.weight = 1,
}; };
ea_set_attr_data(&a0.eattrs, &ea_gen_nexthop, 0, ea_set_attr_data(&ea, &ea_gen_nexthop, 0,
&nhad.ad.data, sizeof nhad - sizeof nhad.ad); &nhad.ad.data, sizeof nhad - sizeof nhad.ad);
p->data[i].a = rta_lookup(&a0); p->data[i].a = rta_lookup(ea);
} }
else else
p->data[i].a = rta_clone(p->data[i-1].a); p->data[i].a = rta_clone(p->data[i-1].a);

View File

@ -58,19 +58,14 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte *
if (new) if (new)
{ {
rta *a = alloca(rta_size(new->attrs));
memcpy(a, new->attrs, rta_size(new->attrs));
a->cached = 0;
ea_unset_attr(&a->eattrs, 0, &ea_gen_hostentry);
rte e0 = { rte e0 = {
.attrs = a, .attrs = new->attrs,
.src = new->src, .src = new->src,
.generation = new->generation + 1, .generation = new->generation + 1,
}; };
ea_unset_attr(&e0.attrs, 0, &ea_gen_hostentry);
rte_update(dst, n, &e0, new->src); rte_update(dst, n, &e0, new->src);
} }
else else

View File

@ -447,11 +447,11 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rt
{ {
/* Update */ /* Update */
ea = ea_find(new->attrs->eattrs, &ea_radv_preference); ea = ea_find(new->attrs, &ea_radv_preference);
uint preference = ea ? ea->u.data : RA_PREF_MEDIUM; uint preference = ea ? ea->u.data : RA_PREF_MEDIUM;
uint preference_set = !!ea; uint preference_set = !!ea;
ea = ea_find(new->attrs->eattrs, &ea_radv_lifetime); ea = ea_find(new->attrs, &ea_radv_lifetime);
uint lifetime = ea ? ea->u.data : 0; uint lifetime = ea ? ea->u.data : 0;
uint lifetime_set = !!ea; uint lifetime_set = !!ea;

View File

@ -151,8 +151,6 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
if (rt) if (rt)
{ {
/* Update */ /* Update */
rta a0 = {};
struct { struct {
ea_list l; ea_list l;
eattr a[3]; eattr a[3];
@ -164,7 +162,8 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
EA_LITERAL_EMBEDDED(&ea_rip_metric, 0, rt->metric), EA_LITERAL_EMBEDDED(&ea_rip_metric, 0, rt->metric),
}, },
}; };
a0.eattrs = &ea_block.l;
ea_list *ea = &ea_block.l;
u16 rt_tag = rt->tag; u16 rt_tag = rt->tag;
struct iface *rt_from = NULL; struct iface *rt_from = NULL;
@ -203,7 +202,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
nhad->ad.length = ((void *) nh - (void *) nhad->ad.data); nhad->ad.length = ((void *) nh - (void *) nhad->ad.data);
ea_set_attr(&a0.eattrs, ea_set_attr(&ea,
EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0,
&(nexthop_sort(nhad, tmp_linpool)->ad))); &(nexthop_sort(nhad, tmp_linpool)->ad)));
} }
@ -217,22 +216,22 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
.nh.iface = rt->from->ifa->iface, .nh.iface = rt->from->ifa->iface,
}; };
ea_set_attr_data(&a0.eattrs, &ea_gen_nexthop, 0, ea_set_attr_data(&ea, &ea_gen_nexthop, 0,
&nhad.ad.data, sizeof nhad - sizeof nhad.ad); &nhad.ad.data, sizeof nhad - sizeof nhad.ad);
ea_set_attr_data(&a0.eattrs, &ea_gen_from, 0, &rt->from->nbr->addr, sizeof(ip_addr)); ea_set_attr_data(&ea, &ea_gen_from, 0, &rt->from->nbr->addr, sizeof(ip_addr));
} }
ea_set_attr_u32(&a0.eattrs, &ea_rip_tag, 0, rt_tag); ea_set_attr_u32(&ea, &ea_rip_tag, 0, rt_tag);
struct rip_iface_adata riad = { struct rip_iface_adata riad = {
.ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) }, .ad = { .length = sizeof(struct rip_iface_adata) - sizeof(struct adata) },
.iface = rt_from, .iface = rt_from,
}; };
ea_set_attr(&a0.eattrs, ea_set_attr(&ea,
EA_LITERAL_DIRECT_ADATA(&ea_rip_from, 0, &riad.ad)); EA_LITERAL_DIRECT_ADATA(&ea_rip_from, 0, &riad.ad));
rte e0 = { rte e0 = {
.attrs = &a0, .attrs = ea,
.src = p->p.main_source, .src = p->p.main_source,
}; };
@ -344,9 +343,9 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, s
if (new) if (new)
{ {
/* Update */ /* Update */
u32 rt_tag = ea_get_int(new->attrs->eattrs, &ea_rip_tag, 0); u32 rt_tag = ea_get_int(new->attrs, &ea_rip_tag, 0);
u32 rt_metric = ea_get_int(new->attrs->eattrs, &ea_rip_metric, 1); u32 rt_metric = ea_get_int(new->attrs, &ea_rip_metric, 1);
const eattr *rie = ea_find(new->attrs->eattrs, &ea_rip_from); const eattr *rie = ea_find(new->attrs, &ea_rip_from);
struct iface *rt_from = rie ? ((struct rip_iface_adata *) rie->u.ptr)->iface : NULL; struct iface *rt_from = rie ? ((struct rip_iface_adata *) rie->u.ptr)->iface : NULL;
if (rt_metric > p->infinity) if (rt_metric > p->infinity)
@ -380,7 +379,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, s
en->tag = rt_tag; en->tag = rt_tag;
en->from = (new->src->proto == P) ? rt_from : NULL; en->from = (new->src->proto == P) ? rt_from : NULL;
eattr *nhea = ea_find(new->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(new->attrs, &ea_gen_nexthop);
if (nhea) if (nhea)
{ {
struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr; struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr;
@ -1119,8 +1118,8 @@ rip_rte_better(struct rte *new, struct rte *old)
ASSERT_DIE(new->src == old->src); ASSERT_DIE(new->src == old->src);
struct rip_proto *p = (struct rip_proto *) new->src->proto; struct rip_proto *p = (struct rip_proto *) new->src->proto;
u32 new_metric = ea_get_int(new->attrs->eattrs, &ea_rip_metric, p->infinity); u32 new_metric = ea_get_int(new->attrs, &ea_rip_metric, p->infinity);
u32 old_metric = ea_get_int(old->attrs->eattrs, &ea_rip_metric, p->infinity); u32 old_metric = ea_get_int(old->attrs, &ea_rip_metric, p->infinity);
return new_metric < old_metric; return new_metric < old_metric;
} }
@ -1128,7 +1127,7 @@ rip_rte_better(struct rte *new, struct rte *old)
static u32 static u32
rip_rte_igp_metric(const rte *rt) rip_rte_igp_metric(const rte *rt)
{ {
return ea_get_int(rt->attrs->eattrs, &ea_rip_metric, IGP_METRIC_UNKNOWN); return ea_get_int(rt->attrs, &ea_rip_metric, IGP_METRIC_UNKNOWN);
} }
static void static void
@ -1229,8 +1228,8 @@ static void
rip_get_route_info(rte *rte, byte *buf) rip_get_route_info(rte *rte, byte *buf)
{ {
struct rip_proto *p = (struct rip_proto *) rte->src->proto; struct rip_proto *p = (struct rip_proto *) rte->src->proto;
u32 rt_metric = ea_get_int(rte->attrs->eattrs, &ea_rip_metric, p->infinity); u32 rt_metric = ea_get_int(rte->attrs, &ea_rip_metric, p->infinity);
u32 rt_tag = ea_get_int(rte->attrs->eattrs, &ea_rip_tag, 0); u32 rt_tag = ea_get_int(rte->attrs, &ea_rip_tag, 0);
buf += bsprintf(buf, " (%d/%d)", rt_get_preference(rte), rt_metric); buf += bsprintf(buf, " (%d/%d)", rt_get_preference(rte), rt_metric);

View File

@ -120,12 +120,11 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
{ {
struct rpki_proto *p = cache->p; struct rpki_proto *p = cache->p;
rta a0 = {}; ea_list *ea = NULL;
ea_set_attr_u32(&ea, &ea_gen_preference, 0, channel->preference);
ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_RPKI);
ea_set_attr_u32(&a0.eattrs, &ea_gen_preference, 0, channel->preference); rte e0 = { .attrs = ea, .src = p->p.main_source, };
ea_set_attr_u32(&a0.eattrs, &ea_gen_source, 0, RTS_RPKI);
rte e0 = { .attrs = &a0, .src = p->p.main_source, };
rte_update(channel, &pfxr->n, &e0, p->p.main_source); rte_update(channel, &pfxr->n, &e0, p->p.main_source);
} }

View File

@ -53,10 +53,10 @@ static inline struct rte_src * static_get_source(struct static_proto *p, uint i)
static void static void
static_announce_rte(struct static_proto *p, struct static_route *r) static_announce_rte(struct static_proto *p, struct static_route *r)
{ {
rta *a = allocz(RTA_MAX_SIZE); ea_list *ea = NULL;
struct rte_src *src = static_get_source(p, r->index); struct rte_src *src = static_get_source(p, r->index);
ea_set_attr_u32(&a->eattrs, &ea_gen_preference, 0, p->p.main_channel->preference); ea_set_attr_u32(&ea, &ea_gen_preference, 0, p->p.main_channel->preference);
ea_set_attr_u32(&a->eattrs, &ea_gen_source, 0, RTS_STATIC); ea_set_attr_u32(&ea, &ea_gen_source, 0, RTS_STATIC);
if (r->dest == RTD_UNICAST) if (r->dest == RTD_UNICAST)
{ {
@ -92,7 +92,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
nh = NEXTHOP_NEXT(nh); nh = NEXTHOP_NEXT(nh);
} }
ea_set_attr_data(&a->eattrs, &ea_gen_nexthop, 0, ea_set_attr_data(&ea, &ea_gen_nexthop, 0,
nhad->ad.data, (void *) nh - (void *) nhad->ad.data); nhad->ad.data, (void *) nh - (void *) nhad->ad.data);
} }
@ -102,19 +102,19 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
u32 *labels = r->mls ? (void *) r->mls->data : NULL; u32 *labels = r->mls ? (void *) r->mls->data : NULL;
u32 lnum = r->mls ? r->mls->length / sizeof(u32) : 0; u32 lnum = r->mls ? r->mls->length / sizeof(u32) : 0;
ea_set_hostentry(&a->eattrs, p->p.main_channel->table, tab, ea_set_hostentry(&ea, p->p.main_channel->table, tab,
r->via, IPA_NONE, lnum, labels); r->via, IPA_NONE, lnum, labels);
} }
else if (r->dest) else if (r->dest)
ea_set_dest(&a->eattrs, 0, r->dest); ea_set_dest(&ea, 0, r->dest);
/* Already announced */ /* Already announced */
if (r->state == SRS_CLEAN) if (r->state == SRS_CLEAN)
return; return;
/* We skip rta_lookup() here */ /* We skip rta_lookup() here */
rte e0 = { .attrs = a, .src = src, .net = r->net, }, *e = &e0; rte e0 = { .attrs = ea, .src = src, .net = r->net, }, *e = &e0;
/* Evaluate the filter */ /* Evaluate the filter */
if (r->cmds) if (r->cmds)
@ -396,16 +396,16 @@ static_reload_routes(struct channel *C)
static int static int
static_rte_better(rte *new, rte *old) static_rte_better(rte *new, rte *old)
{ {
u32 n = ea_get_int(new->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN); u32 n = ea_get_int(new->attrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
u32 o = ea_get_int(old->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN); u32 o = ea_get_int(old->attrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
return n < o; return n < o;
} }
static int static int
static_rte_mergable(rte *pri, rte *sec) static_rte_mergable(rte *pri, rte *sec)
{ {
u32 a = ea_get_int(pri->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN); u32 a = ea_get_int(pri->attrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
u32 b = ea_get_int(sec->attrs->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN); u32 b = ea_get_int(sec->attrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN);
return a == b; return a == b;
} }
@ -693,7 +693,7 @@ static_copy_config(struct proto_config *dest, struct proto_config *src)
static void static void
static_get_route_info(rte *rte, byte *buf) static_get_route_info(rte *rte, byte *buf)
{ {
eattr *a = ea_find(rte->attrs->eattrs, &ea_gen_igp_metric); eattr *a = ea_find(rte->attrs, &ea_gen_igp_metric);
u32 pref = rt_get_preference(rte); u32 pref = rt_get_preference(rte);
if (a) if (a)
buf += bsprintf(buf, " (%d/%u)", pref, a->u.data); buf += bsprintf(buf, " (%d/%u)", pref, a->u.data);

View File

@ -111,7 +111,7 @@ struct nl_parse_state
int merge; int merge;
net_addr *net; net_addr *net;
rta *attrs; ea_list *attrs;
struct krt_proto *proto; struct krt_proto *proto;
s8 new; s8 new;
s8 krt_src; s8 krt_src;
@ -1407,7 +1407,7 @@ HASH_DEFINE_REHASH_FN(RTH, struct krt_proto)
int int
krt_capable(rte *e) krt_capable(rte *e)
{ {
eattr *ea = ea_find(e->attrs->eattrs, &ea_gen_nexthop); eattr *ea = ea_find(e->attrs, &ea_gen_nexthop);
if (!ea) if (!ea)
return 0; return 0;
@ -1440,8 +1440,7 @@ static int
nl_send_route(struct krt_proto *p, const rte *e, int op, int dest, struct nexthop_adata *nh) nl_send_route(struct krt_proto *p, const rte *e, int op, int dest, struct nexthop_adata *nh)
{ {
eattr *ea; eattr *ea;
rta *a = e->attrs; ea_list *eattrs = e->attrs;
ea_list *eattrs = a->eattrs;
int bufsize = 128 + KRT_METRICS_MAX*8 + (nh ? nh_bufsize(nh) : 0); int bufsize = 128 + KRT_METRICS_MAX*8 + (nh ? nh_bufsize(nh) : 0);
u32 priority = 0; u32 priority = 0;
@ -1589,10 +1588,10 @@ dest:
static inline int static inline int
nl_add_rte(struct krt_proto *p, rte *e) nl_add_rte(struct krt_proto *p, rte *e)
{ {
rta *a = e->attrs; ea_list *ea = e->attrs;
int err = 0; int err = 0;
eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(ea, &ea_gen_nexthop);
struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL;
if (krt_ecmp6(p) && nhad && NEXTHOP_IS_REACHABLE(nhad) && !NEXTHOP_ONE(nhad)) if (krt_ecmp6(p) && nhad && NEXTHOP_IS_REACHABLE(nhad) && !NEXTHOP_ONE(nhad))
@ -1640,8 +1639,7 @@ nl_delete_rte(struct krt_proto *p, const rte *e)
static inline int static inline int
nl_replace_rte(struct krt_proto *p, rte *e) nl_replace_rte(struct krt_proto *p, rte *e)
{ {
rta *a = e->attrs; eattr *nhea = ea_find(e->attrs, &ea_gen_nexthop);
eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop);
struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL;
return nl_send_route(p, e, NL_OP_REPLACE, return nl_send_route(p, e, NL_OP_REPLACE,
NEXTHOP_IS_REACHABLE(nhad) ? RTD_UNICAST : nhad->dest, nhad); NEXTHOP_IS_REACHABLE(nhad) ? RTD_UNICAST : nhad->dest, nhad);
@ -1714,14 +1712,14 @@ nl_announce_route(struct nl_parse_state *s)
}; };
EA_LOCAL_LIST(2) ea = { EA_LOCAL_LIST(2) ea = {
.l = { .count = 2, .next = e0.attrs->eattrs }, .l = { .count = 2, .next = e0.attrs },
.a = { .a = {
EA_LITERAL_EMBEDDED(&ea_krt_source, 0, s->krt_proto), EA_LITERAL_EMBEDDED(&ea_krt_source, 0, s->krt_proto),
EA_LITERAL_EMBEDDED(&ea_krt_metric, 0, s->krt_metric), EA_LITERAL_EMBEDDED(&ea_krt_metric, 0, s->krt_metric),
}, },
}; };
e0.attrs->eattrs = &ea.l; e0.attrs = &ea.l;
if (s->scan) if (s->scan)
krt_got_route(s->proto, &e0, s->krt_src); krt_got_route(s->proto, &e0, s->krt_src);
@ -1887,8 +1885,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family)) if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family))
nl_announce_route(s); nl_announce_route(s);
rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE); ea_list *ra = NULL;
ea_set_attr_u32(&ra->eattrs, &ea_gen_source, 0, RTS_INHERIT); ea_set_attr_u32(&ra, &ea_gen_source, 0, RTS_INHERIT);
if (a[RTA_FLOW]) if (a[RTA_FLOW])
s->rta_flow = rta_get_u32(a[RTA_FLOW]); s->rta_flow = rta_get_u32(a[RTA_FLOW]);
@ -1913,7 +1911,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if (!nh) if (!nh)
SKIP("strange RTA_MULTIPATH\n"); SKIP("strange RTA_MULTIPATH\n");
ea_set_attr(&ra->eattrs, EA_LITERAL_DIRECT_ADATA( ea_set_attr(&ra, EA_LITERAL_DIRECT_ADATA(
&ea_gen_nexthop, 0, &nh->ad)); &ea_gen_nexthop, 0, &nh->ad));
break; break;
} }
@ -1999,20 +1997,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
} }
if (i->rtm_scope != def_scope) if (i->rtm_scope != def_scope)
ea_set_attr(&ra->eattrs, ea_set_attr(&ra,
EA_LITERAL_EMBEDDED(&ea_krt_scope, 0, i->rtm_scope)); EA_LITERAL_EMBEDDED(&ea_krt_scope, 0, i->rtm_scope));
if (a[RTA_PREFSRC]) if (a[RTA_PREFSRC])
{ {
ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]); ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]);
ea_set_attr(&ra->eattrs, ea_set_attr(&ra,
EA_LITERAL_STORE_ADATA(&ea_krt_prefsrc, 0, &ps, sizeof(ps))); EA_LITERAL_STORE_ADATA(&ea_krt_prefsrc, 0, &ps, sizeof(ps)));
} }
/* Can be set per-route or per-nexthop */ /* Can be set per-route or per-nexthop */
if (s->rta_flow) if (s->rta_flow)
ea_set_attr(&ra->eattrs, ea_set_attr(&ra,
EA_LITERAL_EMBEDDED(&ea_krt_realm, 0, s->rta_flow)); EA_LITERAL_EMBEDDED(&ea_krt_realm, 0, s->rta_flow));
if (a[RTA_METRICS]) if (a[RTA_METRICS])
@ -2026,7 +2024,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
for (uint t = 1; t < KRT_METRICS_MAX; t++) for (uint t = 1; t < KRT_METRICS_MAX; t++)
if (metrics[0] & (1 << t)) if (metrics[0] & (1 << t))
ea_set_attr(&ra->eattrs, ea_set_attr(&ra,
EA_LITERAL_EMBEDDED(&ea_krt_metrics[t], 0, metrics[t])); EA_LITERAL_EMBEDDED(&ea_krt_metrics[t], 0, metrics[t]));
} }
@ -2046,7 +2044,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
s->attrs = ra; s->attrs = ra;
ea_set_attr_data(&ra->eattrs, &ea_gen_nexthop, 0, ea_set_attr_data(&ra, &ea_gen_nexthop, 0,
nhad.ad.data, nhad.ad.length); nhad.ad.data, nhad.ad.length);
s->proto = p; s->proto = p;
@ -2059,17 +2057,17 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
else else
{ {
/* Merge next hops with the stored route */ /* Merge next hops with the stored route */
eattr *nhea = ea_find(s->attrs->eattrs, &ea_gen_nexthop); eattr *nhea = ea_find(s->attrs, &ea_gen_nexthop);
struct nexthop_adata *nhad_old = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; struct nexthop_adata *nhad_old = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL;
if (nhad_old) if (nhad_old)
ea_set_attr(&s->attrs->eattrs, ea_set_attr(&s->attrs,
EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0, EA_LITERAL_DIRECT_ADATA(&ea_gen_nexthop, 0,
&(nexthop_merge(nhad_old, &nhad.nhad, &(nexthop_merge(nhad_old, &nhad.nhad,
KRT_CF->merge_paths, s->pool)->ad) KRT_CF->merge_paths, s->pool)->ad)
)); ));
else else
ea_set_attr_data(&s->attrs->eattrs, &ea_gen_nexthop, 0, ea_set_attr_data(&s->attrs, &ea_gen_nexthop, 0,
nhad.ad.data, nhad.ad.length); nhad.ad.data, nhad.ad.length);
} }
} }

View File

@ -286,7 +286,7 @@ static struct tbf rl_alien = TBF_DEFAULT_LOG_LIMITS;
static inline u32 static inline u32
krt_metric(rte *a) krt_metric(rte *a)
{ {
eattr *ea = ea_find(a->attrs->eattrs, &ea_krt_metric); eattr *ea = ea_find(a->attrs, &ea_krt_metric);
return ea ? ea->u.data : 0; return ea ? ea->u.data : 0;
} }
@ -306,7 +306,7 @@ static void
krt_learn_announce_update(struct krt_proto *p, rte *e) krt_learn_announce_update(struct krt_proto *p, rte *e)
{ {
rte e0 = { rte e0 = {
.attrs = rta_clone(e->attrs), .attrs = ea_clone(e->attrs),
.src = p->p.main_source, .src = p->p.main_source,
}; };
@ -438,9 +438,7 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
net *n = net_get(p->krt_table, e->net); net *n = net_get(p->krt_table, e->net);
struct rte_storage *g, **gg, *best, **bestp, *old_best; struct rte_storage *g, **gg, *best, **bestp, *old_best;
ASSERT(!e->attrs->cached); ea_set_attr_u32(&e->attrs, &ea_gen_preference, 0, p->p.main_channel->preference);
ea_set_attr_u32(&e->attrs->eattrs, &ea_gen_preference, 0, p->p.main_channel->preference);
struct rte_storage *ee = rte_store(e, n, p->krt_table); struct rte_storage *ee = rte_store(e, n, p->krt_table);
old_best = n->routes; old_best = n->routes;
@ -616,10 +614,10 @@ reject:
static int static int
krt_same_dest(rte *k, rte *e) krt_same_dest(rte *k, rte *e)
{ {
rta *ka = k->attrs, *ea = e->attrs; ea_list *ka = k->attrs, *ea = e->attrs;
eattr *nhea_k = ea_find(ka->eattrs, &ea_gen_nexthop); eattr *nhea_k = ea_find(ka, &ea_gen_nexthop);
eattr *nhea_e = ea_find(ea->eattrs, &ea_gen_nexthop); eattr *nhea_e = ea_find(ea, &ea_gen_nexthop);
return (!nhea_k == !nhea_e) && adata_same(nhea_k->u.ptr, nhea_e->u.ptr); return (!nhea_k == !nhea_e) && adata_same(nhea_k->u.ptr, nhea_e->u.ptr);
} }

View File

@ -56,7 +56,7 @@ async_dump(void)
// XXXX tm_dump_all(); // XXXX tm_dump_all();
if_dump_all(); if_dump_all();
neigh_dump_all(); neigh_dump_all();
rta_dump_all(); ea_dump_all();
rt_dump_all(); rt_dump_all();
protos_dump_all(); protos_dump_all();