diff options
author | Maria Matejka <mq@ucw.cz> | 2022-05-30 15:43:13 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-05-30 15:43:13 +0200 |
commit | 54344f15f8a6a6f5f0388097a1825a9c08c17482 (patch) | |
tree | 85af19e3330719d3486efdf8a12fc5f9549b72ac /filter | |
parent | 3752654852f4962465154257348000d6de1c2dae (diff) | |
parent | 0d0f6554a5c233bf2bf830ae319191c4b1808d49 (diff) |
Merge commit '0d0f6554a5c233bf2bf830ae319191c4b1808d49' into haugesund
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 25 | ||||
-rw-r--r-- | filter/data.c | 20 | ||||
-rw-r--r-- | filter/data.h | 84 | ||||
-rw-r--r-- | filter/decl.m4 | 4 | ||||
-rw-r--r-- | filter/f-inst.c | 128 | ||||
-rw-r--r-- | filter/f-inst.h | 12 | ||||
-rw-r--r-- | filter/f-util.c | 27 | ||||
-rw-r--r-- | filter/filter.h | 2 | ||||
-rw-r--r-- | filter/test.conf | 6 |
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 212ed346..852afc51 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); 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); 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 9964831c..4a8f9703 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]); |