diff options
-rw-r--r-- | doc/bird.sgml | 11 | ||||
-rw-r--r-- | filter/config.Y | 2 | ||||
-rw-r--r-- | filter/filter.c | 38 | ||||
-rw-r--r-- | filter/test.conf | 2 |
4 files changed, 39 insertions, 14 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index fbda9f49..8a8c2275 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -849,10 +849,15 @@ incompatible with each other (that is to prevent you from shooting in the foot). operator deletes all items from clist <m/C/ that are also members of set <m/P/. - Statement <cf><m/C/ = add(<m/C/, <m/P/);</cf> can be shortened to - <cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route attribute - (for example <cf/bgp_community/). Similarly for <cf/delete/. + <cf>filter(<m/C/,<m/P/)</cf> deletes all items from clist + <m/C/ that are not members of pair (or quad) set <m/P/. + I.e., <cf/filter/ do the same as <cf/delete/ with inverted + set <m/P/. + Statement <cf><m/C/ = add(<m/C/, <m/P/);</cf> can be shortened to + <cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route + attribute (for example <cf/bgp_community/). Similarly for + <cf/delete/ and <cf/filter/. </descrip> <sect>Operators diff --git a/filter/config.Y b/filter/config.Y index e635f609..80e74286 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -566,6 +566,7 @@ term: | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } + | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } /* | term '.' LEN { $$->code = P('P','l'); } */ @@ -706,6 +707,7 @@ cmd: | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); } | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } + | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); } ; CF_END diff --git a/filter/filter.c b/filter/filter.c index b8044293..913bd086 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -279,7 +279,7 @@ clist_match_set(struct adata *clist, struct f_tree *set) } static struct adata * -clist_del_matching(struct linpool *pool, struct adata *clist, struct f_tree *set) +clist_filter(struct linpool *pool, struct adata *clist, struct f_tree *set, int pos) { if (!clist) return NULL; @@ -294,7 +294,7 @@ clist_del_matching(struct linpool *pool, struct adata *clist, struct f_tree *set while (l < end) { v.val.i = *l++; - if (!find_tree(set, v)) + if (pos == !!find_tree(set, v)) /* pos && find_tree || !pos && !find_tree */ *k++ = v.val.i; } @@ -945,7 +945,7 @@ interpret(struct f_inst *what) runtime("Can't add/delete to non-clist"); struct f_val dummy; - u16 op = what->aux; + int arg_set = 0; i = 0; if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) @@ -955,17 +955,35 @@ interpret(struct f_inst *what) else if (v2.type == T_IP) i = ipa_to_u32(v2.val.px.ip); #endif - else if ((v2.type == T_SET) && (op == 'd') && clist_set_type(v2.val.t, &dummy)) - op = 'D'; + else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy)) + arg_set = 1; else runtime("Can't add/delete non-pair"); res.type = T_CLIST; - switch (op) { - 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; - case 'D': res.val.ad = clist_del_matching(f_pool, v1.val.ad, v2.val.t); break; - default: bug("unknown Ca operation"); + switch (what->aux) + { + case 'a': + if (arg_set) + runtime("Can't add set"); + res.val.ad = int_set_add(f_pool, v1.val.ad, i); + break; + + case 'd': + if (!arg_set) + res.val.ad = int_set_del(f_pool, v1.val.ad, i); + else + res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 0); + break; + + case 'f': + if (!arg_set) + runtime("Can't filter pair"); + res.val.ad = clist_filter(f_pool, v1.val.ad, v2.val.t, 1); + break; + + default: + bug("unknown Ca operation"); } break; diff --git a/filter/test.conf b/filter/test.conf index dbb3a4ea..ca8e26f5 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -97,7 +97,7 @@ clist l; l = add( l, (one,one) ); l = delete( l, [(5,1),(6,one),(one,1)] ); l = delete( l, [(5,one),(6,one)] ); - l = delete( l, [(2,*)] ); + l = filter( l, [(1,*)] ); print "Community list (1,2) ", l; print "Should be false: ", (2,3) ~ l, " ", l ~ [(2,*)], " ", l ~ [(one,3..6)]; print "Should be always true: ", l ~ [(*,*)]; |