Commit c0999a14 authored by Maria Matejka's avatar Maria Matejka
Browse files

Filter: Converted FI_PRINT and FI_PATHMASK_CONSTRUCT to VARARG

parent c29d73a0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -828,7 +828,7 @@ constructor:
   '(' term ',' term ')' { $$ = f_new_inst(FI_PAIR_CONSTRUCT, $2, $4); }
 | '(' ec_kind ',' term ',' term ')' { $$ = f_new_inst(FI_EC_CONSTRUCT, $4, $6, $2); }
 | '(' term ',' term ',' term ')' { $$ = f_new_inst(FI_LC_CONSTRUCT, $2, $4, $6); }
 | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1, 0); }
 | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1); }
 ;


+44 −19
Original line number Diff line number Diff line
@@ -93,25 +93,6 @@ 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.
@@ -136,6 +117,48 @@ FID_LINEARIZE_BODY
pos = linearize(dest, whati->f$1, pos);
FID_INTERPRET_BODY()')

#	Some instructions accept variable number of arguments.
m4_define(VARARG, `
FID_NEW_ARGS()m4_dnl
  , struct f_inst * fvar
FID_STRUCT_IN()m4_dnl
      struct f_inst * fvar;
      uint varcount;
FID_LINE_IN()m4_dnl
      uint varcount;
FID_NEW_BODY()m4_dnl
whati->varcount = 0;
whati->fvar = fvar;
for (const struct f_inst *child = fvar; child; child = child->next, whati->varcount++) {
  what->size += child->size;
FID_IFCONST([[
  if (child->fi_code != FI_CONSTANT)
    constargs = 0;
]])
}
FID_IFCONST([[
  const struct f_inst **items = NULL;
  if (constargs) {
    items = alloca(whati->varcount * sizeof(struct f_inst *));
    const struct f_inst *child = fvar;
    for (uint i=0; child; i++)
      child = (items[i] = child)->next;
  }
]])
FID_LINEARIZE_BODY()m4_dnl
  pos = linearize(dest, whati->fvar, pos);
  item->varcount = whati->varcount;
FID_DUMP_BODY()m4_dnl
  debug("%snumber of varargs %u\n", INDENT, item->varcount);
FID_SAME_BODY()m4_dnl
  if (f1->varcount != f2->varcount) return 0;
FID_INTERPRET_BODY()
FID_HIC(,[[
  if (fstk->vcnt < whati->varcount) runtime("Stack underflow");
  fstk->vcnt -= whati->varcount;
]],)
')

#	Some arguments need to check their type. After that, ARG_ANY is called.
m4_define(ARG, `ARG_ANY($1)
FID_INTERPRET_EXEC()m4_dnl
@@ -410,6 +433,7 @@ fi_constant(struct f_inst *what, struct f_val val)
#define v1 whati->f1->i_FI_CONSTANT.val
#define v2 whati->f2->i_FI_CONSTANT.val
#define v3 whati->f3->i_FI_CONSTANT.val
#define vv(i) items[i]->i_FI_CONSTANT.val
#define runtime(fmt, ...) cf_error("filter preevaluation, line %d: " fmt, ifs->lino, ##__VA_ARGS__)
#define fpool cfg_mem
#define falloc(size) cfg_alloc(size)
@@ -418,6 +442,7 @@ FID_WR_PUT(3)
#undef v1
#undef v2
#undef v3
#undef vv

/* Line dumpers */
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
+14 −58
Original line number Diff line number Diff line
@@ -60,8 +60,9 @@
 *
 *	What is the syntax here?
 *	m4_dnl	INST(FI_NOP, in, out) {			enum value, input args, output args
 *	m4_dnl	  ARG(num, type);			argument, its id (in data fields) and type
 *	m4_dnl	  ARG_ANY(num);				argument with no type check
 *	m4_dnl	  ARG(num, type);			argument, its id (in data fields) and type accessible by v1, v2, v3
 *	m4_dnl	  ARG_ANY(num);				argument with no type check accessible by v1, v2, v3
 *	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	  SYMBOL;				symbol handed from config
 *	m4_dnl	  STATIC_ATTR;				static attribute definition
@@ -297,45 +298,19 @@
  }

  INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
    ARG_ANY(1);
    FID_MEMBER(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;
      struct f_inst **items;
      if (constargs) {
	items = alloca(len * sizeof(struct f_inst *));
	for (uint i=0; f1; i++) {
	  items[i] = f1;
	  f1 = f1->next;
	  items[i]->next = 0;
	}
	whati->f1 = NULL;
      }
    FID_INTERPRET_BODY

    FID_INTERPRET_EXEC
    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(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
    VARARG;

    FID_INTERPRET_NEW
#define pv(i) items[i]->i_FI_CONSTANT.val
    struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->varcount * sizeof(struct f_path_mask_item));
    pm->len = whati->varcount;

    FID_INTERPRET_BODY
    struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item));
    for (uint i=0; i<whati->count; i++) {
      switch (pv(i).type) {
    for (uint i=0; i<whati->varcount; i++) {
      switch (vv(i).type) {
	case T_PATH_MASK_ITEM:
	  pm->item[i] = pv(i).val.pmi;
	  pm->item[i] = vv(i).val.pmi;
	  break;
	case T_INT:
	  pm->item[i] = (struct f_path_mask_item) {
	    .asn = pv(i).val.i,
	    .asn = vv(i).val.i,
	    .kind = PM_ASN,
	  };
	  break;
@@ -343,13 +318,7 @@
	  runtime( "Error resolving path mask template: value not an integer" );
      }
    }
#undef pv

    FID_INTERPRET_EXEC
      fstk->vcnt -= whati->count;
    FID_INTERPRET_BODY

    pm->len = whati->count;
    RESULT(T_PATH_MASK, path_mask, pm);
  }

@@ -479,24 +448,11 @@

  INST(FI_PRINT, 0, 0) {
    NEVER_CONSTANT;
    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_INTERPRET_BODY

#define pv(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
    if (whati->count && !(fs->flags & FF_SILENT))
      for (uint i=0; i<whati->count; i++)
	val_format(&(pv(i)), &fs->buf);
#undef pv
    VARARG;

    fstk->vcnt -= whati->count;
    if (whati->varcount && !(fs->flags & FF_SILENT))
      for (uint i=0; i<whati->varcount; i++)
	val_format(&(vv(i)), &fs->buf);
  }

  INST(FI_DIE, 0, 0) {
+4 −3
Original line number Diff line number Diff line
@@ -190,9 +190,10 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)

      switch (what->fi_code) {
#define res fstk->vstk[fstk->vcnt]
#define v1 fstk->vstk[fstk->vcnt]
#define v2 fstk->vstk[fstk->vcnt + 1]
#define v3 fstk->vstk[fstk->vcnt + 2]
#define vv(i) fstk->vstk[fstk->vcnt + (i)]
#define v1 vv(0)
#define v2 vv(1)
#define v3 vv(2)

#define runtime(fmt, ...) do { \
  if (!(fs->flags & FF_SILENT)) \