mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Merge commit '2c13759136951ef0e70a3e3c2b2d3c9a387f7ed9' into haugesund
This commit is contained in:
		@@ -35,6 +35,7 @@ struct config {
 | 
			
		||||
  u32 proto_default_debug;		/* Default protocol debug mask */
 | 
			
		||||
  u32 proto_default_mrtdump;		/* Default protocol mrtdump mask */
 | 
			
		||||
  u32 channel_default_debug;		/* Default channel debug mask */
 | 
			
		||||
  u16 filter_vstk, filter_estk;		/* Filter stack depth */
 | 
			
		||||
  struct timeformat tf_route;		/* Time format for 'show route' */
 | 
			
		||||
  struct timeformat tf_proto;		/* Time format for 'show protocol' */
 | 
			
		||||
  struct timeformat tf_log;		/* Time format for the logfile */
 | 
			
		||||
 
 | 
			
		||||
@@ -290,7 +290,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 | 
			
		||||
	MIN, MAX,
 | 
			
		||||
	EMPTY,
 | 
			
		||||
	FILTER, WHERE, EVAL, ATTRIBUTE,
 | 
			
		||||
	BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT)
 | 
			
		||||
	BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT, STACKS)
 | 
			
		||||
 | 
			
		||||
%nonassoc THEN
 | 
			
		||||
%nonassoc ELSE
 | 
			
		||||
@@ -314,6 +314,12 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 | 
			
		||||
 | 
			
		||||
CF_GRAMMAR
 | 
			
		||||
 | 
			
		||||
conf: FILTER STACKS expr expr ';' {
 | 
			
		||||
  new_config->filter_vstk = $3;
 | 
			
		||||
  new_config->filter_estk = $4;
 | 
			
		||||
 }
 | 
			
		||||
 ;
 | 
			
		||||
 | 
			
		||||
conf: filter_def ;
 | 
			
		||||
filter_def:
 | 
			
		||||
   FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ m4_divert(-1)m4_dnl
 | 
			
		||||
#
 | 
			
		||||
#	101	content of per-inst struct
 | 
			
		||||
#	102	constructor arguments
 | 
			
		||||
#	110	constructor attributes
 | 
			
		||||
#	103	constructor body
 | 
			
		||||
#	104	dump line item content
 | 
			
		||||
#		(there may be nothing in dump-line content and
 | 
			
		||||
@@ -45,6 +46,7 @@ m4_divert(-1)m4_dnl
 | 
			
		||||
#	Here are macros to allow you to _divert to the right directions.
 | 
			
		||||
m4_define(FID_STRUCT_IN, `m4_divert(101)')
 | 
			
		||||
m4_define(FID_NEW_ARGS, `m4_divert(102)')
 | 
			
		||||
m4_define(FID_NEW_ATTRIBUTES, `m4_divert(110)')
 | 
			
		||||
m4_define(FID_NEW_BODY, `m4_divert(103)')
 | 
			
		||||
m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
 | 
			
		||||
m4_define(FID_LINEARIZE_BODY, `m4_divert(105)')
 | 
			
		||||
@@ -106,15 +108,18 @@ FID_STRUCT_IN()m4_dnl
 | 
			
		||||
      struct f_inst * f$1;
 | 
			
		||||
FID_NEW_ARGS()m4_dnl
 | 
			
		||||
  , struct f_inst * f$1
 | 
			
		||||
FID_NEW_ATTRIBUTES()m4_dnl
 | 
			
		||||
NONNULL(m4_eval($1+1))
 | 
			
		||||
FID_NEW_BODY()m4_dnl
 | 
			
		||||
whati->f$1 = f$1;
 | 
			
		||||
for (const struct f_inst *child = f$1; child; child = child->next) {
 | 
			
		||||
  what->size += child->size;
 | 
			
		||||
const struct f_inst *child$1 = f$1;
 | 
			
		||||
do {
 | 
			
		||||
  what->size += child$1->size;
 | 
			
		||||
FID_IFCONST([[
 | 
			
		||||
  if (child->fi_code != FI_CONSTANT)
 | 
			
		||||
  if (child$1->fi_code != FI_CONSTANT)
 | 
			
		||||
    constargs = 0;
 | 
			
		||||
]])
 | 
			
		||||
}
 | 
			
		||||
} while (child$1 = child$1->next);
 | 
			
		||||
FID_LINEARIZE_BODY
 | 
			
		||||
pos = linearize(dest, whati->f$1, pos);
 | 
			
		||||
FID_INTERPRET_BODY()')
 | 
			
		||||
@@ -190,6 +195,7 @@ FID_INTERPRET_BODY()')
 | 
			
		||||
#	that was needed in the former implementation.
 | 
			
		||||
m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()')
 | 
			
		||||
m4_define(LINEX_, `do {
 | 
			
		||||
  if (fstk->ecnt + 1 >= fstk->elen) runtime("Filter execution stack overflow");
 | 
			
		||||
  fstk->estk[fstk->ecnt].pos = 0;
 | 
			
		||||
  fstk->estk[fstk->ecnt].line = $1;
 | 
			
		||||
  fstk->estk[fstk->ecnt].ventry = fstk->vcnt;
 | 
			
		||||
@@ -227,7 +233,7 @@ FID_INTERPRET_BODY()')
 | 
			
		||||
#	state the result and put it to the right place.
 | 
			
		||||
m4_define(RESULT, `RESULT_TYPE([[$1]]) RESULT_([[$1]],[[$2]],[[$3]])')
 | 
			
		||||
m4_define(RESULT_, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])')
 | 
			
		||||
m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; fstk->vcnt++; } while (0)]],
 | 
			
		||||
m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; f_vcnt_check_overflow(1); fstk->vcnt++; } while (0)]],
 | 
			
		||||
[[return fi_constant(what, $1)]])')
 | 
			
		||||
m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])')
 | 
			
		||||
 | 
			
		||||
@@ -309,7 +315,9 @@ m4_undivert(107)m4_dnl
 | 
			
		||||
FID_NEW()m4_dnl				 Constructor and interpreter code together
 | 
			
		||||
FID_HIC(
 | 
			
		||||
[[m4_dnl				 Public declaration of constructor in H file
 | 
			
		||||
struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
 | 
			
		||||
struct f_inst *
 | 
			
		||||
m4_undivert(110)m4_dnl
 | 
			
		||||
f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
 | 
			
		||||
m4_undivert(102)m4_dnl
 | 
			
		||||
);]],
 | 
			
		||||
[[m4_dnl				 The one case in The Big Switch inside interpreter
 | 
			
		||||
@@ -321,7 +329,9 @@ m4_undivert(102)m4_dnl
 | 
			
		||||
  break;
 | 
			
		||||
]],
 | 
			
		||||
[[m4_dnl				 Constructor itself
 | 
			
		||||
struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
 | 
			
		||||
struct f_inst *
 | 
			
		||||
m4_undivert(110)m4_dnl
 | 
			
		||||
f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code
 | 
			
		||||
m4_undivert(102)m4_dnl
 | 
			
		||||
)
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
@@ -1103,6 +1103,7 @@
 | 
			
		||||
    curline.vbase = curline.ventry;
 | 
			
		||||
 | 
			
		||||
    /* Storage for local variables */
 | 
			
		||||
    f_vcnt_check_overflow(sym->function->vars);
 | 
			
		||||
    memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars);
 | 
			
		||||
    fstk->vcnt += sym->function->vars;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -50,30 +50,28 @@ enum f_exception {
 | 
			
		||||
  FE_RETURN = 0x1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct filter_stack {
 | 
			
		||||
  /* Value stack for execution */
 | 
			
		||||
#define F_VAL_STACK_MAX	4096
 | 
			
		||||
  uint vcnt;				/* Current value stack size; 0 for empty */
 | 
			
		||||
  uint ecnt;				/* Current execute stack size; 0 for empty */
 | 
			
		||||
 | 
			
		||||
  struct f_val vstk[F_VAL_STACK_MAX];	/* The stack itself */
 | 
			
		||||
 | 
			
		||||
  /* Instruction stack for execution */
 | 
			
		||||
#define F_EXEC_STACK_MAX 4096
 | 
			
		||||
  struct {
 | 
			
		||||
    const struct f_line *line;		/* The line that is being executed */
 | 
			
		||||
    uint pos;				/* Instruction index in the line */
 | 
			
		||||
    uint ventry;			/* Value stack depth on entry */
 | 
			
		||||
    uint vbase;				/* Where to index variable positions from */
 | 
			
		||||
    enum f_exception emask;		/* Exception mask */
 | 
			
		||||
  } estk[F_EXEC_STACK_MAX];
 | 
			
		||||
struct filter_exec_stack {
 | 
			
		||||
  const struct f_line *line;		/* The line that is being executed */
 | 
			
		||||
  uint pos;				/* Instruction index in the line */
 | 
			
		||||
  uint ventry;				/* Value stack depth on entry */
 | 
			
		||||
  uint vbase;				/* Where to index variable positions from */
 | 
			
		||||
  enum f_exception emask;		/* Exception mask */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Internal filter state, to be allocated on stack when executing filters */
 | 
			
		||||
struct filter_state {
 | 
			
		||||
  /* Stacks needed for execution */
 | 
			
		||||
  struct filter_stack *stack;
 | 
			
		||||
  struct filter_stack {
 | 
			
		||||
    /* Current filter stack depth */
 | 
			
		||||
 | 
			
		||||
    /* Value stack */
 | 
			
		||||
    uint vcnt, vlen;
 | 
			
		||||
    struct f_val *vstk;
 | 
			
		||||
 | 
			
		||||
    /* Instruction stack for execution */
 | 
			
		||||
    uint ecnt, elen;
 | 
			
		||||
    struct filter_exec_stack *estk;
 | 
			
		||||
  } stack;
 | 
			
		||||
 | 
			
		||||
  /* The route we are processing. This may be NULL to indicate no route available. */
 | 
			
		||||
  struct rte **rte;
 | 
			
		||||
@@ -95,10 +93,13 @@ struct filter_state {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
_Thread_local static struct filter_state filter_state;
 | 
			
		||||
_Thread_local static struct filter_stack filter_stack;
 | 
			
		||||
 | 
			
		||||
void (*bt_assert_hook)(int result, const struct f_line_item *assert);
 | 
			
		||||
 | 
			
		||||
#define _f_stack_init(fs, px, def) ((fs).stack.px##stk = alloca(sizeof(*(fs).stack.px##stk) * ((fs).stack.px##len = (config && config->filter_##px##stk) ? config->filter_##px##stk : (def))))
 | 
			
		||||
 | 
			
		||||
#define f_stack_init(fs) ( _f_stack_init(fs, v, 128), _f_stack_init(fs, e, 128) )
 | 
			
		||||
 | 
			
		||||
static inline void f_cache_eattrs(struct filter_state *fs)
 | 
			
		||||
{
 | 
			
		||||
  fs->eattrs = &((*fs->rte)->attrs->eattrs);
 | 
			
		||||
@@ -163,15 +164,17 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
 | 
			
		||||
  ASSERT(line->args == 0);
 | 
			
		||||
 | 
			
		||||
  /* Initialize the filter stack */
 | 
			
		||||
  struct filter_stack *fstk = fs->stack;
 | 
			
		||||
  struct filter_stack *fstk = &fs->stack;
 | 
			
		||||
 | 
			
		||||
  fstk->vcnt = line->vars;
 | 
			
		||||
  memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars);
 | 
			
		||||
 | 
			
		||||
  /* The same as with the value stack. Not resetting the stack for performance reasons. */
 | 
			
		||||
  fstk->ecnt = 1;
 | 
			
		||||
  fstk->estk[0].line = line;
 | 
			
		||||
  fstk->estk[0].pos = 0;
 | 
			
		||||
  fstk->estk[0] = (struct filter_exec_stack) {
 | 
			
		||||
    .line = line,
 | 
			
		||||
    .pos = 0,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#define curline fstk->estk[fstk->ecnt-1]
 | 
			
		||||
 | 
			
		||||
@@ -191,6 +194,8 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
 | 
			
		||||
#define v2 vv(1)
 | 
			
		||||
#define v3 vv(2)
 | 
			
		||||
 | 
			
		||||
#define f_vcnt_check_overflow(n) do { if (fstk->vcnt + n >= fstk->vlen) runtime("Filter execution stack overflow"); } while (0)
 | 
			
		||||
 | 
			
		||||
#define runtime(fmt, ...) do { \
 | 
			
		||||
  if (!(fs->flags & FF_SILENT)) \
 | 
			
		||||
    log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
 | 
			
		||||
@@ -276,12 +281,13 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
 | 
			
		||||
 | 
			
		||||
  /* Initialize the filter state */
 | 
			
		||||
  filter_state = (struct filter_state) {
 | 
			
		||||
    .stack = &filter_stack,
 | 
			
		||||
    .rte = rte,
 | 
			
		||||
    .pool = tmp_pool,
 | 
			
		||||
    .flags = flags,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  f_stack_init(filter_state);
 | 
			
		||||
 | 
			
		||||
  LOG_BUFFER_INIT(filter_state.buf);
 | 
			
		||||
 | 
			
		||||
  /* Run the interpreter itself */
 | 
			
		||||
@@ -340,11 +346,12 @@ enum filter_return
 | 
			
		||||
f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool)
 | 
			
		||||
{
 | 
			
		||||
  filter_state = (struct filter_state) {
 | 
			
		||||
    .stack = &filter_stack,
 | 
			
		||||
    .rte = rte,
 | 
			
		||||
    .pool = tmp_pool,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  f_stack_init(filter_state);
 | 
			
		||||
 | 
			
		||||
  LOG_BUFFER_INIT(filter_state.buf);
 | 
			
		||||
 | 
			
		||||
  ASSERT(!((*rte)->flags & REF_COW));
 | 
			
		||||
@@ -363,10 +370,11 @@ enum filter_return
 | 
			
		||||
f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
 | 
			
		||||
{
 | 
			
		||||
  filter_state = (struct filter_state) {
 | 
			
		||||
    .stack = &filter_stack,
 | 
			
		||||
    .pool = tmp_pool,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  f_stack_init(filter_state);
 | 
			
		||||
 | 
			
		||||
  LOG_BUFFER_INIT(filter_state.buf);
 | 
			
		||||
 | 
			
		||||
  enum filter_return fret = interpret(&filter_state, expr, pres);
 | 
			
		||||
@@ -383,10 +391,11 @@ f_eval_int(const struct f_line *expr)
 | 
			
		||||
{
 | 
			
		||||
  /* Called independently in parse-time to eval expressions */
 | 
			
		||||
  filter_state = (struct filter_state) {
 | 
			
		||||
    .stack = &filter_stack,
 | 
			
		||||
    .pool = cfg_mem,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  f_stack_init(filter_state);
 | 
			
		||||
 | 
			
		||||
  struct f_val val;
 | 
			
		||||
 | 
			
		||||
  LOG_BUFFER_INIT(filter_state.buf);
 | 
			
		||||
 
 | 
			
		||||
@@ -272,6 +272,9 @@ no_partial:
 | 
			
		||||
      goto okay;
 | 
			
		||||
    }
 | 
			
		||||
  h = alloc_page();
 | 
			
		||||
#ifdef POISON
 | 
			
		||||
  memset(h, 0xba, get_page_size());
 | 
			
		||||
#endif
 | 
			
		||||
  ASSERT_DIE(SL_GET_HEAD(h) == h);
 | 
			
		||||
  memset(h, 0, s->head_size);
 | 
			
		||||
  add_head(&s->partial_heads, &h->n);
 | 
			
		||||
@@ -327,7 +330,12 @@ sl_free(slab *s, void *oo)
 | 
			
		||||
    {
 | 
			
		||||
      rem_node(&h->n);
 | 
			
		||||
      if (s->num_empty_heads >= MAX_EMPTY_HEADS)
 | 
			
		||||
      {
 | 
			
		||||
#ifdef POISON
 | 
			
		||||
	memset(h, 0xde, get_page_size());
 | 
			
		||||
#endif
 | 
			
		||||
	free_page(h);
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  add_head(&s->empty_heads, &h->n);
 | 
			
		||||
 
 | 
			
		||||
@@ -522,7 +522,10 @@ static inline void
 | 
			
		||||
add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
 | 
			
		||||
{
 | 
			
		||||
  struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
 | 
			
		||||
 | 
			
		||||
  n->n = (node) {};
 | 
			
		||||
  add_tail(&ifa->nbma_list, NODE n);
 | 
			
		||||
 | 
			
		||||
  n->ip = src->ip;
 | 
			
		||||
  n->eligible = src->eligible;
 | 
			
		||||
  n->found = found;
 | 
			
		||||
 
 | 
			
		||||
@@ -309,22 +309,15 @@ die(const char *msg, ...)
 | 
			
		||||
void
 | 
			
		||||
debug(const char *msg, ...)
 | 
			
		||||
{
 | 
			
		||||
#define MAX_DEBUG_BUFSIZE       65536
 | 
			
		||||
#define MAX_DEBUG_BUFSIZE 16384
 | 
			
		||||
  va_list args;
 | 
			
		||||
  static uint bufsize = 4096;
 | 
			
		||||
  static char *buf = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!buf)
 | 
			
		||||
    buf = mb_alloc(&root_pool, bufsize);
 | 
			
		||||
  char buf[MAX_DEBUG_BUFSIZE];
 | 
			
		||||
 | 
			
		||||
  va_start(args, msg);
 | 
			
		||||
  if (dbgf)
 | 
			
		||||
    {
 | 
			
		||||
      while (bvsnprintf(buf, bufsize, msg, args) < 0)
 | 
			
		||||
        if (bufsize >= MAX_DEBUG_BUFSIZE)
 | 
			
		||||
          bug("Extremely long debug output, split it.");
 | 
			
		||||
        else
 | 
			
		||||
          buf = mb_realloc(buf, (bufsize *= 2));
 | 
			
		||||
      if (bvsnprintf(buf, MAX_DEBUG_BUFSIZE, msg, args) < 0)
 | 
			
		||||
	bug("Extremely long debug output, split it.");
 | 
			
		||||
 | 
			
		||||
      fputs(buf, dbgf);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -240,7 +240,7 @@ bt_log_result(int result, u64 time, const char *fmt, va_list argptr)
 | 
			
		||||
  printf("%s\n", result_str);
 | 
			
		||||
 | 
			
		||||
  if (do_die && !result)
 | 
			
		||||
    abort();
 | 
			
		||||
    exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u64
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user