mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Filter: Improve handling of stack frames in filter bytecode
When f_line is done, we have to pop the stack frame. The old code just removed nominal number of args/vars. Change it to use stored ventry value modified by number of returned values. This allows to allocate variables on a stack frame during execution of f_lines instead of just at start. But we need to know the number of returned values for a f_line. It is 1 for term, 0 for cmd. Store that to f_line during linearization.
This commit is contained in:
		
				
					committed by
					
						
						Ondrej Zajicek
					
				
			
			
				
	
			
			
			
						parent
						
							f31f4e6eef
						
					
				
				
					commit
					a2527ee53d
				
			@@ -153,14 +153,14 @@ conf: definition ;
 | 
			
		||||
definition:
 | 
			
		||||
   DEFINE symbol '=' term ';' {
 | 
			
		||||
     struct f_val *val = cfg_allocz(sizeof(struct f_val));
 | 
			
		||||
     if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
 | 
			
		||||
     if (f_eval(f_linearize($4, 1), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
 | 
			
		||||
     cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
 | 
			
		||||
   }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
expr:
 | 
			
		||||
   NUM
 | 
			
		||||
 | '(' term ')' { $$ = f_eval_int(f_linearize($2)); }
 | 
			
		||||
 | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); }
 | 
			
		||||
 | CF_SYM_KNOWN {
 | 
			
		||||
     if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
 | 
			
		||||
     $$ = SYM_VAL($1).i; }
 | 
			
		||||
 
 | 
			
		||||
@@ -329,7 +329,7 @@ filter_def:
 | 
			
		||||
 | 
			
		||||
conf: filter_eval ;
 | 
			
		||||
filter_eval:
 | 
			
		||||
   EVAL term { f_eval_int(f_linearize($2)); }
 | 
			
		||||
   EVAL term { f_eval_int(f_linearize($2, 1)); }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
conf: custom_attr ;
 | 
			
		||||
@@ -453,7 +453,7 @@ where_filter:
 | 
			
		||||
 | 
			
		||||
function_body:
 | 
			
		||||
   function_vars '{' cmds '}' {
 | 
			
		||||
     $$ = f_linearize($3);
 | 
			
		||||
     $$ = f_linearize($3, 0);
 | 
			
		||||
     $$->vars = $1;
 | 
			
		||||
   }
 | 
			
		||||
 ;
 | 
			
		||||
@@ -537,7 +537,7 @@ set_atom:
 | 
			
		||||
 | VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
 | 
			
		||||
 | ENUM   { $$.type = pair_a($1); $$.val.i = pair_b($1); }
 | 
			
		||||
 | '(' term ')' {
 | 
			
		||||
     if (f_eval(f_linearize($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
 | 
			
		||||
     if (f_eval(f_linearize($2, 1), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
 | 
			
		||||
     if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
 | 
			
		||||
   }
 | 
			
		||||
 | CF_SYM_KNOWN {
 | 
			
		||||
@@ -549,13 +549,13 @@ set_atom:
 | 
			
		||||
 | 
			
		||||
switch_atom:
 | 
			
		||||
   NUM   { $$.type = T_INT; $$.val.i = $1; }
 | 
			
		||||
 | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2)); }
 | 
			
		||||
 | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2, 1)); }
 | 
			
		||||
 | fipa  { $$ = $1; }
 | 
			
		||||
 | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
cnum:
 | 
			
		||||
   term { $$ = f_eval_int(f_linearize($1)); }
 | 
			
		||||
   term { $$ = f_eval_int(f_linearize($1, 1)); }
 | 
			
		||||
 | 
			
		||||
pair_item:
 | 
			
		||||
   '(' cnum ',' cnum ')'		{ $$ = f_new_pair_item($2, $2, $4, $4); }
 | 
			
		||||
@@ -642,7 +642,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
 | 
			
		||||
 | switch_body switch_items ':' cmds  {
 | 
			
		||||
     /* Fill data fields */
 | 
			
		||||
     struct f_tree *t;
 | 
			
		||||
     struct f_line *line = f_linearize($4);
 | 
			
		||||
     struct f_line *line = f_linearize($4, 0);
 | 
			
		||||
     for (t = $2; t; t = t->left)
 | 
			
		||||
       t->data = line;
 | 
			
		||||
     $$ = f_merge_items($1, $2);
 | 
			
		||||
@@ -651,7 +651,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
 | 
			
		||||
     struct f_tree *t = f_new_tree();
 | 
			
		||||
     t->from.type = t->to.type = T_VOID;
 | 
			
		||||
     t->right = t;
 | 
			
		||||
     t->data = f_linearize($3);
 | 
			
		||||
     t->data = f_linearize($3, 0);
 | 
			
		||||
     $$ = f_merge_items($1, t);
 | 
			
		||||
 }
 | 
			
		||||
 ;
 | 
			
		||||
 
 | 
			
		||||
@@ -216,7 +216,7 @@ whati->f$1 = f$1;
 | 
			
		||||
FID_DUMP_BODY()m4_dnl
 | 
			
		||||
f_dump_line(item->fl$1, indent + 1);
 | 
			
		||||
FID_LINEARIZE_BODY()m4_dnl
 | 
			
		||||
item->fl$1 = f_linearize(whati->f$1);
 | 
			
		||||
item->fl$1 = f_linearize(whati->f$1, $2);
 | 
			
		||||
FID_SAME_BODY()m4_dnl
 | 
			
		||||
if (!f_same(f1->fl$1, f2->fl$1)) return 0;
 | 
			
		||||
FID_ITERATE_BODY()m4_dnl
 | 
			
		||||
