Add bitfield route attribute type

This commit is contained in:
Ondrej Zajicek 2015-05-09 18:50:15 +02:00
parent 77edab6409
commit 315f23a047
3 changed files with 90 additions and 26 deletions

View file

@ -516,6 +516,9 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
#define ACCESS_RTE \ #define ACCESS_RTE \
do { if (!f_rte) runtime("No route to access"); } while (0) do { if (!f_rte) runtime("No route to access"); } while (0)
#define BITFIELD_MASK(what) \
(1u << (what->a2.i >> 24))
/** /**
* interpret * interpret
* @what: filter to interpret * @what: filter to interpret
@ -864,12 +867,14 @@ interpret(struct f_inst *what)
ACCESS_RTE; ACCESS_RTE;
{ {
eattr *e = NULL; eattr *e = NULL;
u16 code = what->a2.i;
if (!(f_flags & FF_FORCE_TMPATTR)) if (!(f_flags & FF_FORCE_TMPATTR))
e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i ); e = ea_find((*f_rte)->attrs->eattrs, code);
if (!e) if (!e)
e = ea_find( (*f_tmp_attrs), what->a2.i ); e = ea_find((*f_tmp_attrs), code);
if ((!e) && (f_flags & FF_FORCE_TMPATTR)) if ((!e) && (f_flags & FF_FORCE_TMPATTR))
e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i ); e = ea_find((*f_rte)->attrs->eattrs, code);
if (!e) { if (!e) {
/* A special case: undefined int_set looks like empty int_set */ /* A special case: undefined int_set looks like empty int_set */
@ -878,8 +883,9 @@ interpret(struct f_inst *what)
res.val.ad = adata_empty(f_pool, 0); res.val.ad = adata_empty(f_pool, 0);
break; break;
} }
/* The same special case for ec_set */ /* The same special case for ec_set */
else if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) { if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
res.type = T_ECLIST; res.type = T_ECLIST;
res.val.ad = adata_empty(f_pool, 0); res.val.ad = adata_empty(f_pool, 0);
break; break;
@ -912,6 +918,10 @@ interpret(struct f_inst *what)
res.type = T_PATH; res.type = T_PATH;
res.val.ad = e->u.ptr; res.val.ad = e->u.ptr;
break; break;
case EAF_TYPE_BITFIELD:
res.type = T_BOOL;
res.val.i = !!(e->u.data & BITFIELD_MASK(what));
break;
case EAF_TYPE_INT_SET: case EAF_TYPE_INT_SET:
res.type = T_CLIST; res.type = T_CLIST;
res.val.ad = e->u.ptr; res.val.ad = e->u.ptr;
@ -933,13 +943,15 @@ interpret(struct f_inst *what)
ONEARG; ONEARG;
{ {
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr)); struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
u16 code = what->a2.i;
l->next = NULL; l->next = NULL;
l->flags = EALF_SORTED; l->flags = EALF_SORTED;
l->count = 1; l->count = 1;
l->attrs[0].id = what->a2.i; l->attrs[0].id = code;
l->attrs[0].flags = 0; l->attrs[0].flags = 0;
l->attrs[0].type = what->aux | EAF_ORIGINATED; l->attrs[0].type = what->aux | EAF_ORIGINATED;
switch (what->aux & EAF_TYPE_MASK) { switch (what->aux & EAF_TYPE_MASK) {
case EAF_TYPE_INT: case EAF_TYPE_INT:
if (v1.type != T_INT) if (v1.type != T_INT)
@ -978,6 +990,26 @@ interpret(struct f_inst *what)
runtime( "Setting path attribute to non-path value" ); runtime( "Setting path attribute to non-path value" );
l->attrs[0].u.ptr = v1.val.ad; l->attrs[0].u.ptr = v1.val.ad;
break; break;
case EAF_TYPE_BITFIELD:
if (v1.type != T_BOOL)
runtime( "Setting bit in bitfield attribute to non-bool value" );
{
/* First, we have to find the old value */
eattr *e = NULL;
if (!(f_flags & FF_FORCE_TMPATTR))
e = ea_find((*f_rte)->attrs->eattrs, code);
if (!e)
e = ea_find((*f_tmp_attrs), code);
if ((!e) && (f_flags & FF_FORCE_TMPATTR))
e = ea_find((*f_rte)->attrs->eattrs, code);
u32 data = e ? e->u.data : 0;
if (v1.val.i)
l->attrs[0].u.data = data | BITFIELD_MASK(what);
else
l->attrs[0].u.data = data & ~BITFIELD_MASK(what);;
}
break;
case EAF_TYPE_INT_SET: case EAF_TYPE_INT_SET:
if (v1.type != T_CLIST) if (v1.type != T_CLIST)
runtime( "Setting clist attribute to non-clist value" ); runtime( "Setting clist attribute to non-clist value" );

View file

@ -417,13 +417,15 @@ typedef struct eattr {
#define EA_CODE_MASK 0xffff #define EA_CODE_MASK 0xffff
#define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */ #define EA_ALLOW_UNDEF 0x10000 /* ea_find: allow EAF_TYPE_UNDEF */
#define EA_BIT(n) ((n) << 24) /* Used in bitfield accessors */
#define EAF_TYPE_MASK 0x0f /* Mask with this to get type */ #define EAF_TYPE_MASK 0x0f /* Mask with this to get type */
#define EAF_TYPE_INT 0x01 /* 32-bit signed integer number */ #define EAF_TYPE_INT 0x01 /* 32-bit unsigned integer number */
#define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */ #define EAF_TYPE_OPAQUE 0x02 /* Opaque byte string (not filterable) */
#define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */ #define EAF_TYPE_IP_ADDRESS 0x04 /* IP address */
#define EAF_TYPE_ROUTER_ID 0x05 /* Router ID (IPv4 address) */ #define EAF_TYPE_ROUTER_ID 0x05 /* Router ID (IPv4 address) */
#define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */ #define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */
#define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */
#define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */ #define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */
#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_UNDEF 0x0f /* `force undefined' entry */ #define EAF_TYPE_UNDEF 0x0f /* `force undefined' entry */
@ -469,6 +471,7 @@ void ea_merge(ea_list *from, ea_list *to); /* Merge sub-lists to allocated buffe
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 */
unsigned int ea_hash(ea_list *e); /* Calculate 16-bit hash value */ unsigned int 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(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
int mpnh__same(struct mpnh *x, struct mpnh *y); /* Compare multipath nexthops */ int mpnh__same(struct mpnh *x, struct mpnh *y); /* Compare multipath nexthops */
static inline int mpnh_same(struct mpnh *x, struct mpnh *y) static inline int mpnh_same(struct mpnh *x, struct mpnh *y)

View file

@ -563,6 +563,32 @@ get_generic_attr(eattr *a, byte **buf, int buflen UNUSED)
return GA_UNKNOWN; return GA_UNKNOWN;
} }
void
ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max)
{
byte *bound = buf + bufsize - 32;
u32 data = a->u.data;
int i;
for (i = min; i < max; i++)
if ((data & (1u << i)) && names[i])
{
if (buf > bound)
{
strcpy(buf, " ...");
return;
}
buf += bsprintf(buf, " %s", names[i]);
data &= ~(1u << i);
}
if (data)
bsprintf(buf, " %08x", data);
return;
}
static inline void static inline void
opaque_format(struct adata *ad, byte *buf, unsigned int size) opaque_format(struct adata *ad, byte *buf, unsigned int size)
{ {
@ -665,6 +691,9 @@ ea_show(struct cli *c, eattr *e)
case EAF_TYPE_AS_PATH: case EAF_TYPE_AS_PATH:
as_path_format(ad, pos, end - pos); as_path_format(ad, pos, end - pos);
break; break;
case EAF_TYPE_BITFIELD:
bsprintf(pos, "%08x", e->u.data);
break;
case EAF_TYPE_INT_SET: case EAF_TYPE_INT_SET:
ea_show_int_set(c, ad, 1, pos, buf, end); ea_show_int_set(c, ad, 1, pos, buf, end);
return; return;