diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 22 | ||||
-rw-r--r-- | filter/filter.c | 39 | ||||
-rw-r--r-- | filter/filter.h | 2 |
3 files changed, 51 insertions, 12 deletions
diff --git a/filter/config.Y b/filter/config.Y index 1ef5a3a8..7c077b65 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -317,6 +317,26 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3) return rv; } +static inline struct f_inst * +f_generate_path_mask(struct f_path_mask *t) +{ + for (struct f_path_mask *tt = t; tt; tt = tt->next) { + if (tt->kind == PM_ASN_EXPR) { + struct f_inst *mrv = f_new_inst(FI_PATHMASK_CONSTRUCT); + mrv->a1.p = t; + return mrv; + } + } + + NEW_F_VAL; + val->type = T_PATH_MASK; + val->val.path_mask = t; + + struct f_inst *rv = f_new_inst(FI_CONSTANT_INDIRECT); + rv->a1.p = val; + + return rv; +} CF_DECLS @@ -708,13 +728,13 @@ constant: | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(FI_CONSTANT); $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_PREFIX_SET; $$->a2.p = $2; } | ENUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } - | bgp_path { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } ; constructor: '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); } + | bgp_path { $$ = f_generate_path_mask($1); } ; diff --git a/filter/filter.c b/filter/filter.c index 023f7e2f..8b66b57e 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -82,8 +82,7 @@ pm_format(struct f_path_mask *p, buffer *buf) break; case PM_ASN_EXPR: - buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val)); - break; + ASSERT(0); } p = p->next; @@ -772,6 +771,32 @@ interpret(struct f_inst *what) break; } + case FI_PATHMASK_CONSTRUCT: + { + struct f_path_mask *tt = what->a1.p, *vbegin, **vv = &vbegin; + + while (tt) { + *vv = lp_alloc(f_pool, sizeof(struct f_path_mask)); + if (tt->kind == PM_ASN_EXPR) { + struct f_val res = interpret((struct f_inst *) tt->val); + (*vv)->kind = PM_ASN; + if (res.type != T_INT) { + runtime( "Error resolving path mask template: value not an integer" ); + return (struct f_val) { .type = T_VOID }; + } + + (*vv)->val = res.val.i; + } else { + **vv = *tt; + } + tt = tt->next; + vv = &((*vv)->next); + } + + res = (struct f_val) { .type = T_PATH_MASK, .val.path_mask = vbegin }; + break; + } + /* Relational operators */ #define COMPARE(x) \ @@ -1550,6 +1575,8 @@ i_same(struct f_inst *f1, struct f_inst *f2) case FI_LT: case FI_LTE: TWOARGS; break; + case FI_PATHMASK_CONSTRUCT: if (!pm_same(f1->a1.p, f2->a1.p)) return 0; break; + case FI_NOT: ONEARG; break; case FI_NOT_MATCH: case FI_MATCH: TWOARGS; break; @@ -1771,14 +1798,6 @@ f_eval_int(struct f_inst *expr) return res.val.i; } -u32 -f_eval_asn(struct f_inst *expr) -{ - /* Called as a part of another interpret call, therefore no log_reset() */ - struct f_val res = interpret(expr); - return (res.type == T_INT) ? res.val.i : 0; -} - /** * filter_same - compare two filters * @new: first filter to be compared diff --git a/filter/filter.h b/filter/filter.h index 1d0f389e..572459d8 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -27,6 +27,7 @@ F(FI_PAIR_CONSTRUCT, 'm', 'p') \ F(FI_EC_CONSTRUCT, 'm', 'c') \ F(FI_LC_CONSTRUCT, 'm', 'l') \ + F(FI_PATHMASK_CONSTRUCT, 'm', 'P') \ F(FI_NEQ, '!', '=') \ F(FI_EQ, '=', '=') \ F(FI_LT, 0, '<') \ @@ -196,7 +197,6 @@ int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, s struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool); struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool); uint f_eval_int(struct f_inst *expr); -u32 f_eval_asn(struct f_inst *expr); char *filter_name(struct filter *filter); int filter_same(struct filter *new, struct filter *old); |