]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: adding explicit route-block type
authorMaria Matejka <mq@ucw.cz>
Mon, 30 Oct 2023 08:49:20 +0000 (09:49 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 30 Oct 2023 12:10:36 +0000 (13:10 +0100)
This is a split-commit of the neighboring aggregator branch
with a bit improved lvalue handling, to have easier merge into v3.

filter/data.c
filter/data.h
filter/f-inst.c

index cb52b499c38aa8207f32a59e30238f0d6b5785dc..de745654a729a64efd7a1f30ec2c563da3f6ab78 100644 (file)
@@ -58,6 +58,7 @@ static const char * const f_type_str[] = {
   [T_RD]       = "rd",
 
   [T_ROUTE]    = "route",
+  [T_ROUTES_BLOCK] = "block of routes",
 };
 
 const char *
@@ -80,6 +81,7 @@ f_type_element_type(enum f_type t)
     case T_CLIST:  return T_PAIR;
     case T_ECLIST: return T_EC;
     case T_LCLIST: return T_LC;
+    case T_ROUTES_BLOCK: return T_ROUTE;
     default: return T_VOID;
   };
 }
@@ -209,6 +211,7 @@ val_compare(const struct f_val *v1, const struct f_val *v2)
   case T_STRING:
     return strcmp(v1->val.s, v2->val.s);
   case T_ROUTE:
+  case T_ROUTES_BLOCK:
   default:
     return F_CMP_ERROR;
   }
@@ -301,6 +304,15 @@ val_same(const struct f_val *v1, const struct f_val *v2)
     return trie_same(v1->val.ti, v2->val.ti);
   case T_ROUTE:
     return rte_same(v1->val.rte, v2->val.rte);
+  case T_ROUTES_BLOCK:
+    for (
+       rte *r1 = v1->val.rte, *r2 = v2->val.rte;
+       r1 || r2;
+       r1 = r1->next, r2 = r2->next
+       )
+      if (!r1 || !r2 || !rte_same(r1, r2))
+       return 0;
+    return 1;
   default:
     bug("Invalid type in val_same(): %x", v1->type);
   }
@@ -589,6 +601,19 @@ rte_format(const struct rte *rte, buffer *buf)
     buffer_puts(buf, "[No route]");
 }
 
+static void
+rte_block_format(const struct rte *rte, buffer *buf)
+{
+  buffer_print(buf, "Block of routes:");
+
+  for (int i = 0; rte; rte = rte->next, i++)
+  {
+    buffer_print(buf, "%s%d: ", i ? "; " : " ", i);
+    rte_format(rte, buf);
+  }
+}
+
+
 /*
  * val_format - format filter value
  */
@@ -619,6 +644,7 @@ val_format(const struct f_val *v, buffer *buf)
   case T_LCLIST: lc_set_format(v->val.ad, -1, buf2, 1000); buffer_print(buf, "(lclist %s)", buf2); return;
   case T_PATH_MASK: pm_format(v->val.path_mask, buf); return;
   case T_ROUTE: rte_format(v->val.rte, buf); return;
+  case T_ROUTES_BLOCK: rte_block_format(v->val.rte, buf); return;
   default:     buffer_print(buf, "[unknown type %x]", v->type); return;
   }
 }
index 620a80bf7dbfa91d89fa051db5a3c3daebf08e37..103591b741e12ff6d86fd0cd75355635652dd5a4 100644 (file)
@@ -63,6 +63,7 @@ enum f_type {
   T_BYTESTRING = 0x2c,
 
   T_ROUTE = 0x78,
+  T_ROUTES_BLOCK = 0x79,
   T_SET = 0x80,
   T_PREFIX_SET = 0x81,
 } PACKED;
index 76ec272de2a5e88c1bd05b8d2e2abf2c86827caf..42e38a4bf273d5e2d6145033ad9b404ad5a9e67a 100644 (file)
     METHOD_CONSTRUCTOR("!for_next");
   }
 
+  INST(FI_ROUTES_BLOCK_FOR_NEXT, 3, 0) {
+    NEVER_CONSTANT;
+    ARG(1, T_ROUTES_BLOCK);
+
+    /* Loop auxiliary variable is initialized to T_VOID.
+     * In the first run, we initialize the auxiliary variable
+     * to the routes block supplied. It changes its type
+     * to T_ROUTES_BLOCK and therefore won't be run again. */
+    if (v2.type == T_VOID)
+      v2 = v1;
+
+    if (v2.val.rte)
+    {
+      /* There is some route to process, set it into the iterator variable.
+       * Its type has been already initialized by f_for_cycle(). */
+      v3.val.rte = v2.val.rte;
+      v3.val.eattrs = v3.val.rte->attrs->eattrs;
+
+      /* Prepare next route in the loop auxiliary variable */
+      v2.val.rte = v2.val.rte->next;
+
+      /* And execute the line */
+      LINE(2,0);
+    }
+
+    METHOD_CONSTRUCTOR("!for_next");
+  }
+
   INST(FI_CONDITION, 1, 0) {
     ARG(1, T_BOOL);
     if (v1.val.i)