diff options
author | Maria Matejka <mq@ucw.cz> | 2021-03-20 21:16:12 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2021-10-13 19:09:04 +0200 |
commit | cee0cd148c9b71bf47d007c850193b5fbf9486c1 (patch) | |
tree | 83d46b46691d897fbb97b723f176a390bcad9788 | |
parent | 8216ec3027d01b790e59a266227d378ba77a623e (diff) |
Export table: Delay freeing of old stored route.
This is needed to provide the protocols the full old route after filters
when export table is enabled.
-rw-r--r-- | nest/route.h | 2 | ||||
-rw-r--r-- | nest/rt-table.c | 58 |
2 files changed, 34 insertions, 26 deletions
diff --git a/nest/route.h b/nest/route.h index f5fc9e31..227a5f5e 100644 --- a/nest/route.h +++ b/nest/route.h @@ -353,7 +353,7 @@ int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src int rt_reload_channel(struct channel *c); void rt_reload_channel_abort(struct channel *c); void rt_prune_sync(rtable *t, int all); -int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, int refeed); +int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old, rte **old_exported, int refeed); struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); diff --git a/nest/rt-table.c b/nest/rt-table.c index 13209dd7..b1e3ab70 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -333,6 +333,26 @@ rte_cow_rta(rte *r, linpool *lp) return r; } +/** + * rte_free - delete a &rte + * @e: &rte to be deleted + * + * rte_free() deletes the given &rte from the routing table it's linked to. + */ +void +rte_free(rte *e) +{ + if (rta_is_cached(e->attrs)) + rta_free(e->attrs); + sl_free(rte_slab, e); +} + +static inline void +rte_free_quick(rte *e) +{ + rta_free(e->attrs); + sl_free(rte_slab, e); +} /** * rte_init_tmp_attrs - initialize temporary ea_list for route @@ -661,8 +681,14 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed) } /* Apply export table */ - if (c->out_table && !rte_update_out(c, net->n.addr, new, old, refeed)) - return; + struct rte *old_exported = NULL; + if (c->out_table) + { + if (!rte_update_out(c, net->n.addr, new, old, &old_exported, refeed)) + return; + } + else if (c->out_filter == FILTER_ACCEPT) + old_exported = old; if (new) stats->exp_updates_accepted++; @@ -692,6 +718,9 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed) } p->rt_notify(p, c, net, new, old); + + if (c->out_table && old_exported) + rte_free_quick(old_exported); } static void @@ -1044,27 +1073,6 @@ rte_validate(rte *e) return 1; } -/** - * rte_free - delete a &rte - * @e: &rte to be deleted - * - * rte_free() deletes the given &rte from the routing table it's linked to. - */ -void -rte_free(rte *e) -{ - if (rta_is_cached(e->attrs)) - rta_free(e->attrs); - sl_free(rte_slab, e); -} - -static inline void -rte_free_quick(rte *e) -{ - rta_free(e->attrs); - sl_free(rte_slab, e); -} - static int rte_same(rte *x, rte *y) { @@ -2762,7 +2770,7 @@ again: */ int -rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, int refeed) +rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, rte **old_exported, int refeed) { struct rtable *tab = c->out_table; struct rte_src *src; @@ -2808,7 +2816,7 @@ rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, int re /* Remove the old rte */ *pos = old->next; - rte_free_quick(old); + *old_exported = old; tab->rt_count--; break; |