@@ -568,7 +568,7 @@ FID_WR_PUT(8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct f_line *
 | 
			
		||||
f_linearize_concat(const struct f_inst * const inst[], uint count)
 | 
			
		||||
f_linearize_concat(const struct f_inst * const inst[], uint count, uint results)
 | 
			
		||||
{
 | 
			
		||||
  uint len = 0;
 | 
			
		||||
  for (uint i=0; i<count; i++)
 | 
			
		||||
@@ -580,6 +580,8 @@ f_linearize_concat(const struct f_inst * const inst[], uint count)
 | 
			
		||||
  for (uint i=0; i<count; i++)
 | 
			
		||||
    out->len = linearize(out, inst[i], out->len);
 | 
			
		||||
 | 
			
		||||
    out->results = results;
 | 
			
		||||
 | 
			
		||||
#ifdef LOCAL_DEBUG
 | 
			
		||||
  f_dump_line(out, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@
 | 
			
		||||
 *	m4_dnl	  ARG_ANY(num);				argument with no type check accessible by v1, v2, v3
 | 
			
		||||
 *	m4_dnl	  ARG_TYPE(num, type);			just declare the type of argument
 | 
			
		||||
 *	m4_dnl	  VARARG;				variable-length argument list; accessible by vv(i) and whati->varcount
 | 
			
		||||
 *	m4_dnl	  LINE(num, unused);			this argument has to be converted to its own f_line
 | 
			
		||||
 *	m4_dnl	  LINE(num, out);			this argument has to be converted to its own f_line
 | 
			
		||||
 *	m4_dnl	  SYMBOL;				symbol handed from config
 | 
			
		||||
 *	m4_dnl	  STATIC_ATTR;				static attribute definition
 | 
			
		||||
 *	m4_dnl	  DYNAMIC_ATTR;				dynamic attribute definition
 | 
			
		||||
@@ -298,7 +298,7 @@
 | 
			
		||||
    RESULT_TYPE(T_BOOL);
 | 
			
		||||
 | 
			
		||||
    if (v1.val.i)
 | 
			
		||||
      LINE(2,0);
 | 
			
		||||
      LINE(2,1);
 | 
			
		||||
    else
 | 
			
		||||
      RESULT_VAL(v1);
 | 
			
		||||
  }
 | 
			
		||||
@@ -308,7 +308,7 @@
 | 
			
		||||
    RESULT_TYPE(T_BOOL);
 | 
			
		||||
 | 
			
		||||
    if (!v1.val.i)
 | 
			
		||||
      LINE(2,0);
 | 
			
		||||
      LINE(2,1);
 | 
			
		||||
    else
 | 
			
		||||
      RESULT_VAL(v1);
 | 
			
		||||
  }
 | 
			
		||||
@@ -536,7 +536,7 @@
 | 
			
		||||
    if (v1.val.i)
 | 
			
		||||
      LINE(2,0);
 | 
			
		||||
    else
 | 
			
		||||
      LINE(3,1);
 | 
			
		||||
      LINE(3,0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  INST(FI_PRINT, 0, 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,14 +46,15 @@ struct f_line {
 | 
			
		||||
  uint len;				/* Line length */
 | 
			
		||||
  u8 args;				/* Function: Args required */
 | 
			
		||||
  u8 vars;
 | 
			
		||||
  u8 results;				/* Results left on stack: cmd -> 0, term -> 1 */
 | 
			
		||||
  struct f_arg *arg_list;
 | 
			
		||||
  struct f_line_item items[0];		/* The items themselves */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Convert the f_inst infix tree to the f_line structures */
 | 
			
		||||
struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count);
 | 
			
		||||
static inline struct f_line *f_linearize(const struct f_inst *root)
 | 
			
		||||
{ return f_linearize_concat(&root, 1); }
 | 
			
		||||
struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count, uint results);
 | 
			
		||||
static inline struct f_line *f_linearize(const struct f_inst *root, uint results)
 | 
			
		||||
{ return f_linearize_concat(&root, 1, results); }
 | 
			
		||||
 | 
			
		||||
void f_dump_line(const struct f_line *, uint indent);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ struct filter *f_new_where(struct f_inst *where)
 | 
			
		||||
				   f_new_inst(FI_DIE, F_REJECT));
 | 
			
		||||
 | 
			
		||||
  struct filter *f = cfg_allocz(sizeof(struct filter));
 | 
			
		||||
  f->root = f_linearize(cond);
 | 
			
		||||
  f->root = f_linearize(cond, 0);
 | 
			
		||||
  return f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -215,8 +215,7 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* End of current line. Drop local variables before exiting. */
 | 
			
		||||
    fstk->vcnt -= curline.line->vars;
 | 
			
		||||
    fstk->vcnt -= curline.line->args;
 | 
			
		||||
    fstk->vcnt = curline.ventry + curline.line->results;
 | 
			
		||||
    fstk->ecnt--;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -165,7 +165,7 @@ rtrid:
 | 
			
		||||
 | 
			
		||||
idval:
 | 
			
		||||
   NUM { $$ = $1; }
 | 
			
		||||
 | '(' term ')' { $$ = f_eval_int(f_linearize($2)); }
 | 
			
		||||
 | '(' term ')' { $$ = f_eval_int(f_linearize($2, 1)); }
 | 
			
		||||
 | IP4 { $$ = ip4_to_u32($1); }
 | 
			
		||||
 | CF_SYM_KNOWN {
 | 
			
		||||
     if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
 | 
			
		||||
@@ -860,7 +860,7 @@ CF_CLI(DUMP FILTER ALL,,, [[Dump all filters in linearized form]])
 | 
			
		||||
{ filters_dump_all(); cli_msg(0, ""); } ;
 | 
			
		||||
 | 
			
		||||
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
 | 
			
		||||
{ cmd_eval(f_linearize($2)); } ;
 | 
			
		||||
{ cmd_eval(f_linearize($2, 1)); } ;
 | 
			
		||||
 | 
			
		||||
CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
 | 
			
		||||
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [<buffer-size>], [[Control echoing of log messages]]) {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ static_route_finish(void)
 | 
			
		||||
  if (net_type_match(this_srt->net, NB_DEST) == !this_srt->dest)
 | 
			
		||||
    cf_error("Unexpected or missing nexthop/type");
 | 
			
		||||
 | 
			
		||||
  this_srt->cmds = f_linearize(this_srt_cmds);
 | 
			
		||||
  this_srt->cmds = f_linearize(this_srt_cmds, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CF_DECLS
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user