From: Maria Matejka Date: Mon, 30 May 2022 14:41:15 +0000 (+0200) Subject: Merge commit 'f2f3163f6c3fba7f9ef03640d7b2f6323873d2cc' into haugesund X-Git-Tag: v3.0-alpha1~171^2~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e16e1e4138cf10fd8f2508fa0e41e5ec98de6d53;p=thirdparty%2Fbird.git Merge commit 'f2f3163f6c3fba7f9ef03640d7b2f6323873d2cc' into haugesund --- e16e1e4138cf10fd8f2508fa0e41e5ec98de6d53 diff --cc filter/filter.c index 4545946f3,9bedb9381..124c99324 --- a/filter/filter.c +++ b/filter/filter.c @@@ -117,7 -131,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); ++ fs->rte->attrs = rta_do_cow(fs->rte->attrs, tmp_linpool); /* Re-cache the ea_list */ f_cache_eattrs(fs); @@@ -233,11 -247,25 +230,11 @@@ interpret(struct filter_state *fs, cons * @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, struct linpool *tmp_pool, int flags) -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; @@@ -285,7 -339,7 +281,7 @@@ */ 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) ++f_eval_rte(const struct f_line *expr, struct rte *rte) { filter_state = (struct filter_state) { .rte = rte, diff --cc filter/filter.h index 351174e47,43c044438..0c3486e0a --- a/filter/filter.h +++ b/filter/filter.h @@@ -51,10 -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); ++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 --cc nest/rt-show.c index 8c25375f1,7d02f52ed..26180a8d2 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@@ -208,10 -179,10 +208,10 @@@ rt_show_net(struct cli *c, net *n, stru } } - if (d->show_protocol && (d->show_protocol != e->src->proto)) + 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 --cc nest/rt-table.c index 0873cf42b,049b7a7f9..9c7fd5e4c --- a/nest/rt-table.c +++ b/nest/rt-table.c @@@ -735,7 -713,7 +735,7 @@@ rte_feed_obtain(net *n, struct rte **fe } static rte * - export_filter_(struct channel *c, rte *rt, linpool *pool, int silent) -export_filter(struct channel *c, rte *rt0, rte **rt_free, 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 -743,7 +765,7 @@@ } v = filter && ((filter == FILTER_REJECT) || - (f_run(filter, rt, pool, - (f_run(filter, &rt, ++ (f_run(filter, rt, (silent ? FF_SILENT : 0)) > F_ACCEPT)); if (v) { @@@ -791,53 -765,58 +791,47 @@@ 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, net *net, rte *new, rte *old, int refeed) +do_rt_notify(struct channel *c, const net_addr *net, rte *new, const rte *old) { struct proto *p = c->proto; - struct proto_stats *stats = &c->stats; + struct channel_export_stats *stats = &c->export_stats; - if (refeed && new) + if (c->refeeding && new) c->refeed_count++; - /* Apply export limit */ - struct channel_limit *l = &c->out_limit; - if (l->action && !old && new) - { - if (stats->exp_routes >= l->limit) - channel_notify_limit(c, l, PLD_OUT, stats->exp_routes); - - if (l->state == PLS_BLOCKED) + if (!old && new) + if (CHANNEL_LIMIT_PUSH(c, OUT)) { - stats->exp_updates_rejected++; - rte_trace_out(D_FILTERS, c, new, "rejected [limit]"); + stats->updates_rejected++; + channel_rte_trace_out(D_FILTERS, c, new, "rejected [limit]"); return; } - } + + if (!new && old) + CHANNEL_LIMIT_POP(c, OUT); /* Apply export table */ - struct rte *old_exported = NULL; + struct rte_storage *old_exported = NULL; if (c->out_table) { - if (!rte_update_out(c, net->n.addr, new, old, &old_exported, refeed)) + if (!rte_update_out(c, net, new, old, &old_exported)) + { + channel_rte_trace_out(D_ROUTES, c, new, "idempotent"); return; + } } - else if (c->out_filter == FILTER_ACCEPT) - old_exported = old; if (new) - stats->exp_updates_accepted++; + stats->updates_accepted++; else - stats->exp_withdraws_accepted++; + stats->withdraws_accepted++; if (old) - { bmap_clear(&c->export_map, old->id); - stats->exp_routes--; - } if (new) - { bmap_set(&c->export_map, new->id); - stats->exp_routes++; - } if (p->debug & D_ROUTES) { @@@ -967,33 -957,26 +961,33 @@@ rt_export_merged(struct channel *c, str if (!rte_is_valid(best0)) return NULL; - best = export_filter(c, best0, rt_free, silent); + /* Already rejected, no need to re-run the filter */ + if (!c->refeeding && bmap_test(&c->export_reject_map, best0->id)) + 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 */ + return NULL; - if (!best || !rte_is_reachable(best)) + if (!rte_is_reachable(best)) + /* Unreachable routes can't be merged */ return best; - for (rt0 = best0->next; rt0; rt0 = rt0->next) + for (uint i = 1; i < count; i++) { - if (!rte_mergable(best0, rt0)) + if (!rte_mergable(best0, feed[i])) continue; - rt = export_filter(c, rt0, &tmp, 1); + rte tmp0 = *feed[i]; - rte *tmp = export_filter_(c, &tmp0, pool, 1); ++ rte *tmp = export_filter(c, &tmp0, 1); - if (!rt) + if (!tmp || !rte_is_reachable(tmp)) continue; - if (rte_is_reachable(rt)) - nhs = nexthop_merge_rta(nhs, rt->attrs, pool, c->merge_limit); - - if (tmp) - rte_free(tmp); + nhs = nexthop_merge_rta(nhs, tmp->attrs, pool, c->merge_limit); } if (nhs) @@@ -1544,60 -1557,81 +1538,60 @@@ rte_update_direct(struct channel *c, co rte_update_lock(); if (new) { - /* Create a temporary table node */ - nn = alloca(sizeof(net) + n->length); - memset(nn, 0, sizeof(net) + n->length); - net_copy(nn->n.addr, n); + new->net = n; - new->net = nn; - new->sender = c; + int fr; - stats->imp_updates_received++; - if (!rte_validate(new)) + stats->updates_received++; + if (!rte_validate(c, new)) { - rte_trace_in(D_FILTERS, c, new, "invalid"); - stats->imp_updates_invalid++; - goto drop; + channel_rte_trace_in(D_FILTERS, c, new, "invalid"); + stats->updates_invalid++; + new = NULL; } - - if (filter == FILTER_REJECT) + 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->imp_updates_filtered++; - rte_trace_in(D_FILTERS, c, new, "filtered out"); + stats->updates_filtered++; + channel_rte_trace_in(D_FILTERS, c, new, "filtered out"); - if (! c->in_keep_filtered) - goto drop; - - /* new is a private copy, i could modify it */ - new->flags |= REF_FILTERED; + if (c->in_keep_filtered) + new->flags |= REF_FILTERED; + else + new = NULL; } - else if (filter) - { - int fr = f_run(filter, &new, 0); - if (fr > F_ACCEPT) - { - stats->imp_updates_filtered++; - rte_trace_in(D_FILTERS, c, new, "filtered out"); + } + else + stats->withdraws_received++; - if (! c->in_keep_filtered) - goto drop; + rte_import(&c->in_req, n, new, src); - new->flags |= REF_FILTERED; - } - } - if (!rta_is_cached(new->attrs)) /* Need to copy attributes */ - new->attrs = rta_lookup(new->attrs); - new->flags |= REF_COW; + rte_update_unlock(); +} + +void +rte_import(struct rt_import_request *req, const net_addr *n, rte *new, struct rte_src *src) +{ + struct rt_import_hook *hook = req->hook; + if (!hook) + return; + net *nn; + if (new) + { /* Use the actual struct network, not the dummy one */ - nn = net_get(c->table, n); - new->net = nn; + nn = net_get(hook->table, n); + new->net = nn->n.addr; + new->sender = hook; } - else + else if (!(nn = net_find(hook->table, n))) { - stats->imp_withdraws_received++; - - if (!(nn = net_find(c->table, n)) || !src) - { - stats->imp_withdraws_ignored++; - rte_update_unlock(); - return; - } + req->hook->stats.withdraws_ignored++; + return; } - recalc: /* And recalculate the best route */ - rte_recalculate(c, nn, new, src); - - rte_update_unlock(); - return; - - drop: - rte_free(new); - new = NULL; - if (nn = net_find(c->table, n)) - goto recalc; - - rte_update_unlock(); + rte_recalculate(hook, nn, new, src); } /* Independent call to rte_announce(), used from next hop @@@ -1651,10 -1688,14 +1645,10 @@@ rt_examine(rtable *t, net_addr *a, stru rte_update_lock(); /* Rest is stripped down export_filter() */ - int v = p->preexport ? p->preexport(p, rt) : 0; + 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); - /* Discard temporary rte */ - if (rt != n->routes) - rte_free(rt); - rte_update_unlock(); return v > 0; diff --cc proto/mrt/mrt.c index 7bcf28ba4,c595f2987..6a1869993 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@@ -524,9 -525,11 +524,9 @@@ mrt_rib_table_dump(struct mrt_table_dum continue; } - if (f_run(s->filter, &rt, 0) <= F_ACCEPT) - mrt_rib_table_entry(s, rt); - - if (rt != rt0) - rte_free(rt); + 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 --cc proto/static/static.c index fe0c77bc6,42febcd42..87d795eeb --- a/proto/static/static.c +++ b/proto/static/static.c @@@ -103,18 -101,25 +101,14 @@@ static_announce_rte(struct static_prot return; /* We skip rta_lookup() here */ - rte *e = rte_get_temp(a, src); - e->pflags = 0; + rte e0 = { .attrs = a, .src = src, .net = r->net, }, *e = &e0; + /* Evaluate the filter */ if (r->cmds) - f_eval_rte(r->cmds, e, static_lp); - { - /* Create a temporary table node */ - e->net = alloca(sizeof(net) + r->net->length); - memset(e->net, 0, sizeof(net) + r->net->length); - net_copy(e->net->n.addr, r->net); - - /* Evaluate the filter */ - f_eval_rte(r->cmds, &e); - - /* Remove the temporary node */ - e->net = NULL; - } ++ f_eval_rte(r->cmds, e); - rte_update2(p->p.main_channel, r->net, e, src); + rte_update(p->p.main_channel, r->net, e, src); r->state = SRS_CLEAN; - - if (r->cmds) - lp_flush(static_lp); - return; withdraw: