Commit c9f90da9 authored by Jan Maria Matejka's avatar Jan Maria Matejka Committed by Maria Matejka
Browse files

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.
parent f5afee15
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -124,8 +124,7 @@ conf: definition ;
definition:
   DEFINE SYM '=' term ';' {
     struct f_val *val = cfg_alloc(sizeof(struct f_val));
     *val = f_eval($4, cfg_mem);
     if (val->type == T_RETURN) cf_error("Runtime error");
     if (f_eval($4, cfg_mem, val) > F_RETURN) cf_error("Runtime error");
     cf_define_symbol($2, SYM_CONSTANT | val->type, val);
   }
 ;
+1 −1
Original line number Diff line number Diff line
@@ -653,7 +653,7 @@ set_atom:
 | VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
 | ENUM   { $$.type = pair_a($1); $$.val.i = pair_b($1); }
 | '(' 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");
   }
 | SYM {
+11 −15
Original line number Diff line number Diff line
@@ -121,15 +121,15 @@
      while (tt) {
	*vv = lp_alloc(fs->pool, sizeof(struct f_path_mask));
	if (tt->kind == PM_ASN_EXPR) {
	  struct f_val res;
	  INTERPRET(res, (struct f_inst *) tt->val);
	  struct f_val xres;
	  INTERPRET(xres, (struct f_inst *) tt->val);
	  (*vv)->kind = PM_ASN;
	  if (res.type != T_INT) {
	  if (xres.type != T_INT) {
	    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 {
	  **vv = *tt;
	}
@@ -280,9 +280,7 @@
      /* Should take care about turning ACCEPT into MODIFY */
    case F_ERROR:
    case F_REJECT:	/* FIXME (noncritical) Should print complete route along with reason to reject route */
      res.type = T_RETURN;
      res.val.i = what->a2.i;
      return res;	/* We have to return now, no more processing. */
      return what->a2.i;	/* We have to return now, no more processing. */
    case F_NONL:
    case F_NOP:
      break;
@@ -658,14 +656,12 @@
  case FI_RETURN:
    ARG_ANY(1);
    res = v1;
    res.type |= T_RETURN;
    return res;
  case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
    return F_RETURN;
  case FI_CALL:
    ARG_ANY(1);
    res = interpret(fs, what->a2.p);
    if (res.type == T_RETURN)
      return res;
    res.type &= ~T_RETURN;
    fret = interpret(fs, what->a2.p, &res);
    if (fret > F_RETURN)
      return fret;
    break;
  case FI_CLEAR_LOCAL_VARS:	/* Clear local variables */
    for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
+29 −23
Original line number Diff line number Diff line
@@ -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
 * memory managment.
 */
static struct f_val
interpret(struct filter_state *fs, struct f_inst *what)
static enum filter_return
interpret(struct filter_state *fs, struct f_inst *what, struct f_val *resp)
{
  struct symbol *sym;
  struct f_val v1, v2, v3, res = { .type = T_VOID }, *vp;
  struct f_val v1, v2, v3, *vp;
  unsigned u1, u2;
  enum filter_return fret;
  int i;
  u32 as;

  *resp = (struct f_val) { .type = T_VOID };

  for ( ; what; what = what->next) {
  res.type = T_VOID;
#define res (*resp)
  res = (struct f_val) { .type = T_VOID };
  switch(what->fi_code) {

#define runtime(fmt, ...) do { \
    if (!(fs->flags & FF_SILENT)) \
      log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
    res.type = T_RETURN; \
    res.val.i = F_ERROR; \
    return res; \
    return F_ERROR; \
  } while(0)

#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);

#define INTERPRET(val, what_) \
    val = interpret(fs, what_); \
    if (val.type & T_RETURN) \
      return val;
    fret = interpret(fs, what_, &(val)); \
    if (fret >= F_RETURN) \
      return fret;

#define ACCESS_RTE \
  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"

#undef res
#undef runtime
#undef ARG_ANY
#undef ARG
@@ -664,7 +668,7 @@ interpret(struct filter_state *fs, struct f_inst *what)
#undef ACCESS_RTE
#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
 * 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)
{
  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);

  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) {
    /*
@@ -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))
      log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
    return F_ERROR;
  }
  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() */

struct f_val
enum filter_return
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);

  /* Note that in this function we assume that rte->attrs is private / uncached */
  struct f_val res = interpret(&fs, expr);

  return res;
  struct f_val res;
  return interpret(&fs, expr, &res);
}

struct f_val
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
enum filter_return
f_eval(struct f_inst *expr, struct linpool *tmp_pool, struct f_val *pres)
{
  struct filter_state fs = {
    .pool = tmp_pool,
@@ -916,14 +920,16 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)

  LOG_BUFFER_INIT(fs.buf);

  return interpret(&fs, expr);
  return interpret(&fs, expr, pres);
}

uint
f_eval_int(struct f_inst *expr)
{
  /* 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)
    cf_error("Integer expression expected");
+13 −12
Original line number Diff line number Diff line
@@ -175,9 +175,19 @@ void trie_format(struct f_trie *t, buffer *buf);
struct ea_list;
struct rte;

int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
enum filter_return {
  F_NOP = 0,
  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);

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);


#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_REJECT ((void *) 1)
#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_RD 0x2a		/* Route distinguisher for VPN addresses */

#define T_RETURN 0x40
#define T_SET 0x80
#define T_PREFIX_SET 0x81

Loading