diff --git a/filter/f-inst.c b/filter/f-inst.c index e2212c5b..0226f729 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -714,9 +714,6 @@ case EAF_TYPE_LC_SET: RESULT_(T_LCLIST, ad, e->u.ptr); break; - case EAF_TYPE_UNDEF: - RESULT_VOID; - break; default: bug("Unknown dynamic attribute type"); } @@ -794,23 +791,8 @@ ACCESS_RTE; ACCESS_EATTRS; - { - struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); - - l->next = NULL; - l->flags = EALF_SORTED; - l->count = 1; - l->attrs[0].id = da.ea_code; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_UNDEF; - l->attrs[0].originated = 1; - l->attrs[0].fresh = 1; - l->attrs[0].u.data = 0; - - f_rta_cow(fs); - l->next = *fs->eattrs; - *fs->eattrs = l; - } + f_rta_cow(fs); + ea_unset_attr(fs->eattrs, fs->pool, 1, da.ea_code); } INST(FI_LENGTH, 1, 1) { /* Get length of */ diff --git a/nest/route.h b/nest/route.h index 9fbac898..bf25dcf9 100644 --- a/nest/route.h +++ b/nest/route.h @@ -505,6 +505,7 @@ typedef struct eattr { byte type:5; /* Attribute type */ byte originated:1; /* The attribute has originated locally */ byte fresh:1; /* An uncached attribute (e.g. modified in export filter) */ + byte undef:1; /* Explicitly undefined */ union { uintptr_t data; const struct adata *ptr; /* Attribute data elsewhere */ @@ -540,7 +541,6 @@ const char *ea_custom_name(uint ea); #define EAF_TYPE_PTR 0x0d /* Pointer to an object */ #define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */ #define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */ -#define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */ #define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */ #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */ @@ -610,27 +610,50 @@ void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const cha ea = NULL; \ } while(0) \ +struct ea_one_attr_list { + ea_list l; + eattr a; +}; + static inline eattr * ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val) { - ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr)); - eattr *e = &a->attrs[0]; + struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea)); + *ea = (struct ea_one_attr_list) { + .l.flags = EALF_SORTED, + .l.count = 1, + .l.next = *to, - a->flags = EALF_SORTED; - a->count = 1; - a->next = *to; - *to = a; - - e->id = id; - e->type = type; - e->flags = flags; + .a.id = id, + .a.type = type, + .a.flags = flags, + }; if (type & EAF_EMBEDDED) - e->u.data = (u32) val; + ea->a.u.data = val; else - e->u.ptr = (struct adata *) val; + ea->a.u.ptr = (struct adata *) val; - return e; + *to = &ea->l; + + return &ea->a; +} + +static inline void +ea_unset_attr(ea_list **to, struct linpool *pool, _Bool local, uint code) +{ + struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea)); + *ea = (struct ea_one_attr_list) { + .l.flags = EALF_SORTED, + .l.count = 1, + .l.next = *to, + .a.id = code, + .a.fresh = local, + .a.originated = local, + .a.undef = 1, + }; + + *to = &ea->l; } static inline void diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 2f0395c7..22b45db9 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -448,8 +448,7 @@ ea_find(ea_list *e, unsigned id) { eattr *a = ea__find(e, id & EA_CODE_MASK); - if (a && (a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF && - !(id & EA_ALLOW_UNDEF)) + if (a && a->undef && !(id & EA_ALLOW_UNDEF)) return NULL; return a; } @@ -516,7 +515,7 @@ ea_walk(struct ea_walk_state *s, uint id, uint max) BIT32_SET(s->visited, n); - if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + if (a->undef) continue; s->eattrs = e; @@ -616,7 +615,7 @@ ea_do_prune(ea_list *e) /* Now s0 is the most recent version, s[-1] the oldest one */ /* Drop undefs */ - if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + if (s0->undef) continue; /* Copy the newest version to destination */ @@ -742,6 +741,7 @@ ea_same(ea_list *x, ea_list *y) a->type != b->type || a->originated != b->originated || a->fresh != b->fresh || + a->undef != b->undef || ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr))) return 0; } @@ -944,6 +944,10 @@ ea_show(struct cli *c, const eattr *e) { *pos++ = ':'; *pos++ = ' '; + + if (e->undef) + bsprintf(pos, "undefined"); + else switch (e->type & EAF_TYPE_MASK) { case EAF_TYPE_INT: @@ -973,7 +977,6 @@ ea_show(struct cli *c, const eattr *e) case EAF_TYPE_LC_SET: ea_show_lc_set(c, ad, pos, buf, end); return; - case EAF_TYPE_UNDEF: default: bsprintf(pos, "", e->type); } diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 0513dd7c..454686cf 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -106,7 +106,7 @@ bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintp ({ REPORT(msg, ## args); s->err_withdraw = 1; return; }) #define UNSET(a) \ - ({ a->type = EAF_TYPE_UNDEF; return; }) + ({ a->undef = 1; return; }) #define REJECT(msg, args...) \ ({ log(L_ERR "%s: " msg, s->proto->p.name, ## args); s->err_reject = 1; return; }) @@ -1161,7 +1161,7 @@ bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to) CALL(desc->export, s, a); /* Attribute might become undefined in hook */ - if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) + if (a->undef) return; } else diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index bff49c3a..8a44514c 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -563,9 +563,7 @@ bgp_set_attr_data(ea_list **to, struct linpool *pool, uint code, uint flags, voi bgp_set_attr(to, pool, code, flags, (uintptr_t) a); } -static inline void -bgp_unset_attr(ea_list **to, struct linpool *pool, uint code) -{ eattr *e = bgp_set_attr(to, pool, code, 0, 0); e->type = EAF_TYPE_UNDEF; } +#define bgp_unset_attr(to, pool, code) ea_unset_attr(to, pool, 0, code) int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);