mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Filters: comparison of functions and filters caching
This commit is contained in:
parent
0d12aa4836
commit
f249d0b84c
@ -561,6 +561,8 @@ cf_new_symbol(const byte *c)
|
|||||||
|
|
||||||
HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s);
|
HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s);
|
||||||
|
|
||||||
|
add_tail(&(new_config->symbols), &(s->n));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,7 +578,7 @@ cf_new_symbol(const byte *c)
|
|||||||
* signify no match.
|
* signify no match.
|
||||||
*/
|
*/
|
||||||
struct symbol *
|
struct symbol *
|
||||||
cf_find_symbol(struct config *cfg, const byte *c)
|
cf_find_symbol(const struct config *cfg, const byte *c)
|
||||||
{
|
{
|
||||||
struct symbol *s;
|
struct symbol *s;
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@ config_alloc(const char *name)
|
|||||||
memcpy(ndup, name, nlen);
|
memcpy(ndup, name, nlen);
|
||||||
|
|
||||||
init_list(&c->tests);
|
init_list(&c->tests);
|
||||||
|
init_list(&c->symbols);
|
||||||
c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
|
c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
|
||||||
c->pool = p;
|
c->pool = p;
|
||||||
c->mem = l;
|
c->mem = l;
|
||||||
@ -258,6 +259,8 @@ config_do_commit(struct config *c, int type)
|
|||||||
if (old_config)
|
if (old_config)
|
||||||
old_config->obstacle_count++;
|
old_config->obstacle_count++;
|
||||||
|
|
||||||
|
DBG("filter_commit\n");
|
||||||
|
filter_commit(c, old_config);
|
||||||
DBG("sysdep_commit\n");
|
DBG("sysdep_commit\n");
|
||||||
int force_restart = sysdep_commit(c, old_config);
|
int force_restart = sysdep_commit(c, old_config);
|
||||||
DBG("global_commit\n");
|
DBG("global_commit\n");
|
||||||
|
@ -24,6 +24,7 @@ struct config {
|
|||||||
list tables; /* Configured routing tables (struct rtable_config) */
|
list tables; /* Configured routing tables (struct rtable_config) */
|
||||||
list logfiles; /* Configured log files (sysdep) */
|
list logfiles; /* Configured log files (sysdep) */
|
||||||
list tests; /* Configured unit tests (f_bt_test_suite) */
|
list tests; /* Configured unit tests (f_bt_test_suite) */
|
||||||
|
list symbols; /* Configured symbols in config order */
|
||||||
|
|
||||||
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
|
int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */
|
||||||
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
|
char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
|
||||||
@ -103,6 +104,7 @@ void cfg_copy_list(list *dest, list *src, unsigned node_size);
|
|||||||
extern int (*cf_read_hook)(byte *buf, uint max, int fd);
|
extern int (*cf_read_hook)(byte *buf, uint max, int fd);
|
||||||
|
|
||||||
struct symbol {
|
struct symbol {
|
||||||
|
node n; /* In list of symbols in config */
|
||||||
struct symbol *next;
|
struct symbol *next;
|
||||||
struct sym_scope *scope;
|
struct sym_scope *scope;
|
||||||
int class; /* SYM_* */
|
int class; /* SYM_* */
|
||||||
@ -167,7 +169,7 @@ int cf_lex(void);
|
|||||||
void cf_lex_init(int is_cli, struct config *c);
|
void cf_lex_init(int is_cli, struct config *c);
|
||||||
void cf_lex_unwind(void);
|
void cf_lex_unwind(void);
|
||||||
|
|
||||||
struct symbol *cf_find_symbol(struct config *cfg, const byte *c);
|
struct symbol *cf_find_symbol(const struct config *cfg, const byte *c);
|
||||||
|
|
||||||
struct symbol *cf_get_symbol(const byte *c);
|
struct symbol *cf_get_symbol(const byte *c);
|
||||||
struct symbol *cf_default_name(char *template, int *counter);
|
struct symbol *cf_default_name(char *template, int *counter);
|
||||||
|
@ -470,7 +470,7 @@ filter_def:
|
|||||||
FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }
|
FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }
|
||||||
filter_body {
|
filter_body {
|
||||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
*f = (struct filter) { .name = $2->name, .root = $4 };
|
*f = (struct filter) { .sym = $2, .root = $4 };
|
||||||
$2->filter = f;
|
$2->filter = f;
|
||||||
|
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
|
@ -31,12 +31,10 @@ const char *f_instruction_name(enum f_instruction_code fi);
|
|||||||
struct f_inst *f_clear_local_vars(struct f_inst *decls);
|
struct f_inst *f_clear_local_vars(struct f_inst *decls);
|
||||||
|
|
||||||
/* Filter structures for execution */
|
/* Filter structures for execution */
|
||||||
struct f_line;
|
|
||||||
|
|
||||||
/* Line of instructions to be unconditionally executed one after another */
|
/* Line of instructions to be unconditionally executed one after another */
|
||||||
struct f_line {
|
struct f_line {
|
||||||
uint len; /* Line length */
|
uint len; /* Line length */
|
||||||
u16 args; /* Function: Args required */
|
u8 args; /* Function: Args required */
|
||||||
struct f_line_item items[0]; /* The items themselves */
|
struct f_line_item items[0]; /* The items themselves */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@ filter_name(const struct filter *filter)
|
|||||||
return "ACCEPT";
|
return "ACCEPT";
|
||||||
else if (filter == FILTER_REJECT)
|
else if (filter == FILTER_REJECT)
|
||||||
return "REJECT";
|
return "REJECT";
|
||||||
else if (!filter->name)
|
else if (!filter->sym)
|
||||||
return "(unnamed)";
|
return "(unnamed)";
|
||||||
else
|
else
|
||||||
return filter->name;
|
return filter->sym->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void f_inst_next(struct f_inst *first, const struct f_inst *append)
|
void f_inst_next(struct f_inst *first, const struct f_inst *append)
|
||||||
@ -54,7 +54,7 @@ struct filter *f_new_where(const struct f_inst *where)
|
|||||||
struct f_inst i = {
|
struct f_inst i = {
|
||||||
.fi_code = FI_CONDITION,
|
.fi_code = FI_CONDITION,
|
||||||
.lineno = ifs->lino,
|
.lineno = ifs->lino,
|
||||||
.size = 3,
|
.size = 3 + where->size,
|
||||||
.i_FI_CONDITION = {
|
.i_FI_CONDITION = {
|
||||||
.f1 = where,
|
.f1 = where,
|
||||||
.f2 = &acc,
|
.f2 = &acc,
|
||||||
@ -62,8 +62,7 @@ struct filter *f_new_where(const struct f_inst *where)
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
struct filter *f = cfg_allocz(sizeof(struct filter));
|
||||||
f->name = NULL;
|
|
||||||
f->root = f_postfixify(&i);
|
f->root = f_postfixify(&i);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
|
|||||||
|
|
||||||
if (fret < F_ACCEPT) {
|
if (fret < F_ACCEPT) {
|
||||||
if (!(fs.flags & FF_SILENT))
|
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);
|
log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter_name(filter));
|
||||||
return F_ERROR;
|
return F_ERROR;
|
||||||
}
|
}
|
||||||
DBG( "done (%u)\n", res.val.i );
|
DBG( "done (%u)\n", res.val.i );
|
||||||
@ -378,5 +378,47 @@ filter_same(const struct filter *new, const struct filter *old)
|
|||||||
if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
|
if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
|
||||||
new == FILTER_ACCEPT || new == FILTER_REJECT)
|
new == FILTER_ACCEPT || new == FILTER_REJECT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((!old->sym) && (!new->sym))
|
||||||
return f_same(new->root, old->root);
|
return f_same(new->root, old->root);
|
||||||
|
|
||||||
|
if ((!old->sym) || (!new->sym))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(old->sym->name, new->sym->name))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return new->sym->flags & SYM_FLAG_SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* filter_commit - do filter comparisons on all the named functions and filters
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
filter_commit(const struct config *new, const struct config *old)
|
||||||
|
{
|
||||||
|
if (!old)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct symbol *sym, *osym;
|
||||||
|
WALK_LIST(sym, new->symbols)
|
||||||
|
switch (sym->class) {
|
||||||
|
case SYM_FUNCTION:
|
||||||
|
if ((osym = cf_find_symbol(old, sym->name)) &&
|
||||||
|
(osym->class == SYM_FUNCTION) &&
|
||||||
|
f_same(sym->function, osym->function))
|
||||||
|
sym->flags |= SYM_FLAG_SAME;
|
||||||
|
else
|
||||||
|
sym->flags &= ~SYM_FLAG_SAME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYM_FILTER:
|
||||||
|
if ((osym = cf_find_symbol(old, sym->name)) &&
|
||||||
|
(osym->class == SYM_FILTER) &&
|
||||||
|
f_same(sym->filter->root, osym->filter->root))
|
||||||
|
sym->flags |= SYM_FLAG_SAME;
|
||||||
|
else
|
||||||
|
sym->flags &= ~SYM_FLAG_SAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ struct f_val;
|
|||||||
/* The filter encapsulating structure to be pointed-to from outside */
|
/* The filter encapsulating structure to be pointed-to from outside */
|
||||||
struct f_line;
|
struct f_line;
|
||||||
struct filter {
|
struct filter {
|
||||||
char *name;
|
struct symbol *sym;
|
||||||
const struct f_line *root;
|
const struct f_line *root;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,6 +62,8 @@ const char *filter_name(const struct filter *filter);
|
|||||||
int filter_same(const struct filter *new, const struct filter *old);
|
int filter_same(const struct filter *new, const struct filter *old);
|
||||||
int f_same(const struct f_line *f1, const struct f_line *f2);
|
int f_same(const struct f_line *f1, const struct f_line *f2);
|
||||||
|
|
||||||
|
void filter_commit(const struct config *new, const struct config *old);
|
||||||
|
|
||||||
#define FILTER_ACCEPT NULL
|
#define FILTER_ACCEPT NULL
|
||||||
#define FILTER_REJECT ((void *) 1)
|
#define FILTER_REJECT ((void *) 1)
|
||||||
#define FILTER_UNDEF ((void *) 2) /* Used in BGP */
|
#define FILTER_UNDEF ((void *) 2) /* Used in BGP */
|
||||||
|
23
filter/test-reconf-begin.conf
Normal file
23
filter/test-reconf-begin.conf
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
router id 1.1.1.1;
|
||||||
|
protocol device {}
|
||||||
|
|
||||||
|
function a() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function b() {
|
||||||
|
return a();
|
||||||
|
}
|
||||||
|
|
||||||
|
function c() {
|
||||||
|
return b();
|
||||||
|
}
|
||||||
|
|
||||||
|
filter d {
|
||||||
|
if c() then accept; else reject;
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol static {
|
||||||
|
ipv4 { import filter d; };
|
||||||
|
route 10.0.0.0/24 unreachable;
|
||||||
|
}
|
23
filter/test-reconf-end.conf
Normal file
23
filter/test-reconf-end.conf
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
router id 1.1.1.1;
|
||||||
|
protocol device {}
|
||||||
|
|
||||||
|
function a() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function b() {
|
||||||
|
return a();
|
||||||
|
}
|
||||||
|
|
||||||
|
function c() {
|
||||||
|
return b();
|
||||||
|
}
|
||||||
|
|
||||||
|
filter d {
|
||||||
|
if c() then accept; else reject;
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol static {
|
||||||
|
ipv4 { import filter d; };
|
||||||
|
route 10.0.0.0/24 unreachable;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user