mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Filter: Split printing and dying
This commit is contained in:
		@@ -64,7 +64,9 @@ CF_DECLS
 | 
			
		||||
  struct rtable_config *r;
 | 
			
		||||
  struct channel_config *cc;
 | 
			
		||||
  struct f_inst *x;
 | 
			
		||||
  struct f_inst *xp[2];
 | 
			
		||||
  struct {
 | 
			
		||||
    struct f_inst *begin, *end;
 | 
			
		||||
  } xp;
 | 
			
		||||
  enum filter_return fret;
 | 
			
		||||
  enum ec_subtype ecs;
 | 
			
		||||
  struct f_dynamic_attr fda;
 | 
			
		||||
 
 | 
			
		||||
@@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 | 
			
		||||
%nonassoc ELSE
 | 
			
		||||
 | 
			
		||||
%type <xp> cmds_int
 | 
			
		||||
%type <x> term block cmd cmds constant constructor print_one print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
 | 
			
		||||
%type <x> term block cmd cmds constant constructor print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
 | 
			
		||||
%type <fda> dynamic_attr
 | 
			
		||||
%type <fsa> static_attr
 | 
			
		||||
%type <f> filter where_filter
 | 
			
		||||
@@ -621,11 +621,21 @@ function_def:
 | 
			
		||||
/* Programs */
 | 
			
		||||
 | 
			
		||||
cmds: /* EMPTY */ { $$ = NULL; }
 | 
			
		||||
 | cmds_int { $$ = $1[0]; }
 | 
			
		||||
 | cmds_int { $$ = $1.begin; }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
cmds_int: cmd { $$[0] = $$[1] = $1; }
 | 
			
		||||
 | cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; }
 | 
			
		||||
cmds_int: cmd {
 | 
			
		||||
  $$.begin = $$.end = $1;
 | 
			
		||||
  while ($$.end->next)
 | 
			
		||||
    $$.end = $$.end->next;
 | 
			
		||||
  }
 | 
			
		||||
 | cmds_int cmd {
 | 
			
		||||
  $$.begin = $1.begin;
 | 
			
		||||
  $1.end->next = $2;
 | 
			
		||||
  $$.end = $2;
 | 
			
		||||
  while ($$.end->next)
 | 
			
		||||
    $$.end = $$.end->next;
 | 
			
		||||
 }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
block:
 | 
			
		||||
@@ -960,17 +970,13 @@ break_command:
 | 
			
		||||
 | PRINTN { $$ = F_NONL; }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
print_one:
 | 
			
		||||
   term { $$ = f_new_inst(FI_PRINT, $1); }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
print_list: /* EMPTY */ { $$ = NULL; }
 | 
			
		||||
 | print_one { $$ = $1; }
 | 
			
		||||
 | print_one ',' print_list {
 | 
			
		||||
     if ($1) {
 | 
			
		||||
 | term { $$ = $1; }
 | 
			
		||||
 | term ',' print_list {
 | 
			
		||||
     ASSERT($1);
 | 
			
		||||
     ASSERT($1->next == NULL);
 | 
			
		||||
     $1->next = $3;
 | 
			
		||||
     $$ = $1;
 | 
			
		||||
     } else $$ = $3;
 | 
			
		||||
   }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
@@ -1011,7 +1017,22 @@ cmd:
 | 
			
		||||
 | UNSET '(' dynamic_attr ')' ';' {
 | 
			
		||||
     $$ = f_new_inst(FI_EA_UNSET, $3);
 | 
			
		||||
   }
 | 
			
		||||
 | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); }
 | 
			
		||||
 | break_command print_list ';' {
 | 
			
		||||
    struct f_inst *breaker = NULL;
 | 
			
		||||
    struct f_inst *printer = NULL;
 | 
			
		||||
    if ($2)
 | 
			
		||||
      printer = f_new_inst(FI_PRINT, $2);
 | 
			
		||||
    if ($1 != F_NONL)
 | 
			
		||||
      breaker = f_new_inst(FI_DIE, $1);
 | 
			
		||||
 | 
			
		||||
    if (printer && breaker)
 | 
			
		||||
      printer->next = breaker;
 | 
			
		||||
 | 
			
		||||
    if (printer)
 | 
			
		||||
      $$ = printer;
 | 
			
		||||
    else
 | 
			
		||||
      $$ = breaker;
 | 
			
		||||
   }
 | 
			
		||||
 | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } 
 | 
			
		||||
 | CASE term '{' switch_body '}' {
 | 
			
		||||
      $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,25 @@ FID_INTERPRET_EXEC()m4_dnl
 | 
			
		||||
const $1 $2 = whati->$2
 | 
			
		||||
FID_INTERPRET_BODY')
 | 
			
		||||
 | 
			
		||||
m4_define(FID_MEMBER_IN, `m4_dnl
 | 
			
		||||
FID_LINE_IN()m4_dnl
 | 
			
		||||
      $1 $2;
 | 
			
		||||
FID_STRUCT_IN()m4_dnl
 | 
			
		||||
      $1 $2;
 | 
			
		||||
FID_LINEARIZE_BODY()m4_dnl
 | 
			
		||||
item->$2 = whati->$2;
 | 
			
		||||
m4_ifelse($3,,,[[
 | 
			
		||||
FID_SAME_BODY()m4_dnl
 | 
			
		||||
if ($3) return 0;
 | 
			
		||||
]])
 | 
			
		||||
m4_ifelse($4,,,[[
 | 
			
		||||
FID_DUMP_BODY()m4_dnl
 | 
			
		||||
debug("%s$4\n", INDENT, $5);
 | 
			
		||||
]])
 | 
			
		||||
FID_INTERPRET_EXEC()m4_dnl
 | 
			
		||||
const $1 $2 = whati->$2
 | 
			
		||||
FID_INTERPRET_BODY')
 | 
			
		||||
 | 
			
		||||
#	Instruction arguments are needed only until linearization is done.
 | 
			
		||||
#	This puts the arguments into the filter line to be executed before
 | 
			
		||||
#	the instruction itself.
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@
 | 
			
		||||
    if (fstk->vcnt < whati->count) /* TODO: make this check systematic */
 | 
			
		||||
      runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count);
 | 
			
		||||
 | 
			
		||||
#define pv fstk->vstk[fstk->vcnt - count + i]
 | 
			
		||||
#define pv fstk->vstk[fstk->vcnt - whati->count + i]
 | 
			
		||||
 | 
			
		||||
    FID_INTERPRET_NEW
 | 
			
		||||
#define pv items[i]->i_FI_CONSTANT.val
 | 
			
		||||
@@ -320,11 +320,6 @@
 | 
			
		||||
 | 
			
		||||
    RESULT_VAL(val);
 | 
			
		||||
  }
 | 
			
		||||
  INST(FI_PRINT, 1, 0) {
 | 
			
		||||
    NEVER_CONSTANT;
 | 
			
		||||
    ARG_ANY(1);
 | 
			
		||||
    val_format(&(v1), &fs->buf);
 | 
			
		||||
  }
 | 
			
		||||
  INST(FI_CONDITION, 1, 0) {
 | 
			
		||||
    ARG(1, T_BOOL);
 | 
			
		||||
    if (v1.val.i)
 | 
			
		||||
@@ -332,28 +327,37 @@
 | 
			
		||||
    else
 | 
			
		||||
      LINE(3,1);
 | 
			
		||||
  }
 | 
			
		||||
  INST(FI_PRINT_AND_DIE, 0, 0) {
 | 
			
		||||
 | 
			
		||||
  INST(FI_PRINT, 0, 0) {
 | 
			
		||||
    NEVER_CONSTANT;
 | 
			
		||||
    FID_LINEARIZE_BODY
 | 
			
		||||
    {
 | 
			
		||||
      uint opos = pos;
 | 
			
		||||
      FID_INTERPRET_BODY
 | 
			
		||||
 | 
			
		||||
    ARG_ANY(1);
 | 
			
		||||
    FID_MEMBER_IN(uint, count, f1->count != f2->count, number of items %u, item->count);
 | 
			
		||||
 | 
			
		||||
    FID_NEW_BODY
 | 
			
		||||
      uint len = 0;
 | 
			
		||||
      for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
 | 
			
		||||
	;
 | 
			
		||||
      whati->count = len;
 | 
			
		||||
 | 
			
		||||
      FID_LINEARIZE_BODY
 | 
			
		||||
      if (opos < pos)
 | 
			
		||||
	dest->items[pos].flags |= FIF_PRINTED;
 | 
			
		||||
    }
 | 
			
		||||
    FID_INTERPRET_BODY
 | 
			
		||||
 | 
			
		||||
#define pv fstk->vstk[fstk->vcnt - whati->count + i]
 | 
			
		||||
    if (whati->count)
 | 
			
		||||
      for (uint i=0; i<whati->count; i++)
 | 
			
		||||
	val_format(&(pv), &fs->buf);
 | 
			
		||||
#undef pv
 | 
			
		||||
 | 
			
		||||
    fstk->vcnt -= whati->count;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  INST(FI_DIE, 0, 0) {
 | 
			
		||||
    NEVER_CONSTANT;
 | 
			
		||||
    FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret));
 | 
			
		||||
 | 
			
		||||
    if ((fret == F_NOP || (fret != F_NONL && (what->flags & FIF_PRINTED))) &&
 | 
			
		||||
	!(fs->flags & FF_SILENT))
 | 
			
		||||
    if (fs->buf.start < fs->buf.pos)
 | 
			
		||||
      log_commit(*L_INFO, &fs->buf);
 | 
			
		||||
 | 
			
		||||
    switch (fret) {
 | 
			
		||||
    switch (whati->fret) {
 | 
			
		||||
    case F_QUITBIRD:
 | 
			
		||||
      die( "Filter asked me to die" );
 | 
			
		||||
    case F_ACCEPT:
 | 
			
		||||
@@ -361,7 +365,6 @@
 | 
			
		||||
    case F_ERROR:
 | 
			
		||||
    case F_REJECT:	/* FIXME (noncritical) Should print complete route along with reason to reject route */
 | 
			
		||||
      return fret;	/* We have to return now, no more processing. */
 | 
			
		||||
    case F_NONL:
 | 
			
		||||
    case F_NOP:
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
 
 | 
			
		||||
@@ -33,17 +33,17 @@ filter_name(const struct filter *filter)
 | 
			
		||||
struct filter *f_new_where(struct f_inst *where)
 | 
			
		||||
{
 | 
			
		||||
  struct f_inst acc = {
 | 
			
		||||
    .fi_code = FI_PRINT_AND_DIE,
 | 
			
		||||
    .fi_code = FI_DIE,
 | 
			
		||||
    .lineno = ifs->lino,
 | 
			
		||||
    .size = 1,
 | 
			
		||||
    .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, },
 | 
			
		||||
    .i_FI_DIE = { .fret = F_ACCEPT, },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct f_inst rej = {
 | 
			
		||||
    .fi_code = FI_PRINT_AND_DIE,
 | 
			
		||||
    .fi_code = FI_DIE,
 | 
			
		||||
    .lineno = ifs->lino,
 | 
			
		||||
    .size = 1,
 | 
			
		||||
    .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, },
 | 
			
		||||
    .i_FI_DIE = { .fret = F_REJECT, },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  struct f_inst i = {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user