diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-09-27 22:57:55 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2018-12-12 14:46:24 +0100 |
commit | 682d3f7de0905ca2e853844734cce7ff65f7d77d (patch) | |
tree | e84ab31b4c5b7e99a283cf4c2faf2523dd5d884c /nest/proto.c | |
parent | 01fd00f5ed9298ab5829403cd7a8a9ba22bcc96a (diff) |
BGP: implement Adj-RIB-In
The patch implements optional internal import table to a channel and
hooks it to BGP so it can be used as Adj-RIB-In. When enabled, all
received (pre-filtered) routes are stored there and import filters can
be re-evaluated without explicit route refresh. An import table can be
examined using e.g. 'show route import table bgp1.ipv4'.
Diffstat (limited to 'nest/proto.c')
-rw-r--r-- | nest/proto.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/nest/proto.c b/nest/proto.c index a6aa4e5c..7849b604 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -284,6 +284,54 @@ channel_stop_export(struct channel *c) c->stats.exp_routes = 0; } + +/* Called by protocol for reload from in_table */ +void +channel_schedule_reload(struct channel *c) +{ + ASSERT(c->channel_state == CS_UP); + + rt_reload_channel_abort(c); + ev_schedule(c->reload_event); +} + +static void +channel_reload_loop(void *ptr) +{ + struct channel *c = ptr; + + if (!rt_reload_channel(c)) + { + ev_schedule(c->reload_event); + return; + } +} + +static void +channel_reset_import(struct channel *c) +{ + /* Need to abort feeding */ + ev_postpone(c->reload_event); + rt_reload_channel_abort(c); + + rt_prune_sync(c->in_table, 1); +} + +/* Called by protocol to activate in_table */ +void +channel_setup_in_table(struct channel *c) +{ + struct rtable_config *cf = mb_allocz(c->proto->pool, sizeof(struct rtable_config)); + cf->name = "import"; + cf->addr_type = c->net_type; + + c->in_table = mb_allocz(c->proto->pool, sizeof(struct rtable)); + rt_setup(c->proto->pool, c->in_table, cf); + + c->reload_event = ev_new_init(c->proto->pool, channel_reload_loop, c); +} + + static void channel_do_start(struct channel *c) { @@ -315,6 +363,8 @@ channel_do_flush(struct channel *c) static void channel_do_down(struct channel *c) { + ASSERT(!c->feed_active && !c->reload_active); + rem_node(&c->table_node); rt_unlock_table(c->table); c->proto->active_channels--; @@ -324,6 +374,9 @@ channel_do_down(struct channel *c) memset(&c->stats, 0, sizeof(struct proto_stats)); + c->in_table = NULL; + c->reload_event = NULL; + CALL(c->channel->cleanup, c); /* Schedule protocol shutddown */ @@ -355,6 +408,9 @@ channel_set_state(struct channel *c, uint state) if (es != ES_DOWN) channel_stop_export(c); + if (c->in_table && (cs == CS_UP)) + channel_reset_import(c); + break; case CS_UP: @@ -374,6 +430,9 @@ channel_set_state(struct channel *c, uint state) if (es != ES_DOWN) channel_stop_export(c); + if (c->in_table && (cs == CS_UP)) + channel_reset_import(c); + channel_do_flush(c); break; |