Unsetting route attributes without messing with type system
This commit is contained in:
parent
63cf5d5d8c
commit
0f68515263
5 changed files with 50 additions and 44 deletions
|
@ -714,9 +714,6 @@
|
||||||
case EAF_TYPE_LC_SET:
|
case EAF_TYPE_LC_SET:
|
||||||
RESULT_(T_LCLIST, ad, e->u.ptr);
|
RESULT_(T_LCLIST, ad, e->u.ptr);
|
||||||
break;
|
break;
|
||||||
case EAF_TYPE_UNDEF:
|
|
||||||
RESULT_VOID;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
bug("Unknown dynamic attribute type");
|
bug("Unknown dynamic attribute type");
|
||||||
}
|
}
|
||||||
|
@ -794,23 +791,8 @@
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
ACCESS_EATTRS;
|
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);
|
f_rta_cow(fs);
|
||||||
l->next = *fs->eattrs;
|
ea_unset_attr(fs->eattrs, fs->pool, 1, da.ea_code);
|
||||||
*fs->eattrs = l;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_LENGTH, 1, 1) { /* Get length of */
|
INST(FI_LENGTH, 1, 1) { /* Get length of */
|
||||||
|
|
51
nest/route.h
51
nest/route.h
|
@ -505,6 +505,7 @@ typedef struct eattr {
|
||||||
byte type:5; /* Attribute type */
|
byte type:5; /* Attribute type */
|
||||||
byte originated:1; /* The attribute has originated locally */
|
byte originated:1; /* The attribute has originated locally */
|
||||||
byte fresh:1; /* An uncached attribute (e.g. modified in export filter) */
|
byte fresh:1; /* An uncached attribute (e.g. modified in export filter) */
|
||||||
|
byte undef:1; /* Explicitly undefined */
|
||||||
union {
|
union {
|
||||||
uintptr_t data;
|
uintptr_t data;
|
||||||
const struct adata *ptr; /* Attribute data elsewhere */
|
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_PTR 0x0d /* Pointer to an object */
|
||||||
#define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */
|
#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_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_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) */
|
#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; \
|
ea = NULL; \
|
||||||
} while(0) \
|
} while(0) \
|
||||||
|
|
||||||
|
struct ea_one_attr_list {
|
||||||
|
ea_list l;
|
||||||
|
eattr a;
|
||||||
|
};
|
||||||
|
|
||||||
static inline eattr *
|
static inline eattr *
|
||||||
ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
|
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));
|
struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea));
|
||||||
eattr *e = &a->attrs[0];
|
*ea = (struct ea_one_attr_list) {
|
||||||
|
.l.flags = EALF_SORTED,
|
||||||
|
.l.count = 1,
|
||||||
|
.l.next = *to,
|
||||||
|
|
||||||
a->flags = EALF_SORTED;
|
.a.id = id,
|
||||||
a->count = 1;
|
.a.type = type,
|
||||||
a->next = *to;
|
.a.flags = flags,
|
||||||
*to = a;
|
};
|
||||||
|
|
||||||
e->id = id;
|
|
||||||
e->type = type;
|
|
||||||
e->flags = flags;
|
|
||||||
|
|
||||||
if (type & EAF_EMBEDDED)
|
if (type & EAF_EMBEDDED)
|
||||||
e->u.data = (u32) val;
|
ea->a.u.data = val;
|
||||||
else
|
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
|
static inline void
|
||||||
|
|
|
@ -448,8 +448,7 @@ ea_find(ea_list *e, unsigned id)
|
||||||
{
|
{
|
||||||
eattr *a = ea__find(e, id & EA_CODE_MASK);
|
eattr *a = ea__find(e, id & EA_CODE_MASK);
|
||||||
|
|
||||||
if (a && (a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF &&
|
if (a && a->undef && !(id & EA_ALLOW_UNDEF))
|
||||||
!(id & EA_ALLOW_UNDEF))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
@ -516,7 +515,7 @@ ea_walk(struct ea_walk_state *s, uint id, uint max)
|
||||||
|
|
||||||
BIT32_SET(s->visited, n);
|
BIT32_SET(s->visited, n);
|
||||||
|
|
||||||
if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
|
if (a->undef)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s->eattrs = e;
|
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 */
|
/* Now s0 is the most recent version, s[-1] the oldest one */
|
||||||
/* Drop undefs */
|
/* Drop undefs */
|
||||||
if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
|
if (s0->undef)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Copy the newest version to destination */
|
/* Copy the newest version to destination */
|
||||||
|
@ -742,6 +741,7 @@ ea_same(ea_list *x, ea_list *y)
|
||||||
a->type != b->type ||
|
a->type != b->type ||
|
||||||
a->originated != b->originated ||
|
a->originated != b->originated ||
|
||||||
a->fresh != b->fresh ||
|
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)))
|
((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr)))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -944,6 +944,10 @@ ea_show(struct cli *c, const eattr *e)
|
||||||
{
|
{
|
||||||
*pos++ = ':';
|
*pos++ = ':';
|
||||||
*pos++ = ' ';
|
*pos++ = ' ';
|
||||||
|
|
||||||
|
if (e->undef)
|
||||||
|
bsprintf(pos, "undefined");
|
||||||
|
else
|
||||||
switch (e->type & EAF_TYPE_MASK)
|
switch (e->type & EAF_TYPE_MASK)
|
||||||
{
|
{
|
||||||
case EAF_TYPE_INT:
|
case EAF_TYPE_INT:
|
||||||
|
@ -973,7 +977,6 @@ ea_show(struct cli *c, const eattr *e)
|
||||||
case EAF_TYPE_LC_SET:
|
case EAF_TYPE_LC_SET:
|
||||||
ea_show_lc_set(c, ad, pos, buf, end);
|
ea_show_lc_set(c, ad, pos, buf, end);
|
||||||
return;
|
return;
|
||||||
case EAF_TYPE_UNDEF:
|
|
||||||
default:
|
default:
|
||||||
bsprintf(pos, "<type %02x>", e->type);
|
bsprintf(pos, "<type %02x>", e->type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; })
|
({ REPORT(msg, ## args); s->err_withdraw = 1; return; })
|
||||||
|
|
||||||
#define UNSET(a) \
|
#define UNSET(a) \
|
||||||
({ a->type = EAF_TYPE_UNDEF; return; })
|
({ a->undef = 1; return; })
|
||||||
|
|
||||||
#define REJECT(msg, args...) \
|
#define REJECT(msg, args...) \
|
||||||
({ log(L_ERR "%s: " msg, s->proto->p.name, ## args); s->err_reject = 1; return; })
|
({ 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);
|
CALL(desc->export, s, a);
|
||||||
|
|
||||||
/* Attribute might become undefined in hook */
|
/* Attribute might become undefined in hook */
|
||||||
if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
|
if (a->undef)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -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);
|
bgp_set_attr(to, pool, code, flags, (uintptr_t) a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
#define bgp_unset_attr(to, pool, code) ea_unset_attr(to, pool, 0, code)
|
||||||
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; }
|
|
||||||
|
|
||||||
int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue