From: Maria Matejka Date: Tue, 31 Oct 2023 09:28:01 +0000 (+0100) Subject: Merge commit '407eb388b7082b52921e93476c8ff1a98fe3b873' into thread-next X-Git-Tag: v3.0.0~365 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc3f07fdc3e1b197dbfc838f888e398570088e0d;p=thirdparty%2Fbird.git Merge commit '407eb388b7082b52921e93476c8ff1a98fe3b873' into thread-next --- fc3f07fdc3e1b197dbfc838f888e398570088e0d diff --cc filter/filter.c index 9d3d0c280,4c0f6f12f..2a6261884 --- a/filter/filter.c +++ b/filter/filter.c @@@ -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 */ @@@ -218,11 -292,38 +229,11 @@@ .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)) @@@ -247,17 -348,17 +258,15 @@@ */ 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); } /* @@@ -267,13 -368,16 +276,13 @@@ * @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 92c89fbe1,18ff0874f..121da4686 --- a/filter/filter.h +++ b/filter/filter.h @@@ -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); diff --cc proto/static/static.c index dbce77efb,cf7a47684..27b9a26f2 --- a/proto/static/static.c +++ b/proto/static/static.c @@@ -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: