From: Maria Matejka Date: Mon, 30 Oct 2023 09:44:45 +0000 (+0100) Subject: Filter: predefined variables for specific blocks X-Git-Tag: v3.0.0~365^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=407eb388b7082b52921e93476c8ff1a98fe3b873;p=thirdparty%2Fbird.git Filter: predefined variables for specific blocks This is a split-commit of the neighboring aggregator branch with a bit improved lvalue handling, to have easier merge into v3. --- diff --git a/filter/config.Y b/filter/config.Y index 4e1f6359f..873e40355 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -106,6 +106,10 @@ f_new_var(struct sym_scope *s) return offset; } +/* Macro for top-level pre-defined variables. */ +#define f_predefined_variable(conf_, name_, type_) \ + cf_define_symbol(conf_, cf_get_symbol(conf_, name_), SYM_VARIABLE | type_, offset, f_new_var(conf_->current_scope)) + /* * Sets and their items are during parsing handled as lists, linked * through left ptr. The first item in a list also contains a pointer diff --git a/filter/filter.c b/filter/filter.c index 65fb92a41..4c0f6f12f 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -87,6 +87,9 @@ struct filter_state { /* Linpool for adata allocation */ struct linpool *pool; + /* Additional external values provided to the filter */ + const struct f_val *val; + /* Buffer for log output */ struct buffer buf; @@ -157,18 +160,20 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; * 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; - 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; @@ -271,6 +276,12 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i if (filter == FILTER_REJECT) return F_REJECT; + return f_run_args(filter, rte, tmp_pool, 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) +{ int rte_cow = ((*rte)->flags & REF_COW); DBG( "Running filter `%s'...", filter->name ); @@ -285,7 +296,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i LOG_BUFFER_INIT(filter_state.buf); /* 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) { /* @@ -337,7 +348,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i */ enum filter_return -f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool) +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) { filter_state = (struct filter_state) { .stack = &filter_stack, @@ -347,10 +358,7 @@ f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool LOG_BUFFER_INIT(filter_state.buf); - ASSERT(!((*rte)->flags & REF_COW)); - ASSERT(!rta_is_cached((*rte)->attrs)); - - return interpret(&filter_state, expr, NULL); + return interpret(&filter_state, expr, argc, argv, pres); } /* @@ -369,7 +377,7 @@ f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) LOG_BUFFER_INIT(filter_state.buf); - enum filter_return fret = interpret(&filter_state, expr, pres); + enum filter_return fret = interpret(&filter_state, expr, 0, NULL, pres); return fret; } diff --git a/filter/filter.h b/filter/filter.h index 91de696cf..18ff0874f 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -52,7 +52,8 @@ 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_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool); +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); struct f_val cf_eval(const struct f_inst *inst, int type); diff --git a/proto/static/static.c b/proto/static/static.c index bb93305ed..cf7a47684 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -113,7 +113,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) net_copy(e->net->n.addr, r->net); /* Evaluate the filter */ - f_eval_rte(r->cmds, &e, static_lp); + f_eval_rte(r->cmds, &e, static_lp, 0, NULL, NULL); /* Remove the temporary node */ e->net = NULL;