summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-03-26 11:56:02 +0100
committerMaria Matejka <mq@ucw.cz>2022-05-04 15:37:41 +0200
commit0d0f6554a5c233bf2bf830ae319191c4b1808d49 (patch)
treeb90790a9450dc4eaefd1cab522d49221d358a5d9 /filter
parent80272d4b64a38ee6f04a1c4e8566cac3a2293176 (diff)
Unified attribute and filter types
This commit removes the EAF_TYPE_* namespace completely and also for route attributes, filter-based types T_* are used. This simplifies fetching and setting route attributes from filters. Also, there is now union bval which serves as an universal value holder instead of private unions held separately by eattr and filter code.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y25
-rw-r--r--filter/data.c20
-rw-r--r--filter/data.h84
-rw-r--r--filter/decl.m44
-rw-r--r--filter/f-inst.c128
-rw-r--r--filter/f-inst.h12
-rw-r--r--filter/f-util.c27
-rw-r--r--filter/filter.h2
-rw-r--r--filter/test.conf6
9 files changed, 97 insertions, 211 deletions
diff --git a/filter/config.Y b/filter/config.Y
index fb331c16..22981945 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -163,26 +163,11 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
static inline struct f_inst *
f_generate_empty(struct f_dynamic_attr dyn)
{
- struct f_val empty;
+ const struct f_val *empty = f_get_empty(dyn.type);
+ if (!empty)
+ cf_error("Can't empty that attribute");
- switch (dyn.type) {
- case EAF_TYPE_AS_PATH:
- empty = f_const_empty_path;
- break;
- case EAF_TYPE_INT_SET:
- empty = f_const_empty_clist;
- break;
- case EAF_TYPE_EC_SET:
- empty = f_const_empty_eclist;
- break;
- case EAF_TYPE_LC_SET:
- empty = f_const_empty_lclist;
- break;
- default:
- cf_error("Can't empty that attribute");
- }
-
- return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, empty), dyn);
+ return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, *empty), dyn);
}
#define BA_AS_PATH 0x02
@@ -190,7 +175,7 @@ f_generate_empty(struct f_dynamic_attr dyn)
static inline struct f_inst *
f_implicit_roa_check(struct rtable_config *tab)
{
- struct f_dynamic_attr fda = f_new_dynamic_attr(EAF_TYPE_AS_PATH, T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
+ struct f_dynamic_attr fda = f_new_dynamic_attr(T_PATH, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1);
diff --git a/filter/data.c b/filter/data.c
index 56c1fb17..c3f8bf57 100644
--- a/filter/data.c
+++ b/filter/data.c
@@ -27,6 +27,8 @@
static const char * const f_type_str[] = {
[T_VOID] = "void",
+ [T_OPAQUE] = "opaque byte string",
+ [T_IFACE] = "interface",
[T_INT] = "int",
[T_BOOL] = "bool",
@@ -47,6 +49,7 @@ static const char * const f_type_str[] = {
[T_NET] = "prefix",
[T_STRING] = "string",
[T_PATH_MASK] = "bgpmask",
+ [T_PATH_MASK_ITEM] = "bgpmask item",
[T_PATH] = "bgppath",
[T_CLIST] = "clist",
[T_EC] = "ec",
@@ -54,22 +57,19 @@ static const char * const f_type_str[] = {
[T_LC] = "lc",
[T_LCLIST] = "lclist",
[T_RD] = "rd",
+
+ [T_SET] = "set",
+ [T_PREFIX_SET] = "prefix set",
};
const char *
-f_type_name(enum f_type t)
+f_type_name(btype t)
{
- if (t < ARRAY_SIZE(f_type_str))
- return f_type_str[t] ?: "?";
-
- if ((t == T_SET) || (t == T_PREFIX_SET))
- return "set";
-
- return "?";
+ return (t < ARRAY_SIZE(f_type_str)) ? (f_type_str[t] ?: "?") : "?";
}
-enum f_type
-f_type_element_type(enum f_type t)
+btype
+f_type_element_type(btype t)
{
switch(t) {
case T_CLIST: return T_PAIR;
diff --git a/filter/data.h b/filter/data.h
index 924bbf3e..0b1e8e57 100644
--- a/filter/data.h
+++ b/filter/data.h
@@ -11,65 +11,15 @@
#define _BIRD_FILTER_DATA_H_
#include "nest/bird.h"
-
-/* Type numbers must be in 0..0xff range */
-#define T_MASK 0xff
-
-/* Internal types */
-enum f_type {
-/* Nothing. Simply nothing. */
- T_VOID = 0,
-
-/* Something but inaccessible. */
- T_OPAQUE = 0xee,
-
-/* User visible types, which fit in int */
- T_INT = 0x10,
- T_BOOL = 0x11,
- T_PAIR = 0x12, /* Notice that pair is stored as integer: first << 16 | second */
- T_QUAD = 0x13,
-
-/* Put enumerational types in 0x30..0x3f range */
- T_ENUM_LO = 0x30,
- T_ENUM_HI = 0x3f,
-
- T_ENUM_RTS = 0x30,
- T_ENUM_BGP_ORIGIN = 0x31,
- T_ENUM_SCOPE = 0x32,
- T_ENUM_RTC = 0x33,
- T_ENUM_RTD = 0x34,
- T_ENUM_ROA = 0x35,
- T_ENUM_NETTYPE = 0x36,
- T_ENUM_RA_PREFERENCE = 0x37,
- T_ENUM_AF = 0x38,
-
-/* new enums go here */
-
-#define T_ENUM T_ENUM_LO ... T_ENUM_HI
-
-/* Bigger ones */
- T_IP = 0x20,
- T_NET = 0x21,
- T_STRING = 0x22,
- T_PATH_MASK = 0x23, /* mask for BGP path */
- T_PATH = 0x24, /* BGP path */
- T_CLIST = 0x25, /* Community list */
- T_EC = 0x26, /* Extended community value, u64 */
- T_ECLIST = 0x27, /* Extended community list */
- T_LC = 0x28, /* Large community value, lcomm */
- T_LCLIST = 0x29, /* Large community list */
- T_RD = 0x2a, /* Route distinguisher for VPN addresses */
- T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */
-
- T_SET = 0x80,
- T_PREFIX_SET = 0x81,
-} PACKED;
+#include "lib/type.h"
/* Filter value; size of this affects filter memory consumption */
struct f_val {
- enum f_type type; /* T_* */
+ btype type; /* T_* */
union {
- uint i;
+ union bval bval;
+ BVAL_ITEMS;
+
u64 ec;
lcomm lc;
ip_addr ip;
@@ -77,17 +27,17 @@ struct f_val {
const char *s;
const struct f_tree *t;
const struct f_trie *ti;
- const struct adata *ad;
const struct f_path_mask *path_mask;
struct f_path_mask_item pmi;
} val;
};
+#define fputip(a) ({ ip_addr *ax = falloc(sizeof(*ax)); *ax = (a); ax; })
+
/* Dynamic attribute definition (eattrs) */
struct f_dynamic_attr {
- u8 type; /* EA type (EAF_*) */
+ btype type; /* EA type (EAF_*) */
u8 bit; /* For bitfield accessors */
- enum f_type f_type; /* Filter type */
uint ea_code; /* EA code */
};
@@ -108,9 +58,9 @@ enum f_sa_code {
/* Static attribute definition (members of struct rta) */
struct f_static_attr {
- enum f_type f_type; /* Filter type */
+ btype type; /* Data type */
enum f_sa_code sa_code; /* Static attribute id */
- int readonly:1; /* Don't allow writing */
+ int readonly:1; /* Don't allow writing */
};
/* Filter l-value type */
@@ -266,9 +216,9 @@ trie_match_next_longest_ip6(net_addr_ip6 *n, ip6_addr *found)
#define F_CMP_ERROR 999
-const char *f_type_name(enum f_type t);
+const char *f_type_name(btype t);
-enum f_type f_type_element_type(enum f_type t);
+enum btype f_type_element_type(btype t);
int val_same(const struct f_val *v1, const struct f_val *v2);
int val_compare(const struct f_val *v1, const struct f_val *v2);
@@ -301,6 +251,16 @@ undef_value(struct f_val v)
}
extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist;
+static inline const struct f_val *f_get_empty(btype t)
+{
+ switch (t) {
+ case T_PATH: return &f_const_empty_path;
+ case T_CLIST: return &f_const_empty_clist;
+ case T_ECLIST: return &f_const_empty_eclist;
+ case T_LCLIST: return &f_const_empty_lclist;
+ default: return NULL;
+ }
+}
enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres);
diff --git a/filter/decl.m4 b/filter/decl.m4
index 44537aaa..2e4fb235 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -490,7 +490,7 @@ fi_constant(struct f_inst *what, struct f_val val)
}
static int
-f_const_promotion(struct f_inst *arg, enum f_type want)
+f_const_promotion(struct f_inst *arg, btype want)
{
if (arg->fi_code != FI_CONSTANT)
return 0;
@@ -640,7 +640,7 @@ FID_WR_PUT(4)m4_dnl
struct f_inst {
struct f_inst *next; /* Next instruction */
enum f_instruction_code fi_code; /* Instruction code */
- enum f_type type; /* Type of returned value, if known */
+ btype type; /* Type of returned value, if known */
int size; /* How many instructions are underneath */
int lineno; /* Line number */
union {
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 75a53499..e0bad833 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -533,21 +533,21 @@
switch (sa.sa_code)
{
- case SA_FROM: RESULT(sa.f_type, ip, rta->from); break;
- case SA_GW: RESULT(sa.f_type, ip, rta->nh.gw); break;
- case SA_NET: RESULT(sa.f_type, net, (*fs->rte)->net->n.addr); break;
- case SA_PROTO: RESULT(sa.f_type, s, (*fs->rte)->src->proto->name); break;
- case SA_SOURCE: RESULT(sa.f_type, i, rta->source); break;
- case SA_SCOPE: RESULT(sa.f_type, i, rta->scope); break;
- case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
- case SA_IFNAME: RESULT(sa.f_type, s, rta->nh.iface ? rta->nh.iface->name : ""); break;
- case SA_IFINDEX: RESULT(sa.f_type, i, rta->nh.iface ? rta->nh.iface->index : 0); break;
- case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break;
- case SA_PREF: RESULT(sa.f_type, i, rta->pref); break;
- case SA_GW_MPLS: RESULT(sa.f_type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break;
+ case SA_FROM: RESULT(sa.type, ip, rta->from); break;
+ case SA_GW: RESULT(sa.type, ip, rta->nh.gw); break;
+ case SA_NET: RESULT(sa.type, net, (*fs->rte)->net->n.addr); break;
+ case SA_PROTO: RESULT(sa.type, s, (*fs->rte)->src->proto->name); break;
+ case SA_SOURCE: RESULT(sa.type, i, rta->source); break;
+ case SA_SCOPE: RESULT(sa.type, i, rta->scope); break;
+ case SA_DEST: RESULT(sa.type, i, rta->dest); break;
+ case SA_IFNAME: RESULT(sa.type, s, rta->nh.iface ? rta->nh.iface->name : ""); break;
+ case SA_IFINDEX: RESULT(sa.type, i, rta->nh.iface ? rta->nh.iface->index : 0); break;
+ case SA_WEIGHT: RESULT(sa.type, i, rta->nh.weight + 1); break;
+ case SA_PREF: RESULT(sa.type, i, rta->pref); break;
+ case SA_GW_MPLS: RESULT(sa.type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break;
default:
- bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
+ bug("Invalid static attribute access (%u/%u)", sa.type, sa.sa_code);
}
}
}
@@ -556,7 +556,7 @@
ACCESS_RTE;
ARG_ANY(1);
STATIC_ATTR;
- ARG_TYPE(1, sa.f_type);
+ ARG_TYPE(1, sa.type);
f_rta_cow(fs);
{
@@ -653,7 +653,7 @@
break;
default:
- bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
+ bug("Invalid static attribute access (%u/%u)", sa.type, sa.sa_code);
}
}
}
@@ -662,68 +662,30 @@
DYNAMIC_ATTR;
ACCESS_RTE;
ACCESS_EATTRS;
- RESULT_TYPE(da.f_type);
+ RESULT_TYPE(da.type);
{
+ const struct f_val *empty;
eattr *e = ea_find(*fs->eattrs, da.ea_code);
- if (!e) {
- /* A special case: undefined as_path looks like empty as_path */
- if (da.type == EAF_TYPE_AS_PATH) {
- RESULT_(T_PATH, ad, &null_adata);
- break;
- }
-
- /* The same special case for int_set */
- if (da.type == EAF_TYPE_INT_SET) {
- RESULT_(T_CLIST, ad, &null_adata);
- break;
- }
-
- /* The same special case for ec_set */
- if (da.type == EAF_TYPE_EC_SET) {
- RESULT_(T_ECLIST, ad, &null_adata);
- break;
- }
+ if (e)
+ {
+ ASSERT_DIE(e->type == da.type);
- /* The same special case for lc_set */
- if (da.type == EAF_TYPE_LC_SET) {
- RESULT_(T_LCLIST, ad, &null_adata);
- break;
+ switch (e->type) {
+ case T_IP:
+ RESULT_(T_IP, ip, *((const ip_addr *) e->u.ptr->data));
+ break;
+ default:
+ RESULT_VAL([[(struct f_val) {
+ .type = e->type,
+ .val.bval = e->u,
+ }]]);
}
-
- /* Undefined value */
- RESULT_VOID;
- break;
- }
-
- switch (e->type) {
- case EAF_TYPE_INT:
- RESULT_(da.f_type, i, e->u.data);
- break;
- case EAF_TYPE_ROUTER_ID:
- RESULT_(T_QUAD, i, e->u.data);
- break;
- case EAF_TYPE_OPAQUE:
- RESULT_(T_OPAQUE, ad, e->u.ptr);
- break;
- case EAF_TYPE_IP_ADDRESS:
- RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data));
- break;
- case EAF_TYPE_AS_PATH:
- RESULT_(T_PATH, ad, e->u.ptr);
- break;
- case EAF_TYPE_INT_SET:
- RESULT_(T_CLIST, ad, e->u.ptr);
- break;
- case EAF_TYPE_EC_SET:
- RESULT_(T_ECLIST, ad, e->u.ptr);
- break;
- case EAF_TYPE_LC_SET:
- RESULT_(T_LCLIST, ad, e->u.ptr);
- break;
- default:
- bug("Unknown dynamic attribute type");
}
+ else if (empty = f_get_empty(da.type))
+ RESULT_VAL(*empty);
+ else
+ RESULT_VOID;
}
}
@@ -732,7 +694,7 @@
ACCESS_EATTRS;
ARG_ANY(1);
DYNAMIC_ATTR;
- ARG_TYPE(1, da.f_type);
+ ARG_TYPE(1, da.type);
{
struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));
@@ -746,17 +708,16 @@
l->attrs[0].fresh = 1;
l->attrs[0].undef = 0;
- switch (da.type) {
- case EAF_TYPE_INT:
- case EAF_TYPE_ROUTER_ID:
- l->attrs[0].u.data = v1.val.i;
- break;
+ if (da.type >= EAF_TYPE__MAX)
+ bug("Unsupported attribute type");
- case EAF_TYPE_OPAQUE:
+ switch (da.type) {
+ case T_OPAQUE:
+ case T_IFACE:
runtime( "Setting opaque attribute is not allowed" );
break;
- case EAF_TYPE_IP_ADDRESS:;
+ case T_IP:;
int len = sizeof(ip_addr);
struct adata *ad = lp_alloc(fs->pool, sizeof(struct adata) + len);
ad->length = len;
@@ -764,15 +725,10 @@
l->attrs[0].u.ptr = ad;
break;
- case EAF_TYPE_AS_PATH:
- case EAF_TYPE_INT_SET:
- case EAF_TYPE_EC_SET:
- case EAF_TYPE_LC_SET:
- l->attrs[0].u.ptr = v1.val.ad;
+ default:
+ l->attrs[0].u = v1.val.bval;
break;
- default:
- bug("Unknown dynamic attribute type");
}
f_rta_cow(fs);
diff --git a/filter/f-inst.h b/filter/f-inst.h
index 9265ecec..32da4653 100644
--- a/filter/f-inst.h
+++ b/filter/f-inst.h
@@ -87,12 +87,12 @@ void f_add_lines(const struct f_line_item *what, struct filter_iterator *fit);
struct filter *f_new_where(struct f_inst *);
-static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
-{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
-static inline struct f_dynamic_attr f_new_dynamic_attr_bit(u8 bit, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
-{ return (struct f_dynamic_attr) { .type = EAF_TYPE_INT, .bit = bit, .f_type = T_INT, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
-static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
-{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; }
+static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, uint code)
+{ return (struct f_dynamic_attr) { .type = type, .ea_code = code }; }
+static inline struct f_dynamic_attr f_new_dynamic_attr_bit(u8 bit, uint code)
+{ return (struct f_dynamic_attr) { .type = T_INT, .bit = bit, .ea_code = code }; }
+static inline struct f_static_attr f_new_static_attr(btype type, int code, int readonly)
+{ return (struct f_static_attr) { .type = type, .sa_code = code, .readonly = readonly }; }
struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument);
struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
diff --git a/filter/f-util.c b/filter/f-util.c
index 410999a6..79cf3452 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -82,8 +82,8 @@ static void
ca_dump(resource *r)
{
struct custom_attribute *ca = (void *) r;
- debug("name \"%s\" id 0x%04x ea_type 0x%02x f_type 0x%02x\n",
- ca->name, ca->fda->ea_code, ca->fda->type, ca->fda->f_type);
+ debug("name \"%s\" id 0x%04x ea_type 0x%02x\n",
+ ca->name, ca->fda->ea_code, ca->fda->type);
}
static struct resclass ca_class = {
@@ -96,31 +96,16 @@ static struct resclass ca_class = {
};
struct custom_attribute *
-ca_lookup(pool *p, const char *name, int f_type)
+ca_lookup(pool *p, const char *name, btype type)
{
- int ea_type;
-
- switch (f_type) {
+ switch (type) {
case T_INT:
- ea_type = EAF_TYPE_INT;
- break;
case T_IP:
- ea_type = EAF_TYPE_IP_ADDRESS;
- break;
case T_QUAD:
- ea_type = EAF_TYPE_ROUTER_ID;
- break;
case T_PATH:
- ea_type = EAF_TYPE_AS_PATH;
- break;
case T_CLIST:
- ea_type = EAF_TYPE_INT_SET;
- break;
case T_ECLIST:
- ea_type = EAF_TYPE_EC_SET;
- break;
case T_LCLIST:
- ea_type = EAF_TYPE_LC_SET;
break;
default:
cf_error("Custom route attribute of unsupported type");
@@ -137,7 +122,7 @@ ca_lookup(pool *p, const char *name, int f_type)
inited++;
}
- struct ca_storage *cas = HASH_FIND(ca_hash, CA, name, ea_type);
+ struct ca_storage *cas = HASH_FIND(ca_hash, CA, name, type);
if (cas) {
cas->uc++;
} else {
@@ -153,7 +138,7 @@ ca_lookup(pool *p, const char *name, int f_type)
}
cas = mb_allocz(&root_pool, sizeof(struct ca_storage) + strlen(name) + 1);
- cas->fda = f_new_dynamic_attr(ea_type, f_type, EA_CUSTOM(id));
+ cas->fda = f_new_dynamic_attr(type, EA_CUSTOM(id));
cas->uc = 1;
strcpy(cas->name, name);
diff --git a/filter/filter.h b/filter/filter.h
index 26c1037b..e9c9d917 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -77,6 +77,6 @@ struct custom_attribute {
const char *name;
};
-struct custom_attribute *ca_lookup(pool *p, const char *name, int ea_type);
+struct custom_attribute *ca_lookup(pool *p, const char *name, btype type);
#endif
diff --git a/filter/test.conf b/filter/test.conf
index ee2f5be4..062756b1 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -406,9 +406,9 @@ bt_test_suite(t_ip_set, "Testing sets of ip address");
function t_enum()
{
- bt_assert(format(RTS_STATIC) = "(enum 30)1");
- bt_assert(format(NET_IP4) = "(enum 36)1");
- bt_assert(format(NET_VPN6) = "(enum 36)4");
+ bt_assert(format(RTS_STATIC) = "(enum 31)1");
+ bt_assert(format(NET_IP4) = "(enum 3b)1");
+ bt_assert(format(NET_VPN6) = "(enum 3b)4");
bt_assert(RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE]);
bt_assert(RTS_BGP !~ [RTS_STATIC, RTS_DEVICE]);