0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-18 17:18:42 +00:00

Attribute list normalization cleanup

This commit is contained in:
Maria Matejka 2022-04-10 14:11:46 +02:00
parent 0b871c1704
commit de86040b2c
8 changed files with 73 additions and 79 deletions

View File

@ -717,12 +717,8 @@
runtime( "Setting opaque attribute is not allowed" ); runtime( "Setting opaque attribute is not allowed" );
break; break;
case T_IP:; case T_IP:
int len = sizeof(ip_addr); l->attrs[0].u.ptr = lp_store_adata(fs->pool, &v1.val.ip, sizeof(ip_addr));
struct adata *ad = lp_alloc(fs->pool, sizeof(struct adata) + len);
ad->length = len;
(* (ip_addr *) ad->data) = v1.val.ip;
l->attrs[0].u.ptr = ad;
break; break;
default: default:

View File

@ -17,6 +17,8 @@ typedef struct adata {
byte data[0]; byte data[0];
} adata; } adata;
#define ADATA_SIZE(s) BIRD_CPU_ALIGN(sizeof(struct adata) + s)
extern const adata null_adata; /* adata of length 0 */ extern const adata null_adata; /* adata of length 0 */
static inline struct adata * static inline struct adata *
@ -27,6 +29,14 @@ lp_alloc_adata(struct linpool *pool, uint len)
return ad; return ad;
} }
static inline struct adata *
lp_store_adata(struct linpool *pool, const void *buf, uint len)
{
struct adata *ad = lp_alloc_adata(pool, len);
memcpy(ad->data, buf, len);
return ad;
}
static inline int adata_same(const struct adata *a, const struct adata *b) static inline int adata_same(const struct adata *a, const struct adata *b)
{ return (a->length == b->length && !memcmp(a->data, b->data, a->length)); } { return (a->length == b->length && !memcmp(a->data, b->data, a->length)); }

View File

@ -19,6 +19,7 @@ struct align_probe { char x; long int y; };
#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i))) #define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1)) #define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
#define CPU_STRUCT_ALIGN (sizeof(struct align_probe)) #define CPU_STRUCT_ALIGN (sizeof(struct align_probe))
#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
/* Utility macros */ /* Utility macros */

View File

@ -204,24 +204,16 @@ ea_get_int(ea_list *e, unsigned id, u32 def)
} }
void ea_dump(ea_list *); void ea_dump(ea_list *);
void ea_sort(ea_list *); /* Sort entries in all sub-lists */
unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */
void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffer */
int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */ int ea_same(ea_list *x, ea_list *y); /* Test whether two ea_lists are identical */
uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
ea_list *ea_append(ea_list *to, ea_list *what); ea_list *ea_append(ea_list *to, ea_list *what);
void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max); void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
#define ea_normalize(ea) do { \ /* Normalize ea_list; allocates the result from tmp_linpool */
if (ea->next) { \ ea_list *ea_normalize(const ea_list *e);
ea_list *t = alloca(ea_scan(ea)); \
ea_merge(ea, t); \ uint ea_list_size(ea_list *);
ea = t; \ void ea_list_copy(ea_list *dest, ea_list *src, uint size);
} \
ea_sort(ea); \
if (ea->count == 0) \
ea = NULL; \
} while(0) \
struct ea_one_attr_list { struct ea_one_attr_list {
ea_list l; ea_list l;

View File

@ -626,7 +626,7 @@ ea_do_prune(ea_list *e)
* If an attribute occurs multiple times in a single &ea_list, * If an attribute occurs multiple times in a single &ea_list,
* ea_sort() leaves only the first (the only significant) occurrence. * ea_sort() leaves only the first (the only significant) occurrence.
*/ */
void static void
ea_sort(ea_list *e) ea_sort(ea_list *e)
{ {
while (e) while (e)
@ -650,8 +650,8 @@ ea_sort(ea_list *e)
* This function calculates an upper bound of the size of * This function calculates an upper bound of the size of
* a given &ea_list after merging with ea_merge(). * a given &ea_list after merging with ea_merge().
*/ */
unsigned static unsigned
ea_scan(ea_list *e) ea_scan(const ea_list *e)
{ {
unsigned cnt = 0; unsigned cnt = 0;
@ -677,8 +677,8 @@ ea_scan(ea_list *e)
* segments with ea_merge() and finally sort and prune the result * segments with ea_merge() and finally sort and prune the result
* by calling ea_sort(). * by calling ea_sort().
*/ */
void static void
ea_merge(ea_list *e, ea_list *t) ea_merge(const ea_list *e, ea_list *t)
{ {
eattr *d = t->attrs; eattr *d = t->attrs;
@ -694,6 +694,16 @@ ea_merge(ea_list *e, ea_list *t)
} }
} }
ea_list *
ea_normalize(const ea_list *e)
{
ea_list *t = tmp_alloc(ea_scan(e));
ea_merge(e, t);
ea_sort(t);
return t->count ? t : NULL;
}
/** /**
* ea_same - compare two &ea_list's * ea_same - compare two &ea_list's
* @x: attribute list * @x: attribute list
@ -729,33 +739,38 @@ ea_same(ea_list *x, ea_list *y)
return 1; return 1;
} }
static inline ea_list * uint
ea_list_copy(ea_list *o) ea_list_size(ea_list *o)
{ {
ea_list *n; unsigned i, elen;
unsigned i, adpos, elen;
if (!o) ASSERT_DIE(o);
return NULL; ASSERT_DIE(!o->next);
ASSERT(!o->next); elen = BIRD_CPU_ALIGN(sizeof(ea_list) + sizeof(eattr) * o->count);
elen = adpos = sizeof(ea_list) + sizeof(eattr) * o->count;
for(i=0; i<o->count; i++) for(i=0; i<o->count; i++)
{ {
eattr *a = &o->attrs[i]; eattr *a = &o->attrs[i];
if (!(a->type & EAF_EMBEDDED)) if (!(a->type & EAF_EMBEDDED))
elen += sizeof(struct adata) + a->u.ptr->length; elen += ADATA_SIZE(a->u.ptr->length);
} }
n = mb_alloc(rta_pool, elen); return elen;
}
void
ea_list_copy(ea_list *n, ea_list *o, uint elen)
{
uint adpos = sizeof(ea_list) + sizeof(eattr) * o->count;
memcpy(n, o, adpos); memcpy(n, o, adpos);
n->flags |= EALF_CACHED; adpos = BIRD_CPU_ALIGN(adpos);
for(i=0; i<o->count; i++)
for(uint i=0; i<o->count; i++)
{ {
eattr *a = &n->attrs[i]; eattr *a = &n->attrs[i];
if (!(a->type & EAF_EMBEDDED)) if (!(a->type & EAF_EMBEDDED))
{ {
unsigned size = sizeof(struct adata) + a->u.ptr->length; unsigned size = ADATA_SIZE(a->u.ptr->length);
ASSERT_DIE(adpos + size <= elen); ASSERT_DIE(adpos + size <= elen);
struct adata *d = ((void *) n) + adpos; struct adata *d = ((void *) n) + adpos;
@ -765,8 +780,8 @@ ea_list_copy(ea_list *o)
adpos += size; adpos += size;
} }
} }
ASSERT_DIE(adpos == elen); ASSERT_DIE(adpos == elen);
return n;
} }
static inline void static inline void
@ -1029,6 +1044,7 @@ ea_hash(ea_list *e)
if (e) /* Assuming chain of length 1 */ if (e) /* Assuming chain of length 1 */
{ {
ASSERT_DIE(!e->next);
for(i=0; i<e->count; i++) for(i=0; i<e->count; i++)
{ {
struct eattr *a = &e->attrs[i]; struct eattr *a = &e->attrs[i];
@ -1135,7 +1151,13 @@ rta_copy(rta *o)
memcpy(r, o, rta_size(o)); memcpy(r, o, rta_size(o));
r->uc = 1; r->uc = 1;
r->nh.next = nexthop_copy(o->nh.next); r->nh.next = nexthop_copy(o->nh.next);
r->eattrs = ea_list_copy(o->eattrs); 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);
r->eattrs->flags |= EALF_CACHED;
return r; return r;
} }
@ -1191,7 +1213,7 @@ rta_lookup(rta *o)
ASSERT(!o->cached); ASSERT(!o->cached);
if (o->eattrs) if (o->eattrs)
ea_normalize(o->eattrs); o->eattrs = ea_normalize(o->eattrs);
h = rta_hash(o); h = rta_hash(o);
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next) for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)

View File

@ -55,7 +55,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
/* 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->eattrs)
ea_normalize(a->eattrs); a->eattrs = ea_normalize(a->eattrs);
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)

View File

@ -1191,12 +1191,11 @@ bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to)
* Result: one sorted attribute list segment, or NULL if attributes are unsuitable. * Result: one sorted attribute list segment, or NULL if attributes are unsuitable.
*/ */
static inline ea_list * static inline ea_list *
bgp_export_attrs(struct bgp_export_state *s, ea_list *attrs) bgp_export_attrs(struct bgp_export_state *s, const ea_list *a)
{ {
/* Merge the attribute list */ /* Merge the attribute list */
ea_list *new = lp_alloc(s->pool, ea_scan(attrs)); ea_list *new = ea_normalize(a);
ea_merge(attrs, new); ASSERT_DIE(new);
ea_sort(new);
uint i, count; uint i, count;
count = new->count; count = new->count;
@ -1498,6 +1497,7 @@ bgp_free_bucket_table(struct bgp_channel *c)
static struct bgp_bucket * static struct bgp_bucket *
bgp_get_bucket(struct bgp_channel *c, ea_list *new) bgp_get_bucket(struct bgp_channel *c, ea_list *new)
{ {
/* Hash and lookup */ /* Hash and lookup */
u32 hash = ea_hash(new); u32 hash = ea_hash(new);
struct bgp_bucket *b = HASH_FIND(c->bucket_hash, RBH, new, hash); struct bgp_bucket *b = HASH_FIND(c->bucket_hash, RBH, new, hash);
@ -1505,45 +1505,18 @@ bgp_get_bucket(struct bgp_channel *c, ea_list *new)
if (b) if (b)
return b; return b;
uint ea_size = sizeof(ea_list) + new->count * sizeof(eattr); /* Scan the list for total size */
uint ea_size_aligned = BIRD_ALIGN(ea_size, CPU_STRUCT_ALIGN); uint ea_size = BIRD_CPU_ALIGN(ea_list_size(new));
uint size = sizeof(struct bgp_bucket) + ea_size_aligned; uint size = sizeof(struct bgp_bucket) + ea_size;
uint i;
byte *dest;
/* Gather total size of non-inline attributes */ /* Allocate the bucket */
for (i = 0; i < new->count; i++)
{
eattr *a = &new->attrs[i];
if (!(a->type & EAF_EMBEDDED))
size += BIRD_ALIGN(sizeof(struct adata) + a->u.ptr->length, CPU_STRUCT_ALIGN);
}
/* Create the bucket */
b = mb_alloc(c->pool, size); b = mb_alloc(c->pool, size);
*b = (struct bgp_bucket) { }; *b = (struct bgp_bucket) { };
init_list(&b->prefixes); init_list(&b->prefixes);
b->hash = hash; b->hash = hash;
/* Copy list of extended attributes */ /* Copy the ea_list */
memcpy(b->eattrs, new, ea_size); ea_list_copy(b->eattrs, new, ea_size);
dest = ((byte *) b->eattrs) + ea_size_aligned;
/* Copy values of non-inline attributes */
for (i = 0; i < new->count; i++)
{
eattr *a = &b->eattrs->attrs[i];
if (!(a->type & EAF_EMBEDDED))
{
const struct adata *oa = a->u.ptr;
struct adata *na = (struct adata *) dest;
memcpy(na, oa, sizeof(struct adata) + oa->length);
a->u.ptr = na;
dest += BIRD_ALIGN(sizeof(struct adata) + na->length, CPU_STRUCT_ALIGN);
}
}
/* Insert the bucket to send queue and bucket hash */ /* Insert the bucket to send queue and bucket hash */
add_tail(&c->bucket_queue, &b->send_node); add_tail(&c->bucket_queue, &b->send_node);

View File

@ -431,7 +431,7 @@ mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r)
/* Attribute list must be normalized for bgp_encode_attrs() */ /* Attribute list must be normalized for bgp_encode_attrs() */
if (!rta_is_cached(r->attrs)) if (!rta_is_cached(r->attrs))
ea_normalize(eattrs); eattrs = ea_normalize(eattrs);
mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE); mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
byte *pos = b->pos; byte *pos = b->pos;