summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/confbase.Y6
-rw-r--r--filter/config.Y2
-rw-r--r--filter/data.c72
-rw-r--r--filter/data.h4
-rw-r--r--filter/f-inst.c6
-rw-r--r--filter/filter.c29
-rw-r--r--filter/filter.h6
-rw-r--r--filter/filter_test.c2
-rw-r--r--lib/attrs.h2
-rw-r--r--nest/cmds.c2
-rw-r--r--nest/rt-show.c4
-rw-r--r--nest/rt-table.c18
-rw-r--r--proto/mrt/mrt.c2
-rw-r--r--proto/static/static.c11
-rw-r--r--sysdep/unix/krt.c2
15 files changed, 110 insertions, 58 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 3fdacb12..a81560dc 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -152,9 +152,9 @@ conf: definition ;
definition:
DEFINE symbol '=' term ';' {
- struct f_val *val = cfg_allocz(sizeof(struct f_val));
- if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
- cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
+ struct f_val val;
+ if (f_eval(f_linearize($4), &val) > F_RETURN) cf_error("Runtime error");
+ cf_define_symbol($2, SYM_CONSTANT | val.type, val, lp_val_copy(cfg_mem, &val));
}
;
diff --git a/filter/config.Y b/filter/config.Y
index 22981945..92656f7c 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -529,7 +529,7 @@ set_atom:
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
- if (f_eval(f_linearize($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
+ if (f_eval(f_linearize($2), &($$)) > F_RETURN) cf_error("Runtime error");
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
}
| CF_SYM_KNOWN {
diff --git a/filter/data.c b/filter/data.c
index 381448fa..425dfdd3 100644
--- a/filter/data.c
+++ b/filter/data.c
@@ -602,3 +602,75 @@ val_dump(const struct f_val *v) {
return val_dump_buffer;
}
+
+struct f_val *
+lp_val_copy(struct linpool *lp, const struct f_val *v)
+{
+ switch (v->type)
+ {
+ case T_VOID:
+ case T_BOOL:
+ case T_INT:
+ case T_IP:
+ case T_PAIR:
+ case T_QUAD:
+ case T_EC:
+ case T_LC:
+ case T_RD:
+ case T_ENUM:
+ case T_PATH_MASK_ITEM:
+ /* These aren't embedded but there is no need to copy them */
+ case T_SET:
+ case T_PREFIX_SET:
+ case T_PATH_MASK:
+ case T_IFACE:
+ {
+ struct f_val *out = lp_alloc(lp, sizeof(*out));
+ *out = *v;
+ return out;
+ }
+
+ case T_NET:
+ {
+ struct {
+ struct f_val val;
+ net_addr net[0];
+ } *out = lp_alloc(lp, sizeof(*out) + v->val.net->length);
+ out->val = *v;
+ out->val.val.net = out->net;
+ net_copy(out->net, v->val.net);
+ return &out->val;
+ }
+
+ case T_STRING:
+ {
+ uint len = strlen(v->val.s);
+ struct {
+ struct f_val val;
+ char buf[0];
+ } *out = lp_alloc(lp, sizeof(*out) + len + 1);
+ out->val = *v;
+ out->val.val.s = out->buf;
+ memcpy(out->buf, v->val.s, len+1);
+ return &out->val;
+ }
+
+ case T_PATH:
+ case T_CLIST:
+ case T_ECLIST:
+ case T_LCLIST:
+ {
+ struct {
+ struct f_val val;
+ struct adata ad;
+ } *out = lp_alloc(lp, sizeof(*out) + v->val.ad->length);
+ out->val = *v;
+ out->val.val.ad = &out->ad;
+ memcpy(&out->ad, v->val.ad, v->val.ad->length);
+ return &out->val;
+ }
+
+ default:
+ bug("Unknown type in value copy: %d", v->type);
+ }
+}
diff --git a/filter/data.h b/filter/data.h
index 9ffa1b61..cba47d6a 100644
--- a/filter/data.h
+++ b/filter/data.h
@@ -213,6 +213,8 @@ void val_format(const struct f_val *v, buffer *buf);
char *val_format_str(struct linpool *lp, const struct f_val *v);
const char *val_dump(const struct f_val *v);
+struct f_val *lp_val_copy(struct linpool *lp, const struct f_val *v);
+
static inline int val_is_ip4(const struct f_val *v)
{ return (v->type == T_IP) && ipa_is_ip4(v->val.ip); }
int val_in_range(const struct f_val *v1, const struct f_val *v2);
@@ -249,6 +251,6 @@ static inline const struct f_val *f_get_empty(btype t)
}
}
-enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres);
+enum filter_return f_eval(const struct f_line *expr, struct f_val *pres);
#endif
diff --git a/filter/f-inst.c b/filter/f-inst.c
index c8e597e9..eb0141b6 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -696,7 +696,7 @@
DYNAMIC_ATTR;
ARG_TYPE(1, da.type);
{
- struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));
+ struct ea_list *l = tmp_alloc(sizeof(struct ea_list) + sizeof(eattr));
l->next = NULL;
l->flags = EALF_SORTED;
@@ -718,7 +718,7 @@
break;
case T_IP:
- l->attrs[0].u.ptr = lp_store_adata(fs->pool, &v1.val.ip, sizeof(ip_addr));
+ l->attrs[0].u.ptr = tmp_store_adata(&v1.val.ip, sizeof(ip_addr));
break;
default:
@@ -739,7 +739,7 @@
ACCESS_EATTRS;
f_rta_cow(fs);
- ea_unset_attr(fs->eattrs, fs->pool, 1, da.ea_code);
+ ea_unset_attr(fs->eattrs, tmp_linpool, 1, da.ea_code);
}
INST(FI_LENGTH, 1, 1) { /* Get length of */
diff --git a/filter/filter.c b/filter/filter.c
index 4545946f..124c9932 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -79,9 +79,6 @@ struct filter_state {
/* Cached pointer to ea_list */
struct ea_list **eattrs;
- /* Linpool for adata allocation */
- struct linpool *pool;
-
/* Buffer for log output */
struct buffer buf;
@@ -117,7 +114,7 @@ f_rta_cow(struct filter_state *fs)
* at the end of f_run()), also the lock of hostentry is inherited (we
* suppose hostentry is not changed by filters).
*/
- fs->rte->attrs = rta_do_cow(fs->rte->attrs, fs->pool);
+ fs->rte->attrs = rta_do_cow(fs->rte->attrs, tmp_linpool);
/* Re-cache the ea_list */
f_cache_eattrs(fs);
@@ -185,8 +182,8 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
return F_ERROR; \
} while(0)
-#define falloc(size) lp_alloc(fs->pool, size)
-#define fpool fs->pool
+#define falloc(size) tmp_alloc(size)
+#define fpool tmp_linpool
#define ACCESS_EATTRS do { if (!fs->eattrs) f_cache_eattrs(fs); } while (0)
@@ -237,7 +234,7 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
* tmp_pool, otherwise the filters may modify it.
*/
enum filter_return
-f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags)
+f_run(const struct filter *filter, struct rte *rte, int flags)
{
if (filter == FILTER_ACCEPT)
return F_ACCEPT;
@@ -250,7 +247,6 @@ f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, in
/* Initialize the filter state */
filter_state = (struct filter_state) {
.rte = rte,
- .pool = tmp_pool,
.flags = flags,
};
@@ -285,11 +281,10 @@ f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, in
*/
enum filter_return
-f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool)
+f_eval_rte(const struct f_line *expr, struct rte *rte)
{
filter_state = (struct filter_state) {
.rte = rte,
- .pool = tmp_pool,
};
f_stack_init(filter_state);
@@ -308,11 +303,9 @@ f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool)
* @pres: here the output will be stored
*/
enum filter_return
-f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres)
+f_eval(const struct f_line *expr, struct f_val *pres)
{
- filter_state = (struct filter_state) {
- .pool = tmp_pool,
- };
+ filter_state = (struct filter_state) {};
f_stack_init(filter_state);
@@ -331,9 +324,7 @@ uint
f_eval_int(const struct f_line *expr)
{
/* Called independently in parse-time to eval expressions */
- filter_state = (struct filter_state) {
- .pool = cfg_mem,
- };
+ filter_state = (struct filter_state) {};
f_stack_init(filter_state);
@@ -354,10 +345,10 @@ f_eval_int(const struct f_line *expr)
* f_eval_buf - get a value of a term and print it to the supplied buffer
*/
enum filter_return
-f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf)
+f_eval_buf(const struct f_line *expr, buffer *buf)
{
struct f_val val;
- enum filter_return fret = f_eval(expr, tmp_pool, &val);
+ enum filter_return fret = f_eval(expr, &val);
if (fret <= F_RETURN)
val_format(&val, buf);
return fret;
diff --git a/filter/filter.h b/filter/filter.h
index 351174e4..0c3486e0 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -51,10 +51,10 @@ struct filter {
struct rte;
-enum filter_return f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags);
-enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool);
+enum filter_return f_run(const struct filter *filter, struct rte *rte, int flags);
+enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte);
uint f_eval_int(const struct f_line *expr);
-enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf);
+enum filter_return f_eval_buf(const struct f_line *expr, buffer *buf);
const char *filter_name(const struct filter *filter);
int filter_same(const struct filter *new, const struct filter *old);
diff --git a/filter/filter_test.c b/filter/filter_test.c
index e8e8b747..63764964 100644
--- a/filter/filter_test.c
+++ b/filter/filter_test.c
@@ -46,7 +46,7 @@ run_function(const void *arg)
if (t->cmp)
return t->result == f_same(t->fn, t->cmp);
- enum filter_return fret = f_eval(t->fn, tmp_linpool, NULL);
+ enum filter_return fret = f_eval(t->fn, NULL);
return (fret < F_REJECT);
}
diff --git a/lib/attrs.h b/lib/attrs.h
index fcb70230..d2638f3f 100644
--- a/lib/attrs.h
+++ b/lib/attrs.h
@@ -37,6 +37,8 @@ lp_store_adata(struct linpool *pool, const void *buf, uint len)
return ad;
}
+#define tmp_store_adata(buf, len) lp_store_adata(tmp_linpool, buf, len)
+
static inline int adata_same(const struct adata *a, const struct adata *b)
{ return (a->length == b->length && !memcmp(a->data, b->data, a->length)); }
diff --git a/nest/cmds.c b/nest/cmds.c
index 3e59cb6f..99a7bbfe 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -133,7 +133,7 @@ cmd_eval(const struct f_line *expr)
buffer buf;
LOG_BUFFER_INIT(buf);
- if (f_eval_buf(expr, this_cli->parser_pool, &buf) > F_RETURN)
+ if (f_eval_buf(expr, &buf) > F_RETURN)
{
cli_msg(8008, "runtime error");
return;
diff --git a/nest/rt-show.c b/nest/rt-show.c
index 8c25375f..26180a8d 100644
--- a/nest/rt-show.c
+++ b/nest/rt-show.c
@@ -198,7 +198,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
* command may change the export filter and do not update routes.
*/
int do_export = (ic > 0) ||
- (f_run(ec->out_filter, &e, c->show_pool, FF_SILENT) <= F_ACCEPT);
+ (f_run(ec->out_filter, &e, FF_SILENT) <= F_ACCEPT);
if (do_export != (d->export_mode == RSEM_EXPORT))
goto skip;
@@ -211,7 +211,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
if (d->show_protocol && (d->show_protocol != e.src->proto))
goto skip;
- if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
+ if (f_run(d->filter, &e, 0) > F_ACCEPT)
goto skip;
if (d->stats < 2)
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 0873cf42..9c7fd5e4 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -735,7 +735,7 @@ rte_feed_obtain(net *n, struct rte **feed, uint count)
}
static rte *
-export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
+export_filter(struct channel *c, rte *rt, int silent)
{
struct proto *p = c->proto;
const struct filter *filter = c->out_filter;
@@ -765,7 +765,7 @@ export_filter_(struct channel *c, rte *rt, linpool *pool, int silent)
}
v = filter && ((filter == FILTER_REJECT) ||
- (f_run(filter, rt, pool,
+ (f_run(filter, rt,
(silent ? FF_SILENT : 0)) > F_ACCEPT));
if (v)
{
@@ -791,12 +791,6 @@ reject_noset:
return NULL;
}
-static inline rte *
-export_filter(struct channel *c, rte *rt, int silent)
-{
- return export_filter_(c, rt, rte_update_pool, silent);
-}
-
static void
do_rt_notify(struct channel *c, const net_addr *net, rte *new, const rte *old)
{
@@ -972,7 +966,7 @@ rt_export_merged(struct channel *c, struct rte **feed, uint count, linpool *pool
return NULL;
rloc = *best0;
- best = export_filter_(c, &rloc, pool, silent);
+ best = export_filter(c, &rloc, silent);
if (!best)
/* Best route doesn't pass the filter */
@@ -988,7 +982,7 @@ rt_export_merged(struct channel *c, struct rte **feed, uint count, linpool *pool
continue;
rte tmp0 = *feed[i];
- rte *tmp = export_filter_(c, &tmp0, pool, 1);
+ rte *tmp = export_filter(c, &tmp0, 1);
if (!tmp || !rte_is_reachable(tmp))
continue;
@@ -1556,7 +1550,7 @@ rte_update_direct(struct channel *c, const net_addr *n, rte *new, struct rte_src
new = NULL;
}
else if ((filter == FILTER_REJECT) ||
- ((fr = f_run(filter, new, rte_update_pool, 0)) > F_ACCEPT))
+ ((fr = f_run(filter, new, 0)) > F_ACCEPT))
{
stats->updates_filtered++;
channel_rte_trace_in(D_FILTERS, c, new, "filtered out");
@@ -1653,7 +1647,7 @@ rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filte
/* Rest is stripped down export_filter() */
int v = c->proto->preexport ? c->proto->preexport(c, &rt) : 0;
if (v == RIC_PROCESS)
- v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
+ v = (f_run(filter, &rt, FF_SILENT) <= F_ACCEPT);
rte_update_unlock();
diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c
index 7bcf28ba..6a186999 100644
--- a/proto/mrt/mrt.c
+++ b/proto/mrt/mrt.c
@@ -525,7 +525,7 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
}
rte e = rt->rte;
- if (f_run(s->filter, &e, s->linpool, 0) <= F_ACCEPT)
+ if (f_run(s->filter, &e, 0) <= F_ACCEPT)
mrt_rib_table_entry(s, &e);
lp_flush(s->linpool);
diff --git a/proto/static/static.c b/proto/static/static.c
index fe0c77bc..87d795ee 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -47,8 +47,6 @@
#include "static.h"
-static linpool *static_lp;
-
static inline struct rte_src * static_get_source(struct static_proto *p, uint i)
{ return i ? rt_get_source(&p->p, i) : p->p.main_source; }
@@ -107,14 +105,10 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
/* Evaluate the filter */
if (r->cmds)
- f_eval_rte(r->cmds, e, static_lp);
+ f_eval_rte(r->cmds, e);
rte_update(p->p.main_channel, r->net, e, src);
r->state = SRS_CLEAN;
-
- if (r->cmds)
- lp_flush(static_lp);
-
return;
withdraw:
@@ -474,9 +468,6 @@ static_start(struct proto *P)
struct static_config *cf = (void *) P->cf;
struct static_route *r;
- if (!static_lp)
- static_lp = lp_new(&root_pool);
-
if (p->igp_table_ip4)
rt_lock_table(p->igp_table_ip4);
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index f8e8d7b3..cf3b5575 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -603,7 +603,7 @@ krt_export_net(struct krt_proto *p, net *net)
if (filter == FILTER_ACCEPT)
goto accept;
- if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT)
+ if (f_run(filter, &rt, FF_SILENT) > F_ACCEPT)
goto reject;