diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/f-inst.c | 10 | ||||
-rw-r--r-- | filter/filter.c | 113 | ||||
-rw-r--r-- | filter/filter.h | 4 |
3 files changed, 38 insertions, 89 deletions
diff --git a/filter/f-inst.c b/filter/f-inst.c index 23271ce7..caf473f0 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -529,13 +529,13 @@ { STATIC_ATTR; ACCESS_RTE; - struct rta *rta = (*fs->rte)->attrs; + struct rta *rta = fs->rte->attrs; switch (sa.sa_code) { case SA_GW: RESULT(sa.type, ip, rta->nh.gw); break; - case SA_NET: RESULT(sa.type, net, (*fs->rte)->net->n.addr); break; - case SA_PROTO: RESULT(sa.type, s, (*fs->rte)->src->proto->name); break; + case SA_NET: RESULT(sa.type, net, fs->rte->net); break; + case SA_PROTO: RESULT(sa.type, s, fs->rte->src->proto->name); break; case SA_DEST: RESULT(sa.type, i, rta->dest); break; case SA_IFNAME: RESULT(sa.type, s, rta->nh.iface ? rta->nh.iface->name : ""); break; case SA_IFINDEX: RESULT(sa.type, i, rta->nh.iface ? rta->nh.iface->index : 0); break; @@ -556,7 +556,7 @@ f_rta_cow(fs); { - struct rta *rta = (*fs->rte)->attrs; + struct rta *rta = fs->rte->attrs; switch (sa.sa_code) { @@ -564,7 +564,7 @@ { ip_addr ip = v1.val.ip; struct iface *ifa = ipa_is_link_local(ip) ? rta->nh.iface : NULL; - neighbor *n = neigh_find((*fs->rte)->src->proto, ip, ifa, 0); + neighbor *n = neigh_find(fs->rte->src->proto, ip, ifa, 0); if (!n || (n->scope == SCOPE_HOST)) runtime( "Invalid gw address" ); diff --git a/filter/filter.c b/filter/filter.c index 9bedb938..124c9932 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -74,10 +74,7 @@ struct filter_state { } stack; /* The route we are processing. This may be NULL to indicate no route available. */ - struct rte **rte; - - /* The old rta to be freed after filters are done. */ - struct rta *old_rta; + struct rte *rte; /* Cached pointer to ea_list */ struct ea_list **eattrs; @@ -99,15 +96,7 @@ void (*bt_assert_hook)(int result, const struct f_line_item *assert); static inline void f_cache_eattrs(struct filter_state *fs) { - fs->eattrs = &((*fs->rte)->attrs->eattrs); -} - -static inline void f_rte_cow(struct filter_state *fs) -{ - if (!((*fs->rte)->flags & REF_COW)) - return; - - *fs->rte = rte_cow(*fs->rte); + fs->eattrs = &(fs->rte->attrs->eattrs); } /* @@ -116,22 +105,16 @@ static inline void f_rte_cow(struct filter_state *fs) static void f_rta_cow(struct filter_state *fs) { - if (!rta_is_cached((*fs->rte)->attrs)) + if (!rta_is_cached(fs->rte->attrs)) return; - /* Prepare to modify rte */ - f_rte_cow(fs); - - /* Store old rta to free it later, it stores reference from rte_cow() */ - fs->old_rta = (*fs->rte)->attrs; - /* * Get shallow copy of rta. Fields eattrs and nexthops of rta are shared * with fs->old_rta (they will be copied when the cached rta will be obtained * 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, tmp_linpool); + fs->rte->attrs = rta_do_cow(fs->rte->attrs, tmp_linpool); /* Re-cache the ea_list */ f_cache_eattrs(fs); @@ -243,29 +226,15 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) /** * f_run - run a filter for a route * @filter: filter to run - * @rte: route being filtered, may be modified + * @rte: route being filtered, must be write-able * @tmp_pool: all filter allocations go from this pool * @flags: flags * - * If filter needs to modify the route, there are several - * posibilities. @rte might be read-only (with REF_COW flag), in that - * case rw copy is obtained by rte_cow() and @rte is replaced. If - * @rte is originally rw, it may be directly modified (and it is never - * copied). - * - * The returned rte may reuse the (possibly cached, cloned) rta, or - * (if rta was modified) contains a modified uncached rta, which - * uses parts allocated from @tmp_pool and parts shared from original - * rta. There is one exception - if @rte is rw but contains a cached - * rta and that is modified, rta in returned rte is also cached. - * - * Ownership of cached rtas is consistent with rte, i.e. - * if a new rte is returned, it has its own clone of cached rta - * (and cached rta of read-only source rte is intact), if rte is - * modified in place, old cached rta is possibly freed. + * If @rte->attrs is cached, the returned rte allocates a new rta on + * tmp_pool, otherwise the filters may modify it. */ enum filter_return -f_run(const struct filter *filter, struct rte **rte, int flags) +f_run(const struct filter *filter, struct rte *rte, int flags) { if (filter == FILTER_ACCEPT) return F_ACCEPT; @@ -273,7 +242,6 @@ f_run(const struct filter *filter, struct rte **rte, int flags) if (filter == FILTER_REJECT) return F_REJECT; - int rte_cow = ((*rte)->flags & REF_COW); DBG( "Running filter `%s'...", filter->name ); /* Initialize the filter state */ @@ -289,32 +257,6 @@ f_run(const struct filter *filter, struct rte **rte, int flags) /* Run the interpreter itself */ enum filter_return fret = interpret(&filter_state, filter->root, NULL); - if (filter_state.old_rta) { - /* - * Cached rta was modified and filter_state->rte contains now an uncached one, - * sharing some part with the cached one. The cached rta should - * be freed (if rte was originally COW, filter_state->old_rta is a clone - * obtained during rte_cow()). - * - * This also implements the exception mentioned in f_run() - * description. The reason for this is that rta reuses parts of - * filter_state->old_rta, and these may be freed during rta_free(filter_state->old_rta). - * This is not the problem if rte was COW, because original rte - * also holds the same rta. - */ - if (!rte_cow) { - /* Cache the new attrs */ - (*filter_state.rte)->attrs = rta_lookup((*filter_state.rte)->attrs); - - /* Drop cached ea_list pointer */ - filter_state.eattrs = NULL; - } - - /* Uncache the old attrs and drop the pointer as it is invalid now. */ - rta_free(filter_state.old_rta); - filter_state.old_rta = NULL; - } - /* Process the filter output, log it and return */ if (fret < F_ACCEPT) { if (!(filter_state.flags & FF_SILENT)) @@ -339,7 +281,7 @@ 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) +f_eval_rte(const struct f_line *expr, struct rte *rte) { filter_state = (struct filter_state) { .rte = rte, @@ -349,8 +291,7 @@ f_eval_rte(const struct f_line *expr, struct rte **rte) LOG_BUFFER_INIT(filter_state.buf); - ASSERT(!((*rte)->flags & REF_COW)); - ASSERT(!rta_is_cached((*rte)->attrs)); + ASSERT(!rta_is_cached(rte->attrs)); return interpret(&filter_state, expr, NULL); } @@ -475,6 +416,23 @@ filter_commit(struct config *new, struct config *old) } } +void channel_filter_dump(const struct filter *f) +{ + if (f == FILTER_ACCEPT) + debug(" ALL"); + else if (f == FILTER_REJECT) + debug(" NONE"); + else if (f == FILTER_UNDEF) + debug(" UNDEF"); + else if (f->sym) { + ASSERT(f->sym->filter == f); + debug(" named filter %s", f->sym->name); + } else { + debug("\n"); + f_dump_line(f->root, 2); + } +} + void filters_dump_all(void) { struct symbol *sym; @@ -494,19 +452,10 @@ void filters_dump_all(void) struct channel *c; WALK_LIST(c, sym->proto->proto->channels) { debug(" Channel %s (%s) IMPORT", c->name, net_label[c->net_type]); - if (c->in_filter == FILTER_ACCEPT) - debug(" ALL\n"); - else if (c->in_filter == FILTER_REJECT) - debug(" NONE\n"); - else if (c->in_filter == FILTER_UNDEF) - debug(" UNDEF\n"); - else if (c->in_filter->sym) { - ASSERT(c->in_filter->sym->filter == c->in_filter); - debug(" named filter %s\n", c->in_filter->sym->name); - } else { - debug("\n"); - f_dump_line(c->in_filter->root, 2); - } + channel_filter_dump(c->in_filter); + debug(" EXPORT", c->name, net_label[c->net_type]); + channel_filter_dump(c->out_filter); + debug("\n"); } } } diff --git a/filter/filter.h b/filter/filter.h index 0273ef15..3f2e62eb 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -51,8 +51,8 @@ struct filter { struct rte; -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); +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, buffer *buf); |