diff options
author | Maria Matejka <mq@ucw.cz> | 2019-02-26 16:44:24 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2019-02-26 16:44:24 +0100 |
commit | f249d0b84c840242a084966999a1d228c603b431 (patch) | |
tree | 7e366d772a68306b20c8c71e34febc747d9a8fe5 /filter | |
parent | 0d12aa48363802e751d3b9a4afd6eb090592d7a3 (diff) |
Filters: comparison of functions and filters caching
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 2 | ||||
-rw-r--r-- | filter/f-inst.h | 4 | ||||
-rw-r--r-- | filter/f-util.c | 9 | ||||
-rw-r--r-- | filter/filter.c | 46 | ||||
-rw-r--r-- | filter/filter.h | 4 | ||||
-rw-r--r-- | filter/test-reconf-begin.conf | 23 | ||||
-rw-r--r-- | filter/test-reconf-end.conf | 23 |
7 files changed, 99 insertions, 12 deletions
diff --git a/filter/config.Y b/filter/config.Y index 5ec226f0..a7618987 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -470,7 +470,7 @@ filter_def: FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } filter_body { 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; cf_pop_scope(); diff --git a/filter/f-inst.h b/filter/f-inst.h index 5b397a5d..4b42c57c 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -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); /* Filter structures for execution */ -struct f_line; - /* Line of instructions to be unconditionally executed one after another */ struct f_line { uint len; /* Line length */ - u16 args; /* Function: Args required */ + u8 args; /* Function: Args required */ struct f_line_item items[0]; /* The items themselves */ }; diff --git a/filter/f-util.c b/filter/f-util.c index 85f5d1c4..35944b2c 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -24,10 +24,10 @@ filter_name(const struct filter *filter) return "ACCEPT"; else if (filter == FILTER_REJECT) return "REJECT"; - else if (!filter->name) + else if (!filter->sym) return "(unnamed)"; else - return filter->name; + return filter->sym->name; } 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 = { .fi_code = FI_CONDITION, .lineno = ifs->lino, - .size = 3, + .size = 3 + where->size, .i_FI_CONDITION = { .f1 = where, .f2 = &acc, @@ -62,8 +62,7 @@ struct filter *f_new_where(const struct f_inst *where) }, }; - struct filter *f = cfg_alloc(sizeof(struct filter)); - f->name = NULL; + struct filter *f = cfg_allocz(sizeof(struct filter)); f->root = f_postfixify(&i); return f; } diff --git a/filter/filter.c b/filter/filter.c index ee5d5426..3be7343c 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -293,7 +293,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i 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); + 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; } 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 || new == FILTER_ACCEPT || new == FILTER_REJECT) return 0; - return f_same(new->root, old->root); + + if ((!old->sym) && (!new->sym)) + 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; + } } diff --git a/filter/filter.h b/filter/filter.h index 26faeaa3..d919cc74 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -47,7 +47,7 @@ struct f_val; /* The filter encapsulating structure to be pointed-to from outside */ struct f_line; struct filter { - char *name; + struct symbol *sym; 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 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_REJECT ((void *) 1) #define FILTER_UNDEF ((void *) 2) /* Used in BGP */ diff --git a/filter/test-reconf-begin.conf b/filter/test-reconf-begin.conf new file mode 100644 index 00000000..aeed007f --- /dev/null +++ b/filter/test-reconf-begin.conf @@ -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; +} diff --git a/filter/test-reconf-end.conf b/filter/test-reconf-end.conf new file mode 100644 index 00000000..19164825 --- /dev/null +++ b/filter/test-reconf-end.conf @@ -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; +} |