]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Adds filter clist operation.
authorOndrej Zajicek <santiago@crfreenet.org>
Sun, 26 Jun 2011 15:09:24 +0000 (17:09 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sun, 26 Jun 2011 15:09:24 +0000 (17:09 +0200)
doc/bird.sgml
filter/config.Y
filter/filter.c
filter/test.conf

index fbda9f49cab314922b64af33b5feaeb0b484c4eb..8a8c2275d3beec5a6ce9f8a40e033d45aa307cbc 100644 (file)
@@ -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
index e635f6094e396b6685759b45d9dfc29de44a93eb..80e74286923888ee374211e630b5f78a3fd0a6be 100644 (file)
@@ -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
index b80442936f1f4fbf798dd043da381e3f4e8df259..913bd086113fa37e1a38d2920d0870832ae3b614 100644 (file)
@@ -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;
 
index dbb3a4ea5752bfe0172dab1a81e80994c822b91d..ca8e26f5ed7707da6a58ccddd88ca9408a606e0b 100644 (file)
@@ -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 ~ [(*,*)];