From 126683feeda03ffb5a4ce23611e59a4598382d49 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 29 Mar 2010 19:29:03 +0200 Subject: Filter language updates; new route attributes and datatype. - Adds bgp_originator_id and bgp_cluster_list route attributes. - Adds dotted quad filter datatype (for router IDs, used by bgp_originator_id and ospf_router_id route attributes). - Fixes pair ~ pair set matching. - Documentation updates. --- filter/config.Y | 9 +++++-- filter/filter.c | 74 ++++++++++++++++++++++++++++++++++++++++++++------------ filter/filter.h | 1 + filter/test.conf | 15 +++++++++++- 4 files changed, 80 insertions(+), 19 deletions(-) (limited to 'filter') diff --git a/filter/config.Y b/filter/config.Y index 1af5649..7723658 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -29,7 +29,7 @@ CF_DECLS CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, ACCEPT, REJECT, ERROR, QUITBIRD, - INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST, + INT, BOOL, IP, PREFIX, PAIR, QUAD, SET, STRING, BGPMASK, BGPPATH, CLIST, IF, THEN, ELSE, CASE, TRUE, FALSE, FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE, @@ -75,6 +75,7 @@ type: | IP { $$ = T_IP; } | PREFIX { $$ = T_PREFIX; } | PAIR { $$ = T_PAIR; } + | QUAD { $$ = T_QUAD; } | STRING { $$ = T_STRING; } | BGPMASK { $$ = T_PATH_MASK; } | BGPPATH { $$ = T_PATH; } @@ -82,8 +83,9 @@ type: | type SET { switch ($1) { case T_INT: - case T_IP: case T_PAIR: + case T_QUAD: + case T_IP: $$ = T_SET; break; @@ -234,6 +236,7 @@ fipa: set_atom: NUM { $$.type = T_INT; $$.val.i = $1; } + | RTRID { $$.type = T_QUAD; $$.val.i = $1; } | cpair { $$.type = T_PAIR; $$.val.i = $1; } | fipa { $$ = $1; } | ENUM { $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; } @@ -340,6 +343,7 @@ constant: | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } + | RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; } | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; } | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } @@ -396,6 +400,7 @@ symbol: case SYM_VARIABLE | T_BOOL: case SYM_VARIABLE | T_INT: case SYM_VARIABLE | T_PAIR: + case SYM_VARIABLE | T_QUAD: case SYM_VARIABLE | T_STRING: case SYM_VARIABLE | T_IP: case SYM_VARIABLE | T_PREFIX: diff --git a/filter/filter.c b/filter/filter.c index de7a97b..ae3b03a 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -65,6 +65,7 @@ pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2) if ((!m1) || (!m2)) return !((!m1) && (!m2)); + /* FIXME: buggy, should return -1, 0, 1; but it doesn't matter */ if ((m1->kind != m2->kind) || (m1->val != m2->val)) return 1; m1 = m1->next; m2 = m2->next; @@ -111,6 +112,13 @@ pm_format(struct f_path_mask *p, byte *buf, unsigned int size) *buf = 0; } +static inline int int_cmp(int i1, int i2) +{ + if (i1 == i2) return 0; + if (i1 < i2) return -1; + else return 1; +} + /** * val_compare - compare two values * @v1: first value @@ -133,6 +141,14 @@ val_compare(struct f_val v1, struct f_val v2) return 1; if (v1.type != v2.type) { +#ifndef IPV6 + /* IP->Quad implicit conversion */ + if ((v1.type == T_QUAD) && (v2.type == T_IP)) + return int_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip)); + if ((v1.type == T_IP) && (v2.type == T_QUAD)) + return int_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i); +#endif + debug( "Types do not match in val_compare\n" ); return CMP_ERROR; } @@ -141,9 +157,8 @@ val_compare(struct f_val v1, struct f_val v2) case T_INT: case T_BOOL: case T_PAIR: - if (v1.val.i == v2.val.i) return 0; - if (v1.val.i < v2.val.i) return -1; - return 1; + case T_QUAD: + return int_cmp(v1.val.i, v2.val.i); case T_IP: return ipa_compare(v1.val.px.ip, v2.val.px.ip); case T_PREFIX: @@ -196,8 +211,13 @@ val_simple_in_range(struct f_val v1, struct f_val v2) { if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK)) return as_path_match(v1.val.ad, v2.val.path_mask); - if ((v1.type == T_PAIR) && (v2.type == T_CLIST)) + if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST)) return int_set_contains(v2.val.ad, v1.val.i); +#ifndef IPV6 + /* IP->Quad implicit conversion */ + if ((v1.type == T_IP) && (v2.type == T_CLIST)) + return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip)); +#endif if ((v1.type == T_STRING) && (v2.type == T_STRING)) return patmatch(v2.val.s, v1.val.s); @@ -235,8 +255,9 @@ val_in_range(struct f_val v1, struct f_val v2) switch (v1.type) { case T_ENUM: case T_INT: + case T_PAIR: + case T_QUAD: case T_IP: - case T_PREFIX: { struct f_tree *n; n = find_tree(v2.val.t, v1); @@ -280,6 +301,7 @@ val_print(struct f_val v) case T_IP: PRINTF( "%I", v.val.px.ip ); break; case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break; case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break; + case T_QUAD: PRINTF( "%R", v.val.i ); break; case T_PREFIX_SET: trie_print(v.val.ti, buf, 2040); break; case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break; case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break; @@ -355,7 +377,7 @@ static struct f_val interpret(struct f_inst *what) { struct symbol *sym; - struct f_val v1, v2, res; + struct f_val v1, v2, res, *vp; unsigned u1, u2; int i; u32 as; @@ -435,11 +457,11 @@ interpret(struct f_inst *what) /* Relational operators */ #define COMPARE(x) \ - TWOARGS_C; \ - res.type = T_BOOL; \ + TWOARGS; \ i = val_compare(v1, v2); \ if (i==CMP_ERROR) \ - runtime( "Error in comparison" ); \ + runtime( "Can't compare values of incompatible types" ); \ + res.type = T_BOOL; \ res.val.i = (x); \ break; @@ -473,10 +495,19 @@ interpret(struct f_inst *what) case 's': ARG(v2, a2.p); sym = what->a1.p; - if ((sym->class != (SYM_VARIABLE | v2.type)) && - (v2.type != T_VOID)) + vp = sym->def; + if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) { +#ifndef IPV6 + /* IP->Quad implicit conversion */ + if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) { + vp->type = T_QUAD; + vp->val.i = ipa_to_u32(v2.val.px.ip); + break; + } +#endif runtime( "Assigning to variable of incompatible type" ); - * (struct f_val *) sym->def = v2; + } + *vp = v2; break; /* some constants have value in a2, some in *a1.p, strange. */ @@ -597,10 +628,13 @@ interpret(struct f_inst *what) switch (what->aux & EAF_TYPE_MASK) { case EAF_TYPE_INT: - case EAF_TYPE_ROUTER_ID: res.type = T_INT; res.val.i = e->u.data; break; + case EAF_TYPE_ROUTER_ID: + res.type = T_QUAD; + res.val.i = e->u.data; + break; case EAF_TYPE_OPAQUE: res.type = T_ENUM_EMPTY; res.val.i = 0; @@ -808,13 +842,21 @@ interpret(struct f_inst *what) v1.val.ad = adata_empty(f_pool); else if (v1.type != T_CLIST) runtime("Can't add/delete to non-clist"); - if (v2.type != T_PAIR) + + if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) + i = v2.val.i; +#ifndef IPV6 + /* IP->Quad implicit conversion */ + else if (v2.type == T_IP) + i = ipa_to_u32(v2.val.px.ip); +#endif + else runtime("Can't add/delete non-pair"); res.type = T_CLIST; switch (what->aux) { - case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, v2.val.i); break; - case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, v2.val.i); break; + case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, i); break; + case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, i); break; default: bug("unknown Ca operation"); } break; diff --git a/filter/filter.h b/filter/filter.h index 11e0623..46dc1a2 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -115,6 +115,7 @@ void val_print(struct f_val v); #define T_INT 0x10 #define T_BOOL 0x11 #define T_PAIR 0x12 /* Notice that pair is stored as integer: first << 16 | second */ +#define T_QUAD 0x13 /* Put enumerational types in 0x30..0x3f range */ #define T_ENUM_LO 0x30 diff --git a/filter/test.conf b/filter/test.conf index 8eeb5c3..0483c3d 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -138,10 +138,12 @@ bool b; prefix px; ip p; pair pp; +quad qq; int set is; int set is1; int set is2; int set is3; +pair set ps; prefix set pxs; string s; { @@ -190,7 +192,18 @@ string s; pp = (1, 2); print "Testing pairs: (1,2) = ", (1,2), " = ", pp, " = ", (1,1+1), " = ", 'mkpair-a'(2); print " must be true: ", (1,2) = (1,1+1); - print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC; + print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC, " ", + ", true: ", RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE], + ", false: ", RTS_BGP ~ [RTS_STATIC, RTS_DEVICE]; + + ps = [(1,2), (3,4)..(3,8)]; + print "Testing pair set (TTF):", pp ~ ps, " ", (3,5) ~ ps, " ", (3,9) ~ ps; + + qq = 1.2.3.4; + print "Testinq quad: 1.2.3.4 = ", qq, + ", true: ", qq = 1.2.3.4, " ", qq ~ [1.2.3.4, 5.6.7.8], + ", false: ", qq = 4.3.2.1, " ", qq ~ [1.2.1.1, 1.2.3.5]; + s = "Hello"; print "Testing string: ", s, " true: ", s ~ "Hell*", " false: ", s ~ "ell*"; -- cgit v1.2.3