From: Jan Maria Matejka Date: Wed, 24 Jan 2018 15:00:42 +0000 (+0100) Subject: Nest: Dropping global rte_update_pool X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a5557ea8f2a0c4e9373ba46f416401038bedf16;p=thirdparty%2Fbird.git Nest: Dropping global rte_update_pool --- diff --git a/nest/route.h b/nest/route.h index 2ec1dc7fa..c0590f6e6 100644 --- a/nest/route.h +++ b/nest/route.h @@ -295,7 +295,7 @@ rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); /* rte_update() moved to protocol.h to avoid dependency conflicts */ -int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); +int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter, struct linpool *pool); rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent); void rt_refresh_begin(rtable *t, struct channel *c); void rt_refresh_end(rtable *t, struct channel *c); @@ -626,12 +626,12 @@ void rta_dump_all(void); void rta_show(struct cli *, rta *); struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep); -void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls); +void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls, struct linpool *lp); static inline void -rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, mpls_label_stack *mls) +rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr gw, ip_addr ll, mpls_label_stack *mls, struct linpool *lp) { - rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls); + rta_apply_hostentry(a, rt_get_hostentry(tab, gw, ll, dep), mls, lp); } /* diff --git a/nest/rt-table.c b/nest/rt-table.c index 036b34c47..5f6f5720d 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -46,7 +46,6 @@ pool *rt_table_pool; static slab *rte_slab; -static linpool *rte_update_pool; static list routing_tables; @@ -393,8 +392,8 @@ rte_trace_out(uint flag, struct proto *p, rte *e, char *msg) rte_trace(p, e, '<', msg); } -static rte * -export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent) +rte * +export_filter(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent) { struct proto *p = c->proto; struct filter *filter = c->out_filter; @@ -450,12 +449,6 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si return NULL; } -static inline rte * -export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent) -{ - return export_filter_(c, rt0, rt_free, rte_update_pool, silent); -} - static void do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed) { @@ -534,7 +527,7 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed) } static void -rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed) +rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, struct linpool *lp, int refeed) { struct proto *p = c->proto; @@ -569,10 +562,10 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed) */ if (new) - new = export_filter(c, new, &new_free, 0); + new = export_filter(c, new, &new_free, lp, 0); if (old && !(refeed || (old->lastmod <= c->last_tx_filter_change))) - old = export_filter(c, old, &old_free, 1); + old = export_filter(c, old, &old_free, lp, 1); if (!new && !old) { @@ -605,7 +598,7 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed) } static void -rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_changed, rte *before_old, int feed) +rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_changed, rte *before_old, struct linpool *lp, int feed) { // struct proto *p = c->proto; @@ -631,7 +624,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang /* First, find the new_best route - first accepted by filters */ for (r=net->routes; rte_is_valid(r); r=r->next) { - if (new_best = export_filter(c, r, &new_free, 0)) + if (new_best = export_filter(c, r, &new_free, lp, 0)) break; /* Note if we walked around the position of old_changed route */ @@ -692,7 +685,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang /* First case */ if (old_meet) - if (old_best = export_filter(c, old_changed, &old_free, 1)) + if (old_best = export_filter(c, old_changed, &old_free, lp, 1)) goto found; /* Second case */ @@ -710,11 +703,11 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang /* Fourth case */ for (r=r->next; rte_is_valid(r); r=r->next) { - if (old_best = export_filter(c, r, &old_free, 1)) + if (old_best = export_filter(c, r, &old_free, lp, 1)) goto found; if (r == before_old) - if (old_best = export_filter(c, old_changed, &old_free, 1)) + if (old_best = export_filter(c, old_changed, &old_free, lp, 1)) goto found; } @@ -750,7 +743,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int if (!rte_is_valid(best0)) return NULL; - best = export_filter_(c, best0, rt_free, pool, silent); + best = export_filter(c, best0, rt_free, pool, silent); if (!best || !rte_is_reachable(best)) return best; @@ -760,7 +753,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int if (!rte_mergable(best0, rt0)) continue; - rt = export_filter_(c, rt0, &tmp, pool, 1); + rt = export_filter(c, rt0, &tmp, pool, 1); if (!rt) continue; @@ -792,7 +785,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int static void rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed, - rte *new_best, rte*old_best, int refeed) + rte *new_best, rte *old_best, struct linpool *lp, int refeed) { // struct proto *p = c->proto; @@ -811,10 +804,10 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed if ((new_best == old_best) && !refeed) { new_changed = rte_mergable(new_best, new_changed) ? - export_filter(c, new_changed, &new_changed_free, 1) : NULL; + export_filter(c, new_changed, &new_changed_free, lp, 1) : NULL; old_changed = rte_mergable(old_best, old_changed) ? - export_filter(c, old_changed, &old_changed_free, 1) : NULL; + export_filter(c, old_changed, &old_changed_free, lp, 1) : NULL; if (!new_changed && !old_changed) return; @@ -827,12 +820,12 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed /* Prepare new merged route */ if (new_best) - new_best = rt_export_merged(c, net, &new_best_free, rte_update_pool, 0); + new_best = rt_export_merged(c, net, &new_best_free, lp, 0); /* Prepare old merged route (without proper merged next hops) */ /* There are some issues with running filter on old route - see rt_notify_basic() */ if (old_best && !refeed) - old_best = export_filter(c, old_best, &old_best_free, 1); + old_best = export_filter(c, old_best, &old_best_free, lp, 1); if (new_best || old_best) do_rt_notify(c, net, new_best, old_best, refeed); @@ -883,7 +876,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed */ static void rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, - rte *new_best, rte *old_best, rte *before_old) + rte *new_best, rte *old_best, rte *before_old, struct linpool *lp) { if (!rte_is_valid(new)) new = NULL; @@ -911,11 +904,11 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, if (c->ra_mode == type) if (type == RA_ACCEPTED) - rt_notify_accepted(c, net, new, old, before_old, 0); + rt_notify_accepted(c, net, new, old, before_old, lp, 0); else if (type == RA_MERGED) - rt_notify_merged(c, net, new, old, new_best, old_best, 0); + rt_notify_merged(c, net, new, old, new_best, old_best, lp, 0); else - rt_notify_basic(c, net, new, old, 0); + rt_notify_basic(c, net, new, old, lp, 0); } } @@ -994,7 +987,7 @@ rte_same(rte *x, rte *y) static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); } static void -rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) +rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src, struct linpool *lp) { struct proto *p = c->proto; struct rtable *table = c->table; @@ -1229,12 +1222,12 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) } /* Propagate the route change */ - rte_announce(table, RA_ANY, net, new, old, NULL, NULL, NULL); + rte_announce(table, RA_ANY, net, new, old, NULL, NULL, NULL, lp); if (net->routes != old_best) - rte_announce(table, RA_OPTIMAL, net, net->routes, old_best, NULL, NULL, NULL); + rte_announce(table, RA_OPTIMAL, net, net->routes, old_best, NULL, NULL, NULL, lp); if (table->config->sorted) - rte_announce(table, RA_ACCEPTED, net, new, old, NULL, NULL, before_old); - rte_announce(table, RA_MERGED, net, new, old, net->routes, old_best, NULL); + rte_announce(table, RA_ACCEPTED, net, new, old, NULL, NULL, before_old, lp); + rte_announce(table, RA_MERGED, net, new, old, net->routes, old_best, NULL, lp); if (!net->routes && (table->gc_counter++ >= table->config->gc_max_ops) && @@ -1250,21 +1243,6 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) rte_free_quick(old); } -static int rte_update_nest_cnt; /* Nesting counter to allow recursive updates */ - -static inline void -rte_update_lock(void) -{ - rte_update_nest_cnt++; -} - -static inline void -rte_update_unlock(void) -{ - if (!--rte_update_nest_cnt) - lp_flush(rte_update_pool); -} - static inline void rte_hide_dummy_routes(net *net, rte **dummy) { @@ -1333,12 +1311,12 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) struct proto *p = c->proto; struct proto_stats *stats = &c->stats; struct filter *filter = c->in_filter; + struct linpool *lp = lp_new(c->proto->pool, 1024); rte *dummy = NULL; net *nn; ASSERT(c->channel_state == CS_UP); - rte_update_lock(); if (new) { nn = net_get(c->table, n); @@ -1370,11 +1348,11 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) } else { - rte_make_tmp_attrs(&new, rte_update_pool); + rte_make_tmp_attrs(&new, lp); if (filter && (filter != FILTER_REJECT)) { ea_list *oldea = new->attrs->eattrs; - int fr = f_run(filter, &new, rte_update_pool, 0); + int fr = f_run(filter, &new, lp, 0); if (fr > F_ACCEPT) { stats->imp_updates_filtered++; @@ -1400,16 +1378,16 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) if (!(nn = net_find(c->table, n)) || !src) { stats->imp_withdraws_ignored++; - rte_update_unlock(); - return; + goto done; } } recalc: rte_hide_dummy_routes(nn, &dummy); - rte_recalculate(c, nn, new, src); + rte_recalculate(c, nn, new, src, lp); rte_unhide_dummy_routes(nn, &dummy); - rte_update_unlock(); + done: + rfree(lp); return; drop: @@ -1418,32 +1396,11 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) goto recalc; } -/* Independent call to rte_announce(), used from next hop - recalculation, outside of rte_update(). new must be non-NULL */ -static inline void -rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old, - rte *new_best, rte *old_best) -{ - rte_update_lock(); - rte_announce(tab, type, net, new, old, new_best, old_best, NULL); - rte_update_unlock(); -} - -static inline void -rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collection */ -{ - rte_update_lock(); - rte_recalculate(old->sender, old->net, NULL, old->attrs->src); - rte_update_unlock(); -} - /* Modify existing route by protocol hook, used for long-lived graceful restart */ static inline void -rte_modify(rte *old) +rte_modify(rte *old, struct linpool *lp) { - rte_update_lock(); - - rte *new = old->sender->proto->rte_modify(old, rte_update_pool); + rte *new = old->sender->proto->rte_modify(old, lp); if (new != old) { if (new) @@ -1453,15 +1410,13 @@ rte_modify(rte *old) new->flags = (old->flags & ~REF_MODIFY) | REF_COW; } - rte_recalculate(old->sender, old->net, new, old->attrs->src); + rte_recalculate(old->sender, old->net, new, old->attrs->src, lp); } - - rte_update_unlock(); } /* Check rtable for best route to given net whether it would be exported do p */ int -rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) +rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter, struct linpool *lp) { net *n = net_find(t, a); rte *rt = n ? n->routes : NULL; @@ -1469,20 +1424,16 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) if (!rte_is_valid(rt)) return 0; - rte_update_lock(); - /* Rest is stripped down export_filter() */ - rte_make_tmp_attrs(&rt, rte_update_pool); - int v = p->import_control ? p->import_control(p, &rt, rte_update_pool) : 0; + rte_make_tmp_attrs(&rt, lp); + int v = p->import_control ? p->import_control(p, &rt, lp) : 0; if (v == RIC_PROCESS) - v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT); + v = (f_run(filter, &rt, lp, FF_SILENT) <= F_ACCEPT); /* Discard temporary rte */ if (rt != n->routes) rte_free(rt); - rte_update_unlock(); - return v > 0; } @@ -1699,7 +1650,6 @@ rt_init(void) { rta_init(); rt_table_pool = rp_new(&root_pool, "Routing tables"); - rte_update_pool = lp_new_default(rt_table_pool); rte_slab = sl_new(rt_table_pool, sizeof(rte)); init_list(&routing_tables); } @@ -1764,7 +1714,10 @@ again: return; } - rte_discard(e); + /* Non-filtered route deletion */ + struct linpool *lp = lp_new(e->sender->proto->pool, 1024); + rte_recalculate(e->sender, e->net, NULL, e->attrs->src, lp); + rfree(lp); limit--; goto rescan; @@ -1779,7 +1732,9 @@ again: return; } - rte_modify(e); + struct linpool *lp = lp_new(e->sender->proto->pool, 1024); + rte_modify(e, lp); + rfree(lp); limit--; goto rescan; @@ -1853,7 +1808,7 @@ rta_next_hop_outdated(rta *a) } void -rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls) +rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls, struct linpool *lp) { a->hostentry = he; a->dest = he->dest; @@ -1888,7 +1843,7 @@ no_nexthop: else { nhr = nhp; - nhp = (nhp ? (nhp->next = lp_allocz(rte_update_pool, NEXTHOP_MAX_SIZE)) : &(a->nh)); + nhp = (nhp ? (nhp->next = lp_allocz(lp, NEXTHOP_MAX_SIZE)) : &(a->nh)); } nhp->iface = nh->iface; @@ -1933,7 +1888,7 @@ no_nexthop: } static inline rte * -rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) +rt_next_hop_update_rte(rtable *tab UNUSED, rte *old, struct linpool *lp) { rta *a = alloca(RTA_MAX_SIZE); memcpy(a, old->attrs, rta_size(old->attrs)); @@ -1941,7 +1896,7 @@ rt_next_hop_update_rte(rtable *tab UNUSED, rte *old) mpls_label_stack mls = { .len = a->nh.labels_orig }; memcpy(mls.stack, &a->nh.label[a->nh.labels - mls.len], mls.len * sizeof(u32)); - rta_apply_hostentry(a, old->attrs->hostentry, &mls); + rta_apply_hostentry(a, old->attrs->hostentry, &mls, lp); a->aflags = 0; rte *e = sl_alloc(rte_slab); @@ -1962,13 +1917,15 @@ rt_next_hop_update_net(rtable *tab, net *n) if (!old_best) return 0; + struct linpool *lp = lp_new(rt_table_pool, 1024); /* TODO: screw it */ + for (k = &n->routes; e = *k; k = &e->next) if (rta_next_hop_outdated(e->attrs)) { - new = rt_next_hop_update_rte(tab, e); + new = rt_next_hop_update_rte(tab, e, lp); *k = new; - rte_announce_i(tab, RA_ANY, n, new, e, NULL, NULL); + rte_announce(tab, RA_ANY, n, new, e, NULL, NULL, NULL, lp); rte_trace_in(D_ROUTES, new->sender->proto, new, "updated"); /* Call a pre-comparison hook */ @@ -1986,7 +1943,10 @@ rt_next_hop_update_net(rtable *tab, net *n) } if (!count) - return 0; + { + rfree(lp); + return 0; + } /* Find the new best route */ new_best = NULL; @@ -2008,12 +1968,14 @@ rt_next_hop_update_net(rtable *tab, net *n) /* Announce the new best route */ if (new != old_best) { - rte_announce_i(tab, RA_OPTIMAL, n, new, old_best, NULL, NULL); + rte_announce(tab, RA_OPTIMAL, n, new, old_best, NULL, NULL, NULL, lp); rte_trace_in(D_ROUTES, new->sender->proto, new, "updated [best]"); } /* FIXME: Better announcement of merged routes */ - rte_announce_i(tab, RA_MERGED, n, new, old_best, new, old_best); + rte_announce(tab, RA_MERGED, n, new, old_best, new, old_best, NULL, lp); + + rfree(lp); if (free_old_best) rte_free_quick(old_best); @@ -2194,14 +2156,14 @@ rt_commit(struct config *new, struct config *old) static inline void do_feed_channel(struct channel *c, net *n, rte *e) { - rte_update_lock(); + struct linpool *lp = lp_new(c->proto->pool, 1024); if (c->ra_mode == RA_ACCEPTED) - rt_notify_accepted(c, n, e, NULL, NULL, c->refeeding ? 2 : 1); + rt_notify_accepted(c, n, e, NULL, NULL, lp, c->refeeding ? 2 : 1); else if (c->ra_mode == RA_MERGED) - rt_notify_merged(c, n, NULL, NULL, e, c->refeeding ? e : NULL, c->refeeding); + rt_notify_merged(c, n, NULL, NULL, e, c->refeeding ? e : NULL, lp, c->refeeding); else /* RA_BASIC */ - rt_notify_basic(c, n, e, c->refeeding ? e : NULL, c->refeeding); - rte_update_unlock(); + rt_notify_basic(c, n, e, c->refeeding ? e : NULL, lp, c->refeeding); + rfree(lp); } /** diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ed1db04b2..dc65ec9e9 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -832,7 +832,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll) s->hostentry = rt_get_hostentry(tab, gw, ll, c->c.table); if (!s->mpls) - rta_apply_hostentry(a, s->hostentry, NULL); + rta_apply_hostentry(a, s->hostentry, NULL, s->pool); /* With MPLS, hostentry is applied later in bgp_apply_mpls_labels() */ } @@ -866,7 +866,7 @@ bgp_apply_mpls_labels(struct bgp_parse_state *s, rta *a, u32 *labels, uint lnum) ms.len = lnum; memcpy(ms.stack, labels, 4*lnum); - rta_apply_hostentry(a, s->hostentry, &ms); + rta_apply_hostentry(a, s->hostentry, &ms, s->pool); } } diff --git a/proto/radv/radv.c b/proto/radv/radv.c index a381f7372..d719ad781 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -560,7 +560,9 @@ radv_check_active(struct radv_proto *p) return 1; struct channel *c = p->p.main_channel; - return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter); + struct linpool *lp = lp_new(p->p.pool, 1024); + return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter, lp); + rfree(lp); } static void diff --git a/proto/static/static.c b/proto/static/static.c index 40096c162..6984db64f 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -91,7 +91,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) if (r->dest == RTDX_RECURSIVE) { rtable *tab = ipa_is_ip4(r->via) ? p->igp_table_ip4 : p->igp_table_ip6; - rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE, r->mls); + rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE, r->mls, static_lp); } /* Already announced */