Filter: Split printing and dying

This commit is contained in:
Maria Matejka 2019-07-03 01:23:49 +02:00
parent 3265c9169d
commit 0206c070ac
5 changed files with 85 additions and 40 deletions

View file

@ -64,7 +64,9 @@ CF_DECLS
struct rtable_config *r; struct rtable_config *r;
struct channel_config *cc; struct channel_config *cc;
struct f_inst *x; struct f_inst *x;
struct f_inst *xp[2]; struct {
struct f_inst *begin, *end;
} xp;
enum filter_return fret; enum filter_return fret;
enum ec_subtype ecs; enum ec_subtype ecs;
struct f_dynamic_attr fda; struct f_dynamic_attr fda;

View file

@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
%nonassoc ELSE %nonassoc ELSE
%type <xp> cmds_int %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 <fda> dynamic_attr
%type <fsa> static_attr %type <fsa> static_attr
%type <f> filter where_filter %type <f> filter where_filter
@ -621,11 +621,21 @@ function_def:
/* Programs */ /* Programs */
cmds: /* EMPTY */ { $$ = NULL; } cmds: /* EMPTY */ { $$ = NULL; }
| cmds_int { $$ = $1[0]; } | cmds_int { $$ = $1.begin; }
; ;
cmds_int: cmd { $$[0] = $$[1] = $1; } cmds_int: cmd {
| cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; } $$.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: block:
@ -960,17 +970,13 @@ break_command:
| PRINTN { $$ = F_NONL; } | PRINTN { $$ = F_NONL; }
; ;
print_one:
term { $$ = f_new_inst(FI_PRINT, $1); }
;
print_list: /* EMPTY */ { $$ = NULL; } print_list: /* EMPTY */ { $$ = NULL; }
| print_one { $$ = $1; } | term { $$ = $1; }
| print_one ',' print_list { | term ',' print_list {
if ($1) { ASSERT($1);
$1->next = $3; ASSERT($1->next == NULL);
$$ = $1; $1->next = $3;
} else $$ = $3; $$ = $1;
} }
; ;
@ -1011,7 +1017,22 @@ cmd:
| UNSET '(' dynamic_attr ')' ';' { | UNSET '(' dynamic_attr ')' ';' {
$$ = f_new_inst(FI_EA_UNSET, $3); $$ = 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); } | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
| CASE term '{' switch_body '}' { | CASE term '{' switch_body '}' {
$$ = f_new_inst(FI_SWITCH, $2, build_tree($4)); $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));

View file

@ -93,6 +93,25 @@ FID_INTERPRET_EXEC()m4_dnl
const $1 $2 = whati->$2 const $1 $2 = whati->$2
FID_INTERPRET_BODY') 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. # Instruction arguments are needed only until linearization is done.
# This puts the arguments into the filter line to be executed before # This puts the arguments into the filter line to be executed before
# the instruction itself. # the instruction itself.

View file

@ -173,7 +173,7 @@
if (fstk->vcnt < whati->count) /* TODO: make this check systematic */ 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); 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 FID_INTERPRET_NEW
#define pv items[i]->i_FI_CONSTANT.val #define pv items[i]->i_FI_CONSTANT.val
@ -320,11 +320,6 @@
RESULT_VAL(val); RESULT_VAL(val);
} }
INST(FI_PRINT, 1, 0) {
NEVER_CONSTANT;
ARG_ANY(1);
val_format(&(v1), &fs->buf);
}
INST(FI_CONDITION, 1, 0) { INST(FI_CONDITION, 1, 0) {
ARG(1, T_BOOL); ARG(1, T_BOOL);
if (v1.val.i) if (v1.val.i)
@ -332,28 +327,37 @@
else else
LINE(3,1); LINE(3,1);
} }
INST(FI_PRINT_AND_DIE, 0, 0) {
INST(FI_PRINT, 0, 0) {
NEVER_CONSTANT; NEVER_CONSTANT;
FID_LINEARIZE_BODY
{
uint opos = pos;
FID_INTERPRET_BODY
ARG_ANY(1); 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 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)); 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))) && if (fs->buf.start < fs->buf.pos)
!(fs->flags & FF_SILENT))
log_commit(*L_INFO, &fs->buf); log_commit(*L_INFO, &fs->buf);
switch (fret) { switch (whati->fret) {
case F_QUITBIRD: case F_QUITBIRD:
die( "Filter asked me to die" ); die( "Filter asked me to die" );
case F_ACCEPT: case F_ACCEPT:
@ -361,7 +365,6 @@
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 */
return fret; /* We have to return now, no more processing. */ return fret; /* We have to return now, no more processing. */
case F_NONL:
case F_NOP: case F_NOP:
break; break;
default: default:

View file

@ -33,17 +33,17 @@ filter_name(const struct filter *filter)
struct filter *f_new_where(struct f_inst *where) struct filter *f_new_where(struct f_inst *where)
{ {
struct f_inst acc = { struct f_inst acc = {
.fi_code = FI_PRINT_AND_DIE, .fi_code = FI_DIE,
.lineno = ifs->lino, .lineno = ifs->lino,
.size = 1, .size = 1,
.i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, }, .i_FI_DIE = { .fret = F_ACCEPT, },
}; };
struct f_inst rej = { struct f_inst rej = {
.fi_code = FI_PRINT_AND_DIE, .fi_code = FI_DIE,
.lineno = ifs->lino, .lineno = ifs->lino,
.size = 1, .size = 1,
.i_FI_PRINT_AND_DIE = { .fret = F_REJECT, }, .i_FI_DIE = { .fret = F_REJECT, },
}; };
struct f_inst i = { struct f_inst i = {