]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter refactoring: Passing the resulting struct f_val as a pointer.
authorJan Maria Matejka <mq@ucw.cz>
Mon, 17 Dec 2018 12:51:11 +0000 (13:51 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 20 Feb 2019 21:30:54 +0000 (22:30 +0100)
This also drops the multiplexing of errors with the f_val itself
together with the T_RETURN f_val type flag.

conf/confbase.Y
filter/config.Y
filter/f-inst.c
filter/filter.c
filter/filter.h
filter/filter_test.c
nest/cmds.c

index 3fd034dba28e52a5f5b3640a38f3e191dc3ca9e1..3d573e1063392098a0de8321c6502c7d4c878b46 100644 (file)
@@ -124,8 +124,7 @@ conf: definition ;
 definition:
    DEFINE SYM '=' term ';' {
      struct f_val *val = cfg_alloc(sizeof(struct f_val));
-     *val = f_eval($4, cfg_mem);
-     if (val->type == T_RETURN) cf_error("Runtime error");
+     if (f_eval($4, cfg_mem, val) > F_RETURN) cf_error("Runtime error");
      cf_define_symbol($2, SYM_CONSTANT | val->type, val);
    }
  ;
index c1e7453102a6aa9a46d8ea5e5cd5abb25d395b16..200c1f4163d867d174439f9be00ad51f58ee9b96 100644 (file)
@@ -653,7 +653,7 @@ set_atom:
  | VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
  | ENUM   { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  | '(' term ')' {
-     $$ = f_eval($2, cfg_mem);
+     if (f_eval($2, cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
      if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
    }
  | SYM {
index 24908442ed3021db3f177524c734b20922f4fc30..814e026d47c0657df3083861ef555c774ed0d9ca 100644 (file)
       while (tt) {
        *vv = lp_alloc(fs->pool, sizeof(struct f_path_mask));
        if (tt->kind == PM_ASN_EXPR) {
-         struct f_val res;
-         INTERPRET(res, (struct f_inst *) tt->val);
+         struct f_val xres;
+         INTERPRET(xres, (struct f_inst *) tt->val);
          (*vv)->kind = PM_ASN;
-         if (res.type != T_INT) {
+         if (xres.type != T_INT) {
            runtime( "Error resolving path mask template: value not an integer" );
-           return (struct f_val) { .type = T_VOID };
+           return F_ERROR;
          }
 
-         (*vv)->val = res.val.i;
+         (*vv)->val = xres.val.i;
        } else {
          **vv = *tt;
        }
       /* Should take care about turning ACCEPT into MODIFY */
     case F_ERROR:
     case F_REJECT:     /* FIXME (noncritical) Should print complete route along with reason to reject route */
-      res.type = T_RETURN;
-      res.val.i = what->a2.i;
-      return res;      /* We have to return now, no more processing. */
+      return what->a2.i;       /* We have to return now, no more processing. */
     case F_NONL:
     case F_NOP:
       break;
   case FI_RETURN:
     ARG_ANY(1);
     res = v1;
-    res.type |= T_RETURN;
-    return res;
-  case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
+    return F_RETURN;
+  case FI_CALL:
     ARG_ANY(1);
-    res = interpret(fs, what->a2.p);
-    if (res.type == T_RETURN)
-      return res;
-    res.type &= ~T_RETURN;
+    fret = interpret(fs, what->a2.p, &res);
+    if (fret > F_RETURN)
+      return fret;
     break;
   case FI_CLEAR_LOCAL_VARS:    /* Clear local variables */
     for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
index 794e35e80e92061d9802b81ff1830b2cc88443a5..1e6fc003478e6df868e3a7f906bb00b8deb1ab2f 100644 (file)
@@ -615,24 +615,27 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
  * &f_val structures are copied around, so there are no problems with
  * memory managment.
  */
-static struct f_val
-interpret(struct filter_state *fs, struct f_inst *what)
+static enum filter_return
+interpret(struct filter_state *fs, struct f_inst *what, struct f_val *resp)
 {
   struct symbol *sym;
-  struct f_val v1, v2, v3, res = { .type = T_VOID }, *vp;
+  struct f_val v1, v2, v3, *vp;
   unsigned u1, u2;
+  enum filter_return fret;
   int i;
   u32 as;
 
+  *resp = (struct f_val) { .type = T_VOID };
+
   for ( ; what; what = what->next) {
-  res.type = T_VOID;
+#define res (*resp)
+  res = (struct f_val) { .type = T_VOID };
   switch(what->fi_code) {
+
 #define runtime(fmt, ...) do { \
     if (!(fs->flags & FF_SILENT)) \
       log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
-    res.type = T_RETURN; \
-    res.val.i = F_ERROR; \
-    return res; \
+    return F_ERROR; \
   } while(0)
 
 #define ARG_ANY(n) INTERPRET(v##n, what->a##n.p)
@@ -643,9 +646,9 @@ interpret(struct filter_state *fs, struct f_inst *what)
          n, f_instruction_name(what->fi_code), t, v##n.type);
 
 #define INTERPRET(val, what_) \
-    val = interpret(fs, what_); \
-    if (val.type & T_RETURN) \
-      return val;
+    fret = interpret(fs, what_, &(val)); \
+    if (fret >= F_RETURN) \
+      return fret;
 
 #define ACCESS_RTE \
   do { if (!fs->rte) runtime("No route to access"); } while (0)
@@ -657,6 +660,7 @@ interpret(struct filter_state *fs, struct f_inst *what)
 
 #include "filter/f-inst.c"
 
+#undef res
 #undef runtime
 #undef ARG_ANY
 #undef ARG
@@ -664,7 +668,7 @@ interpret(struct filter_state *fs, struct f_inst *what)
 #undef ACCESS_RTE
 #undef ACCESS_EATTRS
   }}
-  return res;
+  return F_NOP;
 }
 
 
@@ -837,7 +841,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
  * (and cached rta of read-only source rte is intact), if rte is
  * modified in place, old cached rta is possibly freed.
  */
-int
+enum filter_return
 f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags)
 {
   if (filter == FILTER_ACCEPT)
@@ -857,7 +861,8 @@ f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int fla
 
   LOG_BUFFER_INIT(fs.buf);
 
-  struct f_val res = interpret(&fs, filter->root);
+  struct f_val res;
+  enum filter_return fret = interpret(&fs, filter->root, &res);
 
   if (fs.old_rta) {
     /*
@@ -879,18 +884,18 @@ f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int fla
   }
 
 
-  if (res.type != T_RETURN) {
+  if (fret < F_ACCEPT) {
     if (!(fs.flags & FF_SILENT))
       log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
     return F_ERROR;
   }
   DBG( "done (%u)\n", res.val.i );
-  return res.val.i;
+  return fret;
 }
 
 /* TODO: perhaps we could integrate f_eval(), f_eval_rte() and f_run() */
 
-struct f_val
+enum filter_return
 f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
 {
 
@@ -902,13 +907,12 @@ f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
   LOG_BUFFER_INIT(fs.buf);
 
   /* Note that in this function we assume that rte->attrs is private / uncached */
-  struct f_val res = interpret(&fs, expr);
-
-  return res;
+  struct f_val res;
+  return interpret(&fs, expr, &res);
 }
 
-struct f_val
-f_eval(struct f_inst *expr, struct linpool *tmp_pool)
+enum filter_return
+f_eval(struct f_inst *expr, struct linpool *tmp_pool, struct f_val *pres)
 {
   struct filter_state fs = {
     .pool = tmp_pool,
@@ -916,14 +920,16 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
 
   LOG_BUFFER_INIT(fs.buf);
 
-  return interpret(&fs, expr);
+  return interpret(&fs, expr, pres);
 }
 
 uint
 f_eval_int(struct f_inst *expr)
 {
   /* Called independently in parse-time to eval expressions */
-  struct f_val res = f_eval(expr, cfg_mem);
+  struct f_val res;
+  if (f_eval(expr, cfg_mem, &res) > F_RETURN)
+    cf_error("Runtime error while evaluating expression");
 
   if (res.type != T_INT)
     cf_error("Integer expression expected");
index a8c33287875ac6557c7eb4ae05f1c89861dfcfde..8728f6797f04ed54b471b9013533df7fa19dd334 100644 (file)
@@ -175,9 +175,19 @@ void trie_format(struct f_trie *t, buffer *buf);
 struct ea_list;
 struct rte;
 
-int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
-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);
+enum filter_return {
+  F_NOP = 0,
+  F_NONL,
+  F_RETURN,
+  F_ACCEPT,   /* Need to preserve ordering: accepts < rejects! */
+  F_REJECT,
+  F_ERROR,
+  F_QUITBIRD,
+};
+
+enum filter_return f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
+enum filter_return f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
+enum filter_return f_eval(struct f_inst *expr, struct linpool *tmp_pool, struct f_val *pres);
 uint f_eval_int(struct f_inst *expr);
 
 char *filter_name(struct filter *filter);
@@ -190,14 +200,6 @@ int val_same(struct f_val v1, struct f_val v2);
 
 void val_format(struct f_val v, buffer *buf);
 
-
-#define F_NOP 0
-#define F_NONL 1
-#define F_ACCEPT 2     /* Need to preserve ordering: accepts < rejects! */
-#define F_REJECT 3
-#define F_ERROR 4
-#define F_QUITBIRD 5
-
 #define FILTER_ACCEPT NULL
 #define FILTER_REJECT ((void *) 1)
 #define FILTER_UNDEF  ((void *) 2)     /* Used in BGP */
@@ -246,7 +248,6 @@ void val_format(struct f_val v, buffer *buf);
 #define T_LCLIST 0x29          /* Large community list */
 #define T_RD 0x2a              /* Route distinguisher for VPN addresses */
 
-#define T_RETURN 0x40
 #define T_SET 0x80
 #define T_PREFIX_SET 0x81
 
index be7fd5211cc536735e3d6b854443094536d19c20..b319225b2d971f5f2472bb5851b1ff7135d35159 100644 (file)
@@ -44,13 +44,11 @@ run_function(const void *parsed_fn_def)
   struct f_inst *f = (struct f_inst *) parsed_fn_def;
 
   linpool *tmp = lp_new_default(&root_pool);
-  struct f_val res = f_eval(f, tmp);
+  struct f_val res;
+  enum filter_return fret = f_eval(f, tmp, &res);
   rfree(tmp);
 
-  if (res.type == T_RETURN && res.val.i >= F_REJECT)
-    return 0;
-
-  return 1;
+  return (fret < F_REJECT);
 }
 
 static void
index ca601ef26744d3eac4edd5f38b9a22928b875cb9..0c89d20fe4d7cfa586a1b9de8508a83056dd975e 100644 (file)
@@ -97,9 +97,8 @@ cmd_show_memory(void)
 void
 cmd_eval(struct f_inst *expr)
 {
-  struct f_val v = f_eval(expr, this_cli->parser_pool);
-
-  if (v.type == T_RETURN)
+  struct f_val v;
+  if (f_eval(expr, this_cli->parser_pool, &v) > F_RETURN)
     {
       cli_msg(8008, "runtime error");
       return;