Filter refactoring: Passing the resulting struct f_val as a pointer.
This also drops the multiplexing of errors with the f_val itself together with the T_RETURN f_val type flag.
This commit is contained in:
parent
f62a369fb4
commit
7afa143886
7 changed files with 60 additions and 61 deletions
|
@ -124,8 +124,7 @@ conf: definition ;
|
||||||
definition:
|
definition:
|
||||||
DEFINE SYM '=' term ';' {
|
DEFINE SYM '=' term ';' {
|
||||||
struct f_val *val = cfg_alloc(sizeof(struct f_val));
|
struct f_val *val = cfg_alloc(sizeof(struct f_val));
|
||||||
*val = f_eval($4, cfg_mem);
|
if (f_eval($4, cfg_mem, val) > F_RETURN) cf_error("Runtime error");
|
||||||
if (val->type == T_RETURN) cf_error("Runtime error");
|
|
||||||
cf_define_symbol($2, SYM_CONSTANT | val->type, val);
|
cf_define_symbol($2, SYM_CONSTANT | val->type, val);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -653,7 +653,7 @@ set_atom:
|
||||||
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
|
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
|
||||||
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
||||||
| '(' term ')' {
|
| '(' 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");
|
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
|
||||||
}
|
}
|
||||||
| SYM {
|
| SYM {
|
||||||
|
|
|
@ -121,15 +121,15 @@
|
||||||
while (tt) {
|
while (tt) {
|
||||||
*vv = lp_alloc(fs->pool, sizeof(struct f_path_mask));
|
*vv = lp_alloc(fs->pool, sizeof(struct f_path_mask));
|
||||||
if (tt->kind == PM_ASN_EXPR) {
|
if (tt->kind == PM_ASN_EXPR) {
|
||||||
struct f_val res;
|
struct f_val xres;
|
||||||
INTERPRET(res, (struct f_inst *) tt->val);
|
INTERPRET(xres, (struct f_inst *) tt->val);
|
||||||
(*vv)->kind = PM_ASN;
|
(*vv)->kind = PM_ASN;
|
||||||
if (res.type != T_INT) {
|
if (xres.type != T_INT) {
|
||||||
runtime( "Error resolving path mask template: value not an integer" );
|
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 {
|
} else {
|
||||||
**vv = *tt;
|
**vv = *tt;
|
||||||
}
|
}
|
||||||
|
@ -280,9 +280,7 @@
|
||||||
/* Should take care about turning ACCEPT into MODIFY */
|
/* Should take care about turning ACCEPT into MODIFY */
|
||||||
case F_ERROR:
|
case F_ERROR:
|
||||||
case F_REJECT: /* FIXME (noncritical) Should print complete route along with reason to reject route */
|
case F_REJECT: /* FIXME (noncritical) Should print complete route along with reason to reject route */
|
||||||
res.type = T_RETURN;
|
return what->a2.i; /* We have to return now, no more processing. */
|
||||||
res.val.i = what->a2.i;
|
|
||||||
return res; /* We have to return now, no more processing. */
|
|
||||||
case F_NONL:
|
case F_NONL:
|
||||||
case F_NOP:
|
case F_NOP:
|
||||||
break;
|
break;
|
||||||
|
@ -658,14 +656,12 @@
|
||||||
case FI_RETURN:
|
case FI_RETURN:
|
||||||
ARG_ANY(1);
|
ARG_ANY(1);
|
||||||
res = v1;
|
res = v1;
|
||||||
res.type |= T_RETURN;
|
return F_RETURN;
|
||||||
return res;
|
case FI_CALL:
|
||||||
case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out */
|
|
||||||
ARG_ANY(1);
|
ARG_ANY(1);
|
||||||
res = interpret(fs, what->a2.p);
|
fret = interpret(fs, what->a2.p, &res);
|
||||||
if (res.type == T_RETURN)
|
if (fret > F_RETURN)
|
||||||
return res;
|
return fret;
|
||||||
res.type &= ~T_RETURN;
|
|
||||||
break;
|
break;
|
||||||
case FI_CLEAR_LOCAL_VARS: /* Clear local variables */
|
case FI_CLEAR_LOCAL_VARS: /* Clear local variables */
|
||||||
for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
|
for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
|
||||||
|
|
|
@ -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
|
* &f_val structures are copied around, so there are no problems with
|
||||||
* memory managment.
|
* memory managment.
|
||||||
*/
|
*/
|
||||||
static struct f_val
|
static enum filter_return
|
||||||
interpret(struct filter_state *fs, struct f_inst *what)
|
interpret(struct filter_state *fs, struct f_inst *what, struct f_val *resp)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
struct f_val v1, v2, v3, res = { .type = T_VOID }, *vp;
|
struct f_val v1, v2, v3, *vp;
|
||||||
unsigned u1, u2;
|
unsigned u1, u2;
|
||||||
|
enum filter_return fret;
|
||||||
int i;
|
int i;
|
||||||
u32 as;
|
u32 as;
|
||||||
|
|
||||||
|
*resp = (struct f_val) { .type = T_VOID };
|
||||||
|
|
||||||
for ( ; what; what = what->next) {
|
for ( ; what; what = what->next) {
|
||||||
res.type = T_VOID;
|
#define res (*resp)
|
||||||
|
res = (struct f_val) { .type = T_VOID };
|
||||||
switch(what->fi_code) {
|
switch(what->fi_code) {
|
||||||
|
|
||||||
#define runtime(fmt, ...) do { \
|
#define runtime(fmt, ...) do { \
|
||||||
if (!(fs->flags & FF_SILENT)) \
|
if (!(fs->flags & FF_SILENT)) \
|
||||||
log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
|
log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
|
||||||
res.type = T_RETURN; \
|
return F_ERROR; \
|
||||||
res.val.i = F_ERROR; \
|
|
||||||
return res; \
|
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define ARG_ANY(n) INTERPRET(v##n, what->a##n.p)
|
#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);
|
n, f_instruction_name(what->fi_code), t, v##n.type);
|
||||||
|
|
||||||
#define INTERPRET(val, what_) \
|
#define INTERPRET(val, what_) \
|
||||||
val = interpret(fs, what_); \
|
fret = interpret(fs, what_, &(val)); \
|
||||||
if (val.type & T_RETURN) \
|
if (fret >= F_RETURN) \
|
||||||
return val;
|
return fret;
|
||||||
|
|
||||||
#define ACCESS_RTE \
|
#define ACCESS_RTE \
|
||||||
do { if (!fs->rte) runtime("No route to access"); } while (0)
|
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"
|
#include "filter/f-inst.c"
|
||||||
|
|
||||||
|
#undef res
|
||||||
#undef runtime
|
#undef runtime
|
||||||
#undef ARG_ANY
|
#undef ARG_ANY
|
||||||
#undef ARG
|
#undef ARG
|
||||||
|
@ -664,7 +668,7 @@ interpret(struct filter_state *fs, struct f_inst *what)
|
||||||
#undef ACCESS_RTE
|
#undef ACCESS_RTE
|
||||||
#undef ACCESS_EATTRS
|
#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
|
* (and cached rta of read-only source rte is intact), if rte is
|
||||||
* modified in place, old cached rta is possibly freed.
|
* 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)
|
f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags)
|
||||||
{
|
{
|
||||||
if (filter == FILTER_ACCEPT)
|
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);
|
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) {
|
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))
|
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);
|
log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
|
||||||
return F_ERROR;
|
return F_ERROR;
|
||||||
}
|
}
|
||||||
DBG( "done (%u)\n", res.val.i );
|
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() */
|
/* 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)
|
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);
|
LOG_BUFFER_INIT(fs.buf);
|
||||||
|
|
||||||
/* Note that in this function we assume that rte->attrs is private / uncached */
|
/* Note that in this function we assume that rte->attrs is private / uncached */
|
||||||
struct f_val res = interpret(&fs, expr);
|
struct f_val res;
|
||||||
|
return interpret(&fs, expr, &res);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct f_val
|
enum filter_return
|
||||||
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
f_eval(struct f_inst *expr, struct linpool *tmp_pool, struct f_val *pres)
|
||||||
{
|
{
|
||||||
struct filter_state fs = {
|
struct filter_state fs = {
|
||||||
.pool = tmp_pool,
|
.pool = tmp_pool,
|
||||||
|
@ -916,14 +920,16 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
||||||
|
|
||||||
LOG_BUFFER_INIT(fs.buf);
|
LOG_BUFFER_INIT(fs.buf);
|
||||||
|
|
||||||
return interpret(&fs, expr);
|
return interpret(&fs, expr, pres);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
f_eval_int(struct f_inst *expr)
|
f_eval_int(struct f_inst *expr)
|
||||||
{
|
{
|
||||||
/* Called independently in parse-time to eval expressions */
|
/* 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)
|
if (res.type != T_INT)
|
||||||
cf_error("Integer expression expected");
|
cf_error("Integer expression expected");
|
||||||
|
|
|
@ -175,9 +175,19 @@ void trie_format(struct f_trie *t, buffer *buf);
|
||||||
struct ea_list;
|
struct ea_list;
|
||||||
struct rte;
|
struct rte;
|
||||||
|
|
||||||
int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
|
enum filter_return {
|
||||||
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
|
F_NOP = 0,
|
||||||
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
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);
|
uint f_eval_int(struct f_inst *expr);
|
||||||
|
|
||||||
char *filter_name(struct filter *filter);
|
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);
|
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_ACCEPT NULL
|
||||||
#define FILTER_REJECT ((void *) 1)
|
#define FILTER_REJECT ((void *) 1)
|
||||||
#define FILTER_UNDEF ((void *) 2) /* Used in BGP */
|
#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_LCLIST 0x29 /* Large community list */
|
||||||
#define T_RD 0x2a /* Route distinguisher for VPN addresses */
|
#define T_RD 0x2a /* Route distinguisher for VPN addresses */
|
||||||
|
|
||||||
#define T_RETURN 0x40
|
|
||||||
#define T_SET 0x80
|
#define T_SET 0x80
|
||||||
#define T_PREFIX_SET 0x81
|
#define T_PREFIX_SET 0x81
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,11 @@ run_function(const void *parsed_fn_def)
|
||||||
struct f_inst *f = (struct f_inst *) parsed_fn_def;
|
struct f_inst *f = (struct f_inst *) parsed_fn_def;
|
||||||
|
|
||||||
linpool *tmp = lp_new_default(&root_pool);
|
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);
|
rfree(tmp);
|
||||||
|
|
||||||
if (res.type == T_RETURN && res.val.i >= F_REJECT)
|
return (fret < F_REJECT);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -97,9 +97,8 @@ cmd_show_memory(void)
|
||||||
void
|
void
|
||||||
cmd_eval(struct f_inst *expr)
|
cmd_eval(struct f_inst *expr)
|
||||||
{
|
{
|
||||||
struct f_val v = f_eval(expr, this_cli->parser_pool);
|
struct f_val v;
|
||||||
|
if (f_eval(expr, this_cli->parser_pool, &v) > F_RETURN)
|
||||||
if (v.type == T_RETURN)
|
|
||||||
{
|
{
|
||||||
cli_msg(8008, "runtime error");
|
cli_msg(8008, "runtime error");
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue