]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '407eb388b7082b52921e93476c8ff1a98fe3b873' into thread-next
authorMaria Matejka <mq@ucw.cz>
Tue, 31 Oct 2023 09:28:01 +0000 (10:28 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 31 Oct 2023 09:28:01 +0000 (10:28 +0100)
1  2 
filter/config.Y
filter/filter.c
filter/filter.h
proto/static/static.c

diff --cc filter/config.Y
Simple merge
diff --cc filter/filter.c
index 9d3d0c2802507dc671eae95dccaf437514440a88,4c0f6f12f990127f056782c444ab088f1e2557a5..2a6261884c55f8daac4b7a09bed9c08fb25afbfd
@@@ -61,23 -73,25 +61,26 @@@ struct filter_exec_stack 
  /* Internal filter state, to be allocated on stack when executing filters */
  struct filter_state {
    /* Stacks needed for execution */
 -  struct filter_stack *stack;
 -
 -  /* The route we are processing. This may be NULL to indicate no route available. */
 -  struct rte **rte;
 +  struct filter_stack {
 +    /* Current filter stack depth */
  
 -  /* The old rta to be freed after filters are done. */
 -  struct rta *old_rta;
 +    /* Value stack */
 +    uint vcnt, vlen;
 +    struct f_val *vstk;
  
 -  /* Cached pointer to ea_list */
 -  struct ea_list **eattrs;
 +    /* Instruction stack for execution */
 +    uint ecnt, elen;
 +    struct filter_exec_stack *estk;
 +  } stack;
  
 -  /* Linpool for adata allocation */
 -  struct linpool *pool;
 +  /* The route we are processing. This may be NULL to indicate no route available. */
 +  struct rte *rte;
  
+   /* Additional external values provided to the filter */
+   const struct f_val *val;
    /* Buffer for log output */
 -  struct buffer buf;
 +  log_buffer buf;
  
    /* Filter execution flags */
    int flags;
@@@ -109,23 -160,23 +112,25 @@@ static struct tbf rl_runtime_err = TBF_
   * TWOARGS macro to get both of them evaluated.
   */
  static enum filter_return
- interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
+ interpret(struct filter_state *fs, const struct f_line *line, uint argc, const struct f_val *argv, struct f_val *val)
  {
-   /* No arguments allowed */
-   ASSERT(line->args == 0);
+   /* Check of appropriate number of arguments */
+   ASSERT(line->args == argc);
  
    /* Initialize the filter stack */
 -  struct filter_stack *fstk = fs->stack;
 +  struct filter_stack *fstk = &fs->stack;
  
-   fstk->vcnt = line->vars;
-   memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars);
+   /* Set the arguments and top-level variables */
+   fstk->vcnt = line->vars + line->args;
+   memcpy(fstk->vstk, argv, sizeof(struct f_val) * line->args);
+   memset(fstk->vstk + argc, 0, sizeof(struct f_val) * line->vars);
  
-   /* The same as with the value stack. Not resetting the stack for performance reasons. */
+   /* The same as with the value stack. Not resetting the stack completely for performance reasons. */
    fstk->ecnt = 1;
 -  fstk->estk[0].line = line;
 -  fstk->estk[0].pos = 0;
 +  fstk->estk[0] = (struct filter_exec_stack) {
 +    .line = line,
 +    .pos = 0,
 +  };
  
  #define curline fstk->estk[fstk->ecnt-1]
  #define prevline fstk->estk[fstk->ecnt-2]
@@@ -210,6 -276,13 +215,12 @@@ f_run(const struct filter *filter, stru
    if (filter == FILTER_REJECT)
      return F_REJECT;
  
 -  return f_run_args(filter, rte, tmp_pool, 0, NULL, flags);
++  return f_run_args(filter, rte, 0, NULL, flags);
+ }
+ enum filter_return
 -f_run_args(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, int flags)
++f_run_args(const struct filter *filter, struct rte *rte, uint argc, const struct f_val *argv, int flags)
+ {
 -  int rte_cow = ((*rte)->flags & REF_COW);
    DBG( "Running filter `%s'...", filter->name );
  
    /* Initialize the filter state */
      .flags = flags,
    };
  
 -  LOG_BUFFER_INIT(filter_state.buf);
 +  f_stack_init(filter_state);
  
    /* Run the interpreter itself */
-   enum filter_return fret = interpret(&filter_state, filter->root, NULL);
+   enum filter_return fret = interpret(&filter_state, filter->root, argc, argv, NULL);
  
 -  if (filter_state.old_rta) {
 -    /*
 -     * Cached rta was modified and filter_state->rte contains now an uncached one,
 -     * sharing some part with the cached one. The cached rta should
 -     * be freed (if rte was originally COW, filter_state->old_rta is a clone
 -     * obtained during rte_cow()).
 -     *
 -     * This also implements the exception mentioned in f_run()
 -     * description. The reason for this is that rta reuses parts of
 -     * filter_state->old_rta, and these may be freed during rta_free(filter_state->old_rta).
 -     * This is not the problem if rte was COW, because original rte
 -     * also holds the same rta.
 -     */
 -    if (!rte_cow) {
 -      /* Cache the new attrs */
 -      (*filter_state.rte)->attrs = rta_lookup((*filter_state.rte)->attrs);
 -
 -      /* Drop cached ea_list pointer */
 -      filter_state.eattrs = NULL;
 -    }
 -
 -    /* Uncache the old attrs and drop the pointer as it is invalid now. */
 -    rta_free(filter_state.old_rta);
 -    filter_state.old_rta = NULL;
 -  }
 -
    /* Process the filter output, log it and return */
    if (fret < F_ACCEPT) {
      if (!(filter_state.flags & FF_SILENT))
   */
  
  enum filter_return
- f_eval_rte(const struct f_line *expr, struct rte *rte)
 -f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, struct f_val *pres)
++f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, struct f_val *pres)
  {
    filter_state = (struct filter_state) {
 -    .stack = &filter_stack,
      .rte = rte,
 -    .pool = tmp_pool,
    };
  
 -  LOG_BUFFER_INIT(filter_state.buf);
 +  f_stack_init(filter_state);
  
-   ASSERT(!rta_is_cached(rte->attrs));
-   return interpret(&filter_state, expr, NULL);
+   return interpret(&filter_state, expr, argc, argv, pres);
  }
  
  /*
   * @pres: here the output will be stored
   */
  enum filter_return
 -f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
 +f_eval(const struct f_line *expr, struct f_val *pres)
  {
 -  filter_state = (struct filter_state) {
 -    .stack = &filter_stack,
 -    .pool = tmp_pool,
 -  };
 +  filter_state = (struct filter_state) {};
  
 -  LOG_BUFFER_INIT(filter_state.buf);
 +  f_stack_init(filter_state);
  
-   enum filter_return fret = interpret(&filter_state, expr, pres);
+   enum filter_return fret = interpret(&filter_state, expr, 0, NULL, pres);
    return fret;
  }
  
diff --cc filter/filter.h
index 92c89fbe1913d7cdc25a0ea2653a5105f33f3bd7,18ff0874f56f35ddb9175d31263959ad56199cfa..121da468652038bea99d8dbf4cebe9f49da246dc
@@@ -52,18 -51,13 +52,19 @@@ struct filter 
  
  struct rte;
  
 -enum filter_return f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
 -enum filter_return f_run_args(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, int flags);
 -enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, struct f_val *pres);
 -enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf);
 +enum filter_return f_run(const struct filter *filter, struct rte *rte, int flags);
- enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte);
++enum filter_return f_run_args(const struct filter *filter, struct rte *rte, uint argc, const struct f_val *argv, int flags);
++enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, uint argc, const struct f_val *argv, struct f_val *pres);
 +enum filter_return f_eval_buf(const struct f_line *expr, buffer *buf);
  
 -struct f_val cf_eval(const struct f_inst *inst, int type);
 -static inline uint cf_eval_int(const struct f_inst *inst) { return cf_eval(inst, T_INT).val.i; };
 +struct f_val cf_eval_tmp(const struct f_inst *inst, int type);
 +static inline struct f_val *cf_eval(const struct f_inst *inst, int type)
 +{
 +  struct f_val val = cf_eval_tmp(inst, type);
 +  return lp_val_copy(cfg_mem, &val);
 +}
 +
 +static inline uint cf_eval_int(const struct f_inst *inst) { return cf_eval_tmp(inst, T_INT).val.i; };
  
  const char *filter_name(const struct filter *filter);
  int filter_same(const struct filter *new, const struct filter *old);
index dbce77efbf03ab5c8377b30e8a93945d725a0590,cf7a476843aca4d409863e54a42206e9f3a8405d..27b9a26f222a6f7413eca2fb29bf5cae1ea643a9
@@@ -117,17 -103,28 +117,17 @@@ static_announce_rte(struct static_prot
      return;
  
    /* We skip rta_lookup() here */
 -  rte *e = rte_get_temp(a, src);
 +  src = static_get_source(p, r->index);
 +  rte e0 = { .attrs = ea, .src = src, .net = r->net, }, *e = &e0;
  
 +  /* Evaluate the filter */
    if (r->cmds)
-     f_eval_rte(r->cmds, e);
 -  {
 -    /* Create a temporary table node */
 -    e->net = alloca(sizeof(net) + r->net->length);
 -    memset(e->net, 0, sizeof(net) + r->net->length);
 -    net_copy(e->net->n.addr, r->net);
++    f_eval_rte(r->cmds, e, 0, NULL, NULL);
  
 -    /* Evaluate the filter */
 -    f_eval_rte(r->cmds, &e, static_lp, 0, NULL, NULL);
 -
 -    /* Remove the temporary node */
 -    e->net = NULL;
 -  }
 +  rte_update(p->p.main_channel, r->net, e, src);
 +  static_free_source(src, r->index);
  
 -  rte_update2(p->p.main_channel, r->net, e, src);
    r->state = SRS_CLEAN;
 -
 -  if (r->cmds)
 -    lp_flush(static_lp);
 -
    return;
  
  withdraw: