diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 18 | ||||
-rw-r--r-- | filter/data.h | 4 | ||||
-rw-r--r-- | filter/f-inst.c | 30 | ||||
-rw-r--r-- | filter/f-inst.h | 4 | ||||
-rw-r--r-- | filter/test.conf | 12 |
5 files changed, 45 insertions, 23 deletions
diff --git a/filter/config.Y b/filter/config.Y index 46ba7769..fb331c16 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -165,7 +165,7 @@ f_generate_empty(struct f_dynamic_attr dyn) { struct f_val empty; - switch (dyn.type & EAF_TYPE_MASK) { + switch (dyn.type) { case EAF_TYPE_AS_PATH: empty = f_const_empty_path; break; @@ -308,7 +308,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type <xp> cmds_int cmd_prep %type <x> term block cmd cmds constant constructor print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail -%type <fda> dynamic_attr +%type <fda> dynamic_attr attr_bit %type <fsa> static_attr %type <f> filter where_filter %type <fl> filter_body function_body @@ -780,6 +780,8 @@ term: | term '-' term { $$ = f_new_inst(FI_SUBTRACT, $1, $3); } | term '*' term { $$ = f_new_inst(FI_MULTIPLY, $1, $3); } | term '/' term { $$ = f_new_inst(FI_DIVIDE, $1, $3); } + | term '&' term { $$ = f_new_inst(FI_BITAND, $1, $3); } + | term '|' term { $$ = f_new_inst(FI_BITOR, $1, $3); } | term AND term { $$ = f_new_inst(FI_AND, $1, $3); } | term OR term { $$ = f_new_inst(FI_OR, $1, $3); } | term '=' term { $$ = f_new_inst(FI_EQ, $1, $3); } @@ -800,6 +802,10 @@ term: | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); } | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); } + | attr_bit { + struct f_inst *c = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)}); + $$ = f_new_inst(FI_EQ, c, f_new_inst(FI_BITAND, f_new_inst(FI_EA_GET, $1), c)); + } | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); } | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); } @@ -897,6 +903,14 @@ cmd: | UNSET '(' dynamic_attr ')' ';' { $$ = f_new_inst(FI_EA_UNSET, $3); } + | attr_bit '=' term ';' { + $$ = f_new_inst(FI_CONDITION, $3, + f_generate_complex(FI_BITOR, $1, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = (1U << $1.bit)})), + f_generate_complex(FI_BITAND, $1, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = ~(1U << $1.bit)})) + ); + } | break_command print_list ';' { struct f_inst *breaker = f_new_inst(FI_DIE, $1); if ($2) { diff --git a/filter/data.h b/filter/data.h index 6d588204..924bbf3e 100644 --- a/filter/data.h +++ b/filter/data.h @@ -20,6 +20,9 @@ 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, @@ -41,7 +44,6 @@ enum f_type { T_ENUM_AF = 0x38, /* new enums go here */ - T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */ #define T_ENUM T_ENUM_LO ... T_ENUM_HI diff --git a/filter/f-inst.c b/filter/f-inst.c index fc240173..212ed346 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -240,6 +240,16 @@ if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" ); RESULT(T_INT, i, v1.val.i / v2.val.i); } + INST(FI_BITOR, 2, 1) { + ARG(1,T_INT); + ARG(2,T_INT); + RESULT(T_INT, i, v1.val.i | v2.val.i); + } + INST(FI_BITAND, 2, 1) { + ARG(1,T_INT); + ARG(2,T_INT); + RESULT(T_INT, i, v1.val.i & v2.val.i); + } INST(FI_AND, 1, 1) { ARG(1,T_BOOL); ARG_TYPE_STATIC(2,T_BOOL); @@ -686,7 +696,7 @@ break; } - switch (e->type & EAF_TYPE_MASK) { + switch (e->type) { case EAF_TYPE_INT: RESULT_(da.f_type, i, e->u.data); break; @@ -694,7 +704,7 @@ RESULT_(T_QUAD, i, e->u.data); break; case EAF_TYPE_OPAQUE: - RESULT_(T_ENUM_EMPTY, i, 0); + RESULT_(T_OPAQUE, ad, e->u.ptr); break; case EAF_TYPE_IP_ADDRESS: RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data)); @@ -702,9 +712,6 @@ case EAF_TYPE_AS_PATH: RESULT_(T_PATH, ad, e->u.ptr); break; - case EAF_TYPE_BITFIELD: - RESULT_(T_BOOL, i, !!(e->u.data & (1u << da.bit))); - break; case EAF_TYPE_INT_SET: RESULT_(T_CLIST, ad, e->u.ptr); break; @@ -764,19 +771,6 @@ l->attrs[0].u.ptr = v1.val.ad; break; - case EAF_TYPE_BITFIELD: - { - /* First, we have to find the old value */ - eattr *e = ea_find(*fs->eattrs, da.ea_code); - u32 data = e ? e->u.data : 0; - - if (v1.val.i) - l->attrs[0].u.data = data | (1u << da.bit); - else - l->attrs[0].u.data = data & ~(1u << da.bit); - } - break; - default: bug("Unknown dynamic attribute type"); } diff --git a/filter/f-inst.h b/filter/f-inst.h index df45f88e..9265ecec 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -89,8 +89,8 @@ 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, 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 = EAF_TYPE_BITFIELD, .bit = bit, .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 }; } struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument); diff --git a/filter/test.conf b/filter/test.conf index 2a5a2d98..ee2f5be4 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -111,6 +111,14 @@ int i; bt_assert(!(i = 4)); bt_assert(1 <= 1); bt_assert(!(1234 < 1234)); + + bt_assert(10 - 5 = 5); + bt_assert(4294967295 + 1 = 0); + bt_assert(6*9=54); + bt_assert(984/41 = 24); + bt_assert(123/45 = 2); + bt_assert(0xfee1a | 0xbeef = 0xffeff); + bt_assert(0xfee1a & 0xbeef = 0xae0a); } bt_test_suite(t_int, "Testing integers"); @@ -1334,6 +1342,10 @@ int j; rip_metric = 14; unset(rip_metric); +# krt_lock_mtu = false; +# krt_lock_window = true; +# krt_lock_rtt = krt_lock_rttvar && krt_lock_sstresh || krt_lock_cwnd; + accept "ok I take that"; } |