summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y22
-rw-r--r--filter/filter.c39
-rw-r--r--filter/filter.h2
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);