diff options
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/unix/krt.c | 52 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 1 |
2 files changed, 41 insertions, 12 deletions
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index b98e7ec0..40a58442 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -542,21 +542,27 @@ krt_is_installed(struct krt_proto *p, net *n) return n->routes && bmap_test(&p->p.main_channel->export_map, n->routes->rte.id); } -static void -krt_flush_routes(struct krt_proto *p) +static uint +rte_feed_count(net *n) { - struct rtable *t = p->p.main_channel->table; + uint count = 0; + for (struct rte_storage *e = n->routes; e; e = e->next) + if (rte_is_valid(RTE_OR_NULL(e))) + count++; + return count; +} - KRT_TRACE(p, D_EVENTS, "Flushing kernel routes"); - FIB_WALK(&t->fib, net, n) +static void +rte_feed_obtain(net *n, rte **feed, uint count) +{ + uint i = 0; + for (struct rte_storage *e = n->routes; e; e = e->next) + if (rte_is_valid(RTE_OR_NULL(e))) { - if (krt_is_installed(p, n)) - { - /* FIXME: this does not work if gw is changed in export filter */ - krt_replace_rte(p, n->n.addr, NULL, &n->routes->rte); - } + ASSERT_DIE(i < count); + feed[i++] = &e->rte; } - FIB_WALK_END; + ASSERT_DIE(i == count); } static struct rte * @@ -566,7 +572,15 @@ krt_export_net(struct krt_proto *p, net *net) const struct filter *filter = c->out_filter; if (c->ra_mode == RA_MERGED) - return rt_export_merged_show(c, net, krt_filter_lp); + { + uint count = rte_feed_count(net); + if (!count) + return NULL; + + rte **feed = alloca(count * sizeof(rte *)); + rte_feed_obtain(net, feed, count); + return rt_export_merged(c, feed, count, krt_filter_lp, 1); + } static _Thread_local rte rt; rt = net->routes->rte; @@ -637,6 +651,9 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src) #endif /* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */ + /* Deleting all routes if flush is requested */ + if (p->flush_routes) + goto delete; /* We wait for the initial feed to have correct installed state */ if (!p->ready) @@ -729,6 +746,17 @@ krt_prune(struct krt_proto *p) p->initialized = 1; } +static void +krt_flush_routes(struct krt_proto *p) +{ + KRT_TRACE(p, D_EVENTS, "Flushing kernel routes"); + p->flush_routes = 1; + krt_init_scan(p); + krt_do_scan(p); + /* No prune! */ + p->flush_routes = 0; +} + void krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src) { diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index cd4bd07d..f6ad6fde 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -66,6 +66,7 @@ struct krt_proto { byte ready; /* Initial feed has been finished */ byte initialized; /* First scan has been finished */ byte reload; /* Next scan is doing reload */ + byte flush_routes; /* Scanning to flush */ }; extern pool *krt_pool; |