summaryrefslogtreecommitdiff
path: root/nest/proto.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2018-09-27 22:57:55 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2018-12-12 14:46:24 +0100
commit682d3f7de0905ca2e853844734cce7ff65f7d77d (patch)
treee84ab31b4c5b7e99a283cf4c2faf2523dd5d884c /nest/proto.c
parent01fd00f5ed9298ab5829403cd7a8a9ba22bcc96a (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.c59
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;