mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 17:18:42 +00:00
Route attribute storage keeps the previous layers
This commit is contained in:
parent
54d94f4b1a
commit
8c92f47ac7
@ -42,7 +42,7 @@ lp_store_adata(struct linpool *pool, const void *buf, uint len)
|
|||||||
#define tmp_copy_adata(ad) tmp_store_adata((ad)->data, (ad)->length)
|
#define tmp_copy_adata(ad) tmp_store_adata((ad)->data, (ad)->length)
|
||||||
|
|
||||||
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 && !b) || (a->length == b->length && !memcmp(a->data, b->data, a->length)); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ 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);
|
||||||
|
|
||||||
/* Normalize ea_list; allocates the result from tmp_linpool */
|
/* Normalize ea_list; allocates the result from tmp_linpool */
|
||||||
ea_list *ea_normalize(const ea_list *e);
|
ea_list *ea_normalize(ea_list *e, int overlay);
|
||||||
|
|
||||||
uint ea_list_size(ea_list *);
|
uint ea_list_size(ea_list *);
|
||||||
void ea_list_copy(ea_list *dest, ea_list *src, uint size);
|
void ea_list_copy(ea_list *dest, ea_list *src, uint size);
|
||||||
@ -414,7 +414,7 @@ static inline int rte_dest(const rte *r)
|
|||||||
|
|
||||||
void rta_init(void);
|
void rta_init(void);
|
||||||
ea_list *ea_lookup(ea_list *); /* Get a cached (and normalized) variant of this attribute list */
|
ea_list *ea_lookup(ea_list *); /* Get a cached (and normalized) variant of this attribute list */
|
||||||
static inline int ea_is_cached(ea_list *r) { return r->flags & EALF_CACHED; }
|
static inline int ea_is_cached(const ea_list *r) { return r->flags & EALF_CACHED; }
|
||||||
static inline ea_list *ea_clone(ea_list *r) { r->uc++; return r; }
|
static inline ea_list *ea_clone(ea_list *r) { r->uc++; return r; }
|
||||||
void ea__free(ea_list *r);
|
void ea__free(ea_list *r);
|
||||||
static inline void ea_free(ea_list *r) { if (r && !--r->uc) ea__free(r); }
|
static inline void ea_free(ea_list *r) { if (r && !--r->uc) ea__free(r); }
|
||||||
|
@ -726,8 +726,8 @@ ea_do_prune(ea_list *e)
|
|||||||
s++;
|
s++;
|
||||||
|
|
||||||
/* Now s0 is the most recent version, s[-1] the oldest one */
|
/* Now s0 is the most recent version, s[-1] the oldest one */
|
||||||
/* Drop undefs */
|
/* Drop undefs unless this is a true overlay */
|
||||||
if (s0->undef)
|
if (s0->undef && !e->next)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Copy the newest version to destination */
|
/* Copy the newest version to destination */
|
||||||
@ -760,18 +760,15 @@ ea_do_prune(ea_list *e)
|
|||||||
static void
|
static void
|
||||||
ea_sort(ea_list *e)
|
ea_sort(ea_list *e)
|
||||||
{
|
{
|
||||||
while (e)
|
|
||||||
{
|
|
||||||
if (!(e->flags & EALF_SORTED))
|
if (!(e->flags & EALF_SORTED))
|
||||||
{
|
{
|
||||||
ea_do_sort(e);
|
ea_do_sort(e);
|
||||||
ea_do_prune(e);
|
ea_do_prune(e);
|
||||||
e->flags |= EALF_SORTED;
|
e->flags |= EALF_SORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->count > 5)
|
if (e->count > 5)
|
||||||
e->flags |= EALF_BISECT;
|
e->flags |= EALF_BISECT;
|
||||||
e = e->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -782,7 +779,7 @@ ea_sort(ea_list *e)
|
|||||||
* a given &ea_list after merging with ea_merge().
|
* a given &ea_list after merging with ea_merge().
|
||||||
*/
|
*/
|
||||||
static unsigned
|
static unsigned
|
||||||
ea_scan(const ea_list *e)
|
ea_scan(const ea_list *e, int overlay)
|
||||||
{
|
{
|
||||||
unsigned cnt = 0;
|
unsigned cnt = 0;
|
||||||
|
|
||||||
@ -790,6 +787,8 @@ ea_scan(const ea_list *e)
|
|||||||
{
|
{
|
||||||
cnt += e->count;
|
cnt += e->count;
|
||||||
e = e->next;
|
e = e->next;
|
||||||
|
if (e && overlay && ea_is_cached(e))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return sizeof(ea_list) + sizeof(eattr)*cnt;
|
return sizeof(ea_list) + sizeof(eattr)*cnt;
|
||||||
}
|
}
|
||||||
@ -809,27 +808,32 @@ ea_scan(const ea_list *e)
|
|||||||
* by calling ea_sort().
|
* by calling ea_sort().
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ea_merge(const ea_list *e, ea_list *t)
|
ea_merge(ea_list *e, ea_list *t, int overlay)
|
||||||
{
|
{
|
||||||
eattr *d = t->attrs;
|
eattr *d = t->attrs;
|
||||||
|
|
||||||
t->flags = 0;
|
t->flags = 0;
|
||||||
t->count = 0;
|
t->count = 0;
|
||||||
t->next = NULL;
|
|
||||||
while (e)
|
while (e)
|
||||||
{
|
{
|
||||||
memcpy(d, e->attrs, sizeof(eattr)*e->count);
|
memcpy(d, e->attrs, sizeof(eattr)*e->count);
|
||||||
t->count += e->count;
|
t->count += e->count;
|
||||||
d += e->count;
|
d += e->count;
|
||||||
e = e->next;
|
e = e->next;
|
||||||
|
|
||||||
|
if (e && overlay && ea_is_cached(e))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t->next = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
ea_list *
|
ea_list *
|
||||||
ea_normalize(const ea_list *e)
|
ea_normalize(ea_list *e, int overlay)
|
||||||
{
|
{
|
||||||
ea_list *t = tmp_alloc(ea_scan(e));
|
ea_list *t = tmp_alloc(ea_scan(e, overlay));
|
||||||
ea_merge(e, t);
|
ea_merge(e, t, overlay);
|
||||||
ea_sort(t);
|
ea_sort(t);
|
||||||
|
|
||||||
return t->count ? t : NULL;
|
return t->count ? t : NULL;
|
||||||
@ -850,7 +854,8 @@ ea_same(ea_list *x, ea_list *y)
|
|||||||
|
|
||||||
if (!x || !y)
|
if (!x || !y)
|
||||||
return x == y;
|
return x == y;
|
||||||
ASSERT(!x->next && !y->next);
|
if (x->next != y->next)
|
||||||
|
return 0;
|
||||||
if (x->count != y->count)
|
if (x->count != y->count)
|
||||||
return 0;
|
return 0;
|
||||||
for(c=0; c<x->count; c++)
|
for(c=0; c<x->count; c++)
|
||||||
@ -876,13 +881,12 @@ ea_list_size(ea_list *o)
|
|||||||
unsigned i, elen;
|
unsigned i, elen;
|
||||||
|
|
||||||
ASSERT_DIE(o);
|
ASSERT_DIE(o);
|
||||||
ASSERT_DIE(!o->next);
|
|
||||||
elen = BIRD_CPU_ALIGN(sizeof(ea_list) + sizeof(eattr) * o->count);
|
elen = BIRD_CPU_ALIGN(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->undef && !(a->type & EAF_EMBEDDED))
|
||||||
elen += ADATA_SIZE(a->u.ptr->length);
|
elen += ADATA_SIZE(a->u.ptr->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,7 +903,7 @@ ea_list_copy(ea_list *n, ea_list *o, uint elen)
|
|||||||
for(uint 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->undef && !(a->type & EAF_EMBEDDED))
|
||||||
{
|
{
|
||||||
unsigned size = ADATA_SIZE(a->u.ptr->length);
|
unsigned size = ADATA_SIZE(a->u.ptr->length);
|
||||||
ASSERT_DIE(adpos + size <= elen);
|
ASSERT_DIE(adpos + size <= elen);
|
||||||
@ -923,12 +927,21 @@ ea_list_ref(ea_list *l)
|
|||||||
eattr *a = &l->attrs[i];
|
eattr *a = &l->attrs[i];
|
||||||
ASSERT_DIE(a->id < ea_class_max);
|
ASSERT_DIE(a->id < ea_class_max);
|
||||||
|
|
||||||
|
if (a->undef)
|
||||||
|
continue;
|
||||||
|
|
||||||
struct ea_class *cl = ea_class_global[a->id];
|
struct ea_class *cl = ea_class_global[a->id];
|
||||||
ASSERT_DIE(cl && cl->uc);
|
ASSERT_DIE(cl && cl->uc);
|
||||||
|
|
||||||
CALL(cl->stored, a);
|
CALL(cl->stored, a);
|
||||||
cl->uc++;
|
cl->uc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (l->next)
|
||||||
|
{
|
||||||
|
ASSERT_DIE(ea_is_cached(l->next));
|
||||||
|
ea_clone(l->next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -939,6 +952,9 @@ ea_list_unref(ea_list *l)
|
|||||||
eattr *a = &l->attrs[i];
|
eattr *a = &l->attrs[i];
|
||||||
ASSERT_DIE(a->id < ea_class_max);
|
ASSERT_DIE(a->id < ea_class_max);
|
||||||
|
|
||||||
|
if (a->undef)
|
||||||
|
continue;
|
||||||
|
|
||||||
struct ea_class *cl = ea_class_global[a->id];
|
struct ea_class *cl = ea_class_global[a->id];
|
||||||
ASSERT_DIE(cl && cl->uc);
|
ASSERT_DIE(cl && cl->uc);
|
||||||
|
|
||||||
@ -946,6 +962,9 @@ ea_list_unref(ea_list *l)
|
|||||||
if (!--cl->uc)
|
if (!--cl->uc)
|
||||||
ea_class_free(cl);
|
ea_class_free(cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (l->next)
|
||||||
|
ea_free(l->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1183,11 +1202,13 @@ ea_hash(ea_list *e)
|
|||||||
|
|
||||||
if (e) /* Assuming chain of length 1 */
|
if (e) /* Assuming chain of length 1 */
|
||||||
{
|
{
|
||||||
ASSERT_DIE(!e->next);
|
h ^= mem_hash(&e->next, sizeof(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];
|
||||||
h ^= a->id; h *= mul;
|
h ^= a->id; h *= mul;
|
||||||
|
if (a->undef)
|
||||||
|
continue;
|
||||||
if (a->type & EAF_EMBEDDED)
|
if (a->type & EAF_EMBEDDED)
|
||||||
h ^= a->u.data;
|
h ^= a->u.data;
|
||||||
else
|
else
|
||||||
@ -1295,7 +1316,7 @@ ea_lookup(ea_list *o)
|
|||||||
uint h;
|
uint h;
|
||||||
|
|
||||||
ASSERT(!ea_is_cached(o));
|
ASSERT(!ea_is_cached(o));
|
||||||
o = ea_normalize(o);
|
o = ea_normalize(o, 1);
|
||||||
h = ea_hash(o);
|
h = ea_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_hash)
|
||||||
@ -1328,7 +1349,6 @@ ea__free(ea_list *a)
|
|||||||
if (a->next_hash)
|
if (a->next_hash)
|
||||||
a->next_hash->pprev_hash = a->pprev_hash;
|
a->next_hash->pprev_hash = a->pprev_hash;
|
||||||
|
|
||||||
ASSERT(!a->next);
|
|
||||||
ea_list_unref(a);
|
ea_list_unref(a);
|
||||||
mb_free(a);
|
mb_free(a);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,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)
|
if (d->verbose && !rta_is_cached(a) && a)
|
||||||
a = ea_normalize(a);
|
a = ea_normalize(a, 0);
|
||||||
|
|
||||||
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)
|
||||||
|
@ -1253,10 +1253,10 @@ 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, const ea_list *a)
|
bgp_export_attrs(struct bgp_export_state *s, ea_list *a)
|
||||||
{
|
{
|
||||||
/* Merge the attribute list */
|
/* Merge the attribute list */
|
||||||
ea_list *new = ea_normalize(a);
|
ea_list *new = ea_normalize(a, 0);
|
||||||
ASSERT_DIE(new);
|
ASSERT_DIE(new);
|
||||||
|
|
||||||
uint i, count;
|
uint i, count;
|
||||||
|
@ -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))
|
||||||
eattrs = ea_normalize(eattrs);
|
eattrs = ea_normalize(eattrs, 0);
|
||||||
|
|
||||||
mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
|
mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
|
||||||
byte *pos = b->pos;
|
byte *pos = b->pos;
|
||||||
|
Loading…
Reference in New Issue
Block a user