Commit 0ae4a719 authored by Jan Maria Matejka's avatar Jan Maria Matejka
Browse files

TMP: let's try to run this

parent 9aec608c
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -331,12 +331,10 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3)
  else
#endif
  {
    rv = cfg_allocz(sizeof(struct f_inst3));
    rv->lineno = ifs->lino;
    rv->fi_code = fi_lc_construct;
    rv = f_new_inst(fi_lc_construct);
    rv->a1.p = t1;
    rv->a2.p = t2;
    INST3(rv).p = t3;
    rv->a3.p = t3;
  }

  return rv;
+71 −63
Original line number Diff line number Diff line
@@ -621,13 +621,7 @@ static struct f_val interpret(struct f_inst *what);
static struct f_val
interpret(struct f_inst *what)
{
  struct symbol *sym;
  struct f_val v1, v2, res, *vp;
  unsigned u1, u2;
  int i;
  u32 as;

  res.type = T_VOID;
  struct f_val res = { .type = T_VOID };
  if (!what)
    return res;

@@ -638,7 +632,7 @@ interpret(struct f_inst *what)
    FI_LIST
#undef F
  default:
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
    bug( "Unknown instruction %d (%c%c)", what->fi_code, (what->fi_code & 0xff00) >> 8, what->fi_code & 0xff);
  }
  if (what->next)
    return interpret(what->next);
@@ -653,7 +647,9 @@ interpret(struct f_inst *what)
#define ONEARG ARG(v1, a1.p)
#define TWOARGS ARG(v1, a1.p) \
		ARG(v2, a2.p)

#define THREEARGS ARG(v1, a1.p) \
		ARG(v2, a2.p) \
		ARG(v3, a3.p)
#define A2_SAME if (f1->a2.i != f2->a2.i) return 0;

/*
@@ -668,38 +664,36 @@ i_same(struct f_inst *f1, struct f_inst *f2)
    return 1;
  if (f1->aux != f2->aux)
    return 0;
  if (f1->code != f2->code)
  if (f1->fi_code != f2->fi_code)
    return 0;
  if (f1 == f2)		/* It looks strange, but it is possible with call rewriting trickery */
    return 1;

  switch(f1->code) {
  case ',': /* fall through */
  case '+':
  case '-':
  case '*':
  case '/':
  case '|':
  case '&':
  case P('m','p'):
  case P('m','c'):
  case P('!','='):
  case P('=','='):
  case '<':
  case P('<','='): TWOARGS; break;

  case '!': ONEARG; break;
  case P('!', '~'):
  case '~': TWOARGS; break;
  case P('d','e'): ONEARG; break;

  case P('m','l'):
    TWOARGS;
    if (!i_same(INST3(f1).p, INST3(f2).p))
      return 0;
  switch(f1->fi_code) {
  case fi_add:
  case fi_subtract:
  case fi_multiply:
  case fi_divide:
  case fi_or:
  case fi_and:
  case fi_pair_construct:
  case fi_ec_construct:
  case fi_neq:
  case fi_eq:
  case fi_lt:
  case fi_lte:
    TWOARGS; break;
  case fi_not:
    ONEARG; break;
  case fi_not_match:
  case fi_match:
    TWOARGS; break;
  case fi_defined:
    ONEARG; break;
  case fi_lc_construct:
    THREEARGS;
    break;

  case 's':
  case fi_set:
    ARG(v2, a2.p);
    {
      struct symbol *s1, *s2;
@@ -712,7 +706,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
    }
    break;

  case 'c':
  case fi_constant:
    switch (f1->aux) {

    case T_PREFIX_SET:
@@ -735,43 +729,57 @@ i_same(struct f_inst *f1, struct f_inst *f2)
    }
    break;

  case 'C':
  case fi_constant_indirect:
    if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
      return 0;
    break;

  case 'V':
  case fi_variable:
    if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
      return 0;
    break;
  case 'p': case 'L': ONEARG; break;
  case '?': TWOARGS; break;
  case '0': case 'E': break;
  case P('p',','): ONEARG; A2_SAME; break;
  case 'P':
  case 'a': A2_SAME; break;
  case P('e','a'): A2_SAME; break;
  case P('P','S'):
  case P('a','S'):
  case P('e','S'): ONEARG; A2_SAME; break;

  case 'r': ONEARG; break;
  case P('c','p'): ONEARG; break;
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
  case fi_print:
  case fi_length:
    ONEARG; break;
  case fi_condition:
    TWOARGS; break;
  case fi_nop:
  case fi_empty:
    break;
  case fi_print_and_die:
    ONEARG;
    A2_SAME;
    break;
  case fi_pref_get:
  case fi_rta_get:
  case fi_ea_get:
    A2_SAME;
    break;
  case fi_pref_set:
  case fi_rta_set:
  case fi_ea_set:
    ONEARG;
    A2_SAME;
    break;

  case fi_return: ONEARG; break;
  case fi_ip: ONEARG; break;
  case fi_call: /* Call rewriting trickery to avoid exponential behaviour */
             ONEARG;
	     if (!i_same(f1->a2.p, f2->a2.p))
	       return 0;
	     f2->a2.p = f1->a2.p;
	     break;
  case P('c','v'): break; /* internal instruction */
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
  case P('i','M'): TWOARGS; break;
  case P('A','p'): TWOARGS; break;
  case P('C','a'): TWOARGS; break;
  case P('a','f'):
  case P('a','l'):
  case P('a','L'): ONEARG; break;
  case P('R','C'):
  case fi_clear_local_vars: break; /* internal instruction */
  case fi_switch: ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
  case fi_ip_mask: TWOARGS; break;
  case fi_path_prepend: TWOARGS; break;
  case fi_clist_add_del: TWOARGS; break;
  case fi_as_path_first:
  case fi_as_path_last:
  case fi_as_path_last_nag:
    ONEARG; break;
  case fi_roa_check:
    TWOARGS;
    /* Does not really make sense - ROA check resuls may change anyway */
    if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
@@ -779,7 +787,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
      return 0;
    break;
  default:
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
    bug( "Unknown instruction %d in same (%c%c)", f1->fi_code, (f1->fi_code & 0xff00) >> 8, f1->fi_code & 0xff);
  }
  return i_same(f1->next, f2->next);
}
+25 −33
Original line number Diff line number Diff line
@@ -18,49 +18,48 @@

#define FI_TWOCHAR(a,b)	((a<<8) | b)
#define FI_LIST \
  F(comma,		  0, ',') \
  F(add,		  0, '+') \
  F(subtract,		  0, '-') \
  F(multiply,		  0, '*') \
  F(divide,		  0, '/') \
  F(and,		  0, '&') \
  F(or,			  0, '|') \
  F(add,		' ', '+') \
  F(subtract,		' ', '-') \
  F(multiply,		' ', '*') \
  F(divide,		' ', '/') \
  F(and,		' ', '&') \
  F(or,			' ', '|') \
  F(pair_construct,	'm', 'p') \
  F(ec_construct,	'm', 'c') \
  F(lc_construct,	'm', 'l') \
  F(neq,		'!', '=') \
  F(eq,			'=', '=') \
  F(lt,			  0, '<') \
  F(lt,			' ', '<') \
  F(lte,		'<', '=') \
  F(not,		  0, '!') \
  F(match,		  0, '~') \
  F(not,		' ', '!') \
  F(match,		' ', '~') \
  F(not_match,		'!', '~') \
  F(defined,		'd', 'e') \
  F(set,		  0, 's') \
  F(constant,		  0, 'c') \
  F(variable,		  0, 'V') \
  F(constant_indirect,	  0, 'C') \
  F(print,		  0, 'p') \
  F(condition,		  0, '?') \
  F(nop,		  0, '0') \
  F(set,		' ', 's') \
  F(constant,		' ', 'c') \
  F(variable,		' ', 'V') \
  F(constant_indirect,	' ', 'C') \
  F(print,		' ', 'p') \
  F(condition,		' ', '?') \
  F(nop,		' ', '0') \
  F(print_and_die,	'p', ',') \
  F(rta_get,		  0, 'a') \
  F(rta_get,		' ', 'a') \
  F(rta_set,		'a', 'S') \
  F(ea_get,		'e', 'a') \
  F(ea_set,		'e', 'S') \
  F(pref_get,		  0, 'P') \
  F(pref_get,		' ', 'P') \
  F(pref_set,		'P', 'S') \
  F(length,		  0, 'L') \
  F(length,		' ', 'L') \
  F(ip,			'c', 'p') \
  F(as_path_first,	'a', 'f') \
  F(as_path_last,	'a', 'l') \
  F(as_path_last_nag,	'a', 'L') \
  F(return,		  0, 'r') \
  F(return,		' ', 'r') \
  F(call,		'c', 'a') \
  F(clear_local_vars,	'c', 'V') \
  F(switch,		'S', 'W') \
  F(ip_mask,		'i', 'M') \
  F(empty,		  0, 'E') \
  F(empty,		' ', 'E') \
  F(path_prepend,	'A', 'p') \
  F(clist_add_del,	'C', 'a') \
  F(roa_check,		'R', 'C')
@@ -84,6 +83,10 @@ struct f_inst { /* Instruction */
    int i;
    void *p;
  } a2;
  union {
    int i;
    void *p;
  } a3;
  int lineno;
};

@@ -96,17 +99,6 @@ struct f_inst_roa_check {
  struct roa_table_config *rtc;
};

struct f_inst3 {
  struct f_inst i;
  union {
    int i;
    void *p;
  } a3;
};

#define INST3(x) (((struct f_inst3 *) x)->a3)


struct f_prefix {
  ip_addr ip;
  int len;
+61 −54
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
  (1u << (what->a2.i >> 24))

#define ARG(n,call) \
  struct f_val v##n = call((n == 3) ? (INST3(what).p) : what->a##n.p); \
  struct f_val v##n = call(what->a##n.p); \
  if (v##n.type & T_RETURN) \
    return v##n;

@@ -23,6 +23,7 @@
#define RET_VOID return F_VAL_VOID
#define RETA(member,value) RET(what->aux, member, value)

/* Interpret */
#define FI_INST_NUMERIC_BINARY(name,op) \
  FI_INST_INTERPRET(name) \
  { \
@@ -61,7 +62,7 @@ static inline struct f_val fi_interpret_boolbinary(const struct f_inst *what)
#define fi_interpret_and fi_interpret_boolbinary
#define fi_interpret_or fi_interpret_boolbinary

F_INST_INTERPRET(pair_construct)
FI_INST_INTERPRET(pair_construct)
{
  AI(1); AI(2);
  if ((v1.type != T_INT) || (v2.type != T_INT))
@@ -72,7 +73,7 @@ F_INST_INTERPRET(pair_construct)
  RET(T_PAIR, i, (u1 << 16) | u2);
}

F_INST_INTERPRET(ec_construct)
FI_INST_INTERPRET(ec_construct)
{
  AI(1); AI(2);
  int check, ipv4_used;
@@ -118,13 +119,13 @@ F_INST_INTERPRET(ec_construct)
  return res;
}

F_INST_INTERPRET(lc_construct)
FI_INST_INTERPRET(lc_construct)
{
  AI(1); AI(2); AI(3);
  if ((v1.type != T_INT) || (v2.type != T_INT) || (v3.type != T_INT))
    runtime( "Can't operate with value of non-integer type in LC constructor" );

  RET(T_LC, lc, (lcomm) { v1.val.i, v2.val.i, v3.val.i });
  RET(T_LC, lc, ((lcomm) { v1.val.i, v2.val.i, v3.val.i }));
}

/* Relational operators */
@@ -150,7 +151,7 @@ static inline struct f_val fi_interpret_compare(const struct f_inst *what)
#define fi_interpret_lt fi_interpret_compare
#define fi_interpret_lte fi_interpret_compare

F_INST_INTERPRET(not)
FI_INST_INTERPRET(not)
{
  AI(1);
  if (v1.type != T_BOOL)
@@ -158,7 +159,7 @@ F_INST_INTERPRET(not)
  RET(T_BOOL, i, !v1.val.i);
}

F_INST_INTERPRET(match)
FI_INST_INTERPRET(match)
{
  AI(1); AI(2);
  int i = val_in_range(v1, v2);
@@ -167,7 +168,7 @@ F_INST_INTERPRET(match)
  RET(T_BOOL, i, !!i);
}

F_INST_INTERPRET(not_match)
FI_INST_INTERPRET(not_match)
{
  AI(1); AI(2);
  int i = val_in_range(v1, v2);
@@ -176,13 +177,13 @@ F_INST_INTERPRET(not_match)
  RET(T_BOOL, i, !i);
}

F_INST_INTERPRET(defined)
FI_INST_INTERPRET(defined)
{
  AI(1);
  RET(T_BOOL, i, (v1.type != T_VOID));
}

F_INST_INTERPRET(set)
FI_INST_INTERPRET(set)
{
  /* Set to indirect value, a1 = variable, a2 = value */
  AI(2);
@@ -194,7 +195,7 @@ F_INST_INTERPRET(set)
    if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
      vp->type = T_QUAD;
      vp->val.i = ipa_to_u32(v2.val.px.ip);
      break;
      RET_VOID;
    }
#endif
    runtime( "Assigning to variable of incompatible type" );
@@ -203,7 +204,7 @@ F_INST_INTERPRET(set)
  RET_VOID;
}

F_INST_INTERPRET(constant)
FI_INST_INTERPRET(constant)
{
  /* some constants have value in a2, some in *a1.p, strange. */
  /* integer (or simple type) constant, string, set, or prefix_set */
@@ -211,25 +212,25 @@ F_INST_INTERPRET(constant)
    case T_PREFIX_SET:	RET(T_PREFIX_SET, ti, what->a2.p);
    case T_SET:		RET(T_SET, t, what->a2.p);
    case T_STRING:	RET(T_STRING, s, what->a2.p);
    default:		RET(what->aux, i, what->a2.p);
    default:		RET(what->aux, i, what->a2.i);
  }
}

F_INST_INTERPRET(variable)
FI_INST_INTERPRET(variable)
{
  return * ((struct f_val *) what->a1.p);
}

#define fi_interpret_constant_indirect fi_interpret_variable

F_INST_INTERPRET(print)
FI_INST_INTERPRET(print)
{
  AI(1);
  val_format(v1, &f_buf);
  RET_VOID;
}

F_INST_INTERPRET(condition)
FI_INST_INTERPRET(condition)
{
  /* Structure of conditions:
   * if (CONDITION) then TRUE_BLOCK else FALSE_BLOCK
@@ -287,12 +288,13 @@ F_INST_INTERPRET(condition)
    RET(T_BOOL, i, 1);
}

F_INST_INTERPRET(nop)
FI_INST_INTERPRET(nop)
{
  debug( "No operation\n" );
  RET_VOID;
}

F_INST_INTERPRET(print_and_die)
FI_INST_INTERPRET(print_and_die)
{
  AI(1);
  if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
@@ -306,7 +308,6 @@ F_INST_INTERPRET(print_and_die)
  case F_ERROR:
  case F_REJECT:	/* FIXME (noncritical) Should print complete route along with reason to reject route */
    RET(T_RETURN, i, what->a2.i);
    return res;	/* We have to return now, no more processing. */
  case F_NONL:
  case F_NOP:
      break;
@@ -316,7 +317,7 @@ F_INST_INTERPRET(print_and_die)
  RET_VOID;
}

F_INST_INTERPRET(rta_get)
FI_INST_INTERPRET(rta_get)
{
  ACCESS_RTE;
  struct rta *rta = (*f_rte)->attrs;
@@ -325,10 +326,10 @@ F_INST_INTERPRET(rta_get)
  {
  case SA_FROM:		RETA(px.ip, rta->from);
  case SA_GW:		RETA(px.ip, rta->gw);
  case SA_NET:		RETA(px, {
  case SA_NET:		RETA(px, ((struct f_prefix) {
			    .ip = (*f_rte)->net->n.prefix,
			    .len = (*f_rte)->net->n.pxlen
			});
			}));
  case SA_PROTO:	RETA(s, rta->src->proto->name);
  case SA_SOURCE:	RETA(i, rta->source);
  case SA_SCOPE:	RETA(i, rta->scope); break;
@@ -343,7 +344,7 @@ F_INST_INTERPRET(rta_get)
  RET_VOID;
}

F_INST_INTERPRET(rta_set)
FI_INST_INTERPRET(rta_set)
{
  AI(1);
  ACCESS_RTE;
@@ -379,16 +380,21 @@ F_INST_INTERPRET(rta_set)
    break;

  case SA_DEST:
    i = v1.val.i;
    if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
      runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );

    rta->dest = i;
    switch(v1.val.i)
    {
      case RTD_BLACKHOLE:
      case RTD_UNREACHABLE:
      case RTD_PROHIBIT:
	rta->dest = v1.val.i;
	rta->gw = IPA_NONE;
	rta->iface = NULL;
	rta->nexthops = NULL;
	rta->hostentry = NULL;
	break;
      default:
	runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
    }
    break;

  default:
    bug("Invalid static attribute access (%x)", what->a2.i);
@@ -396,7 +402,7 @@ F_INST_INTERPRET(rta_set)
  RET_VOID;
}

F_INST_INTERPRET(ea_get)
FI_INST_INTERPRET(ea_get)
{
  ACCESS_RTE;
  eattr *e = NULL;
@@ -453,7 +459,7 @@ F_INST_INTERPRET(ea_get)
  RET_VOID;
}

F_INST_INTERPRET(ea_set)
FI_INST_INTERPRET(ea_set)
{
  ACCESS_RTE;
  AI(1);
@@ -560,12 +566,12 @@ F_INST_INTERPRET(ea_set)
  RET_VOID;
}

F_INST_INTERPRET(pref_get) {
FI_INST_INTERPRET(pref_get) {
  ACCESS_RTE;
  RET(T_INT, i, (*f_rte)->pref);
}

F_INST_INTERPRET(pref_set) {
FI_INST_INTERPRET(pref_set) {
  ACCESS_RTE;
  AI(1);
  if (v1.type != T_INT)
@@ -577,7 +583,7 @@ F_INST_INTERPRET(pref_set) {
  RET_VOID;
}

F_INST_INTERPRET(length) {
FI_INST_INTERPRET(length) {
  AI(1);
  switch(v1.type) {
  case T_PREFIX: RET(T_INT, i, v1.val.px.len);
@@ -590,7 +596,7 @@ F_INST_INTERPRET(length) {
  RET_VOID;
}

F_INST_INTERPRET(ip) {
FI_INST_INTERPRET(ip) {
  AI(1);
  if (v1.type != T_PREFIX)
    runtime( "Prefix expected" );
@@ -598,7 +604,7 @@ F_INST_INTERPRET(ip) {
  RET(T_IP, px.ip, v1.val.px.ip);
}

F_INST_INTERPRET(as_path_first) {
FI_INST_INTERPRET(as_path_first) {
  AI(1);
  if (v1.type != T_PATH)
    runtime( "AS path expected" );
@@ -608,7 +614,7 @@ F_INST_INTERPRET(as_path_first) {
  RET(T_INT, i, as);
}

F_INST_INTERPRET(as_path_last) {
FI_INST_INTERPRET(as_path_last) {
  AI(1);
  if (v1.type != T_PATH)
    runtime( "AS path expected" );
@@ -618,7 +624,7 @@ F_INST_INTERPRET(as_path_last) {
  RET(T_INT, i, as);
}

F_INST_INTERPRET(as_path_last_nag) {
FI_INST_INTERPRET(as_path_last_nag) {
  AI(1);
  if (v1.type != T_PATH)
    runtime( "AS path expected" );
@@ -626,13 +632,13 @@ F_INST_INTERPRET(as_path_last_nag) {
  RET(T_INT, i, as_path_get_last_nonaggregated(v1.val.ad));
}

F_INST_INTERPRET(return) {
FI_INST_INTERPRET(return) {
  AI(1);
  v1.type |= T_RETURN;
  return v1;
}

F_INST_INTERPRET(call) {
FI_INST_INTERPRET(call) {
  AI(1);
  struct f_val res = interpret(what->a2.p);
  if (res.type == T_RETURN) /* Exception */
@@ -642,20 +648,20 @@ F_INST_INTERPRET(call) {
  return res;
}

F_INST_INTERPRET(clear_local_vars) {
  for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
FI_INST_INTERPRET(clear_local_vars) {
  for (struct symbol *sym = what->a1.p; sym != NULL; sym = sym->aux2)
    ((struct f_val *) sym->def)->type = T_VOID;
  RET_VOID;
}

F_INST_INTERPRET(switch) {
FI_INST_INTERPRET(switch) {
  AI(1);
  struct f_tree *t = find_tree(what->a2.p, v1);
  if (!t) {
    t = find_tree(what->a2.p, F_VAL_VOID);
    if (!t) {
      debug( "No else statement?\n");
      break;
      RET_VOID;
    }
  }

@@ -663,7 +669,7 @@ F_INST_INTERPRET(switch) {
  return interpret(t->data);
}

F_INST_INTERPRET(ip_mask) {
FI_INST_INTERPRET(ip_mask) {
  AI(1); AI(2);

  if (v2.type != T_INT)
@@ -675,11 +681,11 @@ F_INST_INTERPRET(ip_mask) {
  RET(T_IP, px.ip, ipa_and(mask, v1.val.px.ip));
}

F_INST_INTERPRET(empty) {
FI_INST_INTERPRET(empty) {
  RETA(ad, adata_empty(f_pool, 0));
}

F_INST_INTERPRET(path_prepend) {
FI_INST_INTERPRET(path_prepend) {
  AI(1); AI(2);
  if (v1.type != T_PATH)
    runtime("Can't prepend to non-path");
@@ -689,7 +695,7 @@ F_INST_INTERPRET(path_prepend) {
  RET(T_PATH, ad, as_path_prepend(f_pool, v1.val.ad, v2.val.i));
}

F_INST_INTERPRET(clist_add_del) {
FI_INST_INTERPRET(clist_add_del) {
  AI(1); AI(2);
  if (v1.type == T_PATH)
  {
@@ -814,7 +820,6 @@ F_INST_INTERPRET(clist_add_del) {
    else if (v2.type != T_LC)
      runtime("Can't add/delete non-lc");

    res.type = T_LCLIST;
    switch (what->aux)
    {
    case 'a':
@@ -844,7 +849,7 @@ F_INST_INTERPRET(clist_add_del) {
    runtime("Can't add/delete to non-[el]?clist");
}

F_INST_INTERPRET(roa_check) {
FI_INST_INTERPRET(roa_check) {
  u32 as;

  ip_addr ip;
@@ -893,3 +898,5 @@ F_INST_INTERPRET(roa_check) {
#undef RET_VOID
#undef RETA
#undef FI_INST_NUMERIC_BINARY

#endif