/* Hook defined in nest/rt-table.c ... to be refactored away later */
rte *krt_export_net(struct channel *c, const net_addr *a, linpool *lp);
+static void krt_rt_notify(struct proto *P, struct channel *ch, const net_addr *net, rte *new, const rte *old);
+
static int
krt_same_dest(rte *k, rte *e)
{
void
krt_got_route(struct krt_proto *p, rte *e, s8 src)
{
+ /* If we happen to get an asynchronous route notification
+ * before initialization, we wait for the scan. */
+ if (p->sync_state == KPS_INIT)
+ return;
+
rte *new = NULL;
e->pflags = 0;
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
- /* We wait for the initial feed to have correct installed state */
- if (!p->ready)
- goto ignore;
-
/* Get the exported version */
new = krt_export_net(p->p.main_channel, e->net, krt_filter_lp);
krt_trace_in(p, e, "already seen");
goto done;
-ignore:
- krt_trace_in(p, e, "ignored");
- goto done;
-
update:
krt_trace_in(p, new, "updating");
krt_replace_rte(p, e->net, new, e);
{
switch (p->sync_state)
{
+ case KPS_INIT:
+ /* Allow exports now */
+ p->p.rt_notify = krt_rt_notify;
+ channel_start_export(p->p.main_channel);
+ rt_refresh_begin(&p->p.main_channel->in_req);
+ p->sync_state = KPS_FIRST_SCAN;
+ return 1;
+
case KPS_IDLE:
rt_refresh_begin(&p->p.main_channel->in_req);
bmap_reset(&p->seen_map, 1024);
p->sync_state = KPS_SCANNING;
return 1;
+ case KPS_FIRST_SCAN:
case KPS_SCANNING:
bug("Kernel scan double-init");
{
switch (p->sync_state)
{
+ case KPS_INIT:
case KPS_IDLE:
bug("Kernel scan prune without scan");
case KPS_SCANNING:
+ channel_request_full_refeed(p->p.main_channel);
+ /* fall through */
+ case KPS_FIRST_SCAN:
p->sync_state = KPS_PRUNING;
KRT_TRACE(p, D_EVENTS, "Pruning table %s", p->p.main_channel->table->name);
rt_refresh_end(&p->p.main_channel->in_req);
- channel_request_full_refeed(p->p.main_channel);
break;
case KPS_PRUNING:
krt_do_scan(NULL);
WALK_LIST2(p, n, krt_proto_list, krt_node)
- if (p->sync_state == KPS_SCANNING)
+ if ((p->sync_state == KPS_SCANNING) || (p->sync_state == KPS_FIRST_SCAN))
krt_prune(p);
}
static int
krt_preexport(struct channel *C, rte *e)
{
+ /* The export should not start before proper sync */
+ ASSERT_DIE(SKIP_BACK(struct krt_proto, p, C->proto)->sync_state != KPS_INIT);
+
if (e->src->owner == &C->proto->sources)
#ifdef CONFIG_SINGLE_ROUTE
return 1;
return -1;
}
- /* Before first scan we don't touch the routes */
- if (!SKIP_BACK(struct krt_proto, p, C->proto)->ready)
- {
- if (C->debug & D_ROUTES)
- log(L_TRACE "%s.%s not ready yet to accept route for %N",
- C->proto->name, C->name, e->net);
- return -1;
- }
-
return 0;
}
switch (p->sync_state)
{
+ case KPS_INIT:
+ bug("Routes in init state should have been rejected by preexport.");
+
case KPS_IDLE:
case KPS_PRUNING:
if (new && bmap_test(&p->seen_map, new->id))
+ {
if (ch->debug & D_ROUTES)
{
/* Already installed and seen in the kernel dump */
log(L_TRACE "%s.%s: %N already in kernel",
P->name, ch->name, net);
- return;
}
+ return;
+ }
/* fall through */
+ case KPS_FIRST_SCAN:
case KPS_SCANNING:
/* Actually replace the route */
krt_replace_rte(p, net, new, old);
if (KRT_CF->learn)
{
- p->reload = 1;
krt_scan_timer_kick(p);
}
{
struct krt_proto *p = (void *) C->proto;
- p->ready = 1;
- p->initialized = 1;
-
switch (p->sync_state)
{
+ case KPS_INIT:
+ bug("KRT export started before scan");
+
case KPS_IDLE:
krt_scan_timer_kick(p);
break;
+ case KPS_FIRST_SCAN:
+ bug("KRT export done before first scan");
+
case KPS_SCANNING:
break;
p->p.main_channel = proto_add_channel(&p->p, proto_cf_main_channel(CF));
p->p.preexport = krt_preexport;
- p->p.rt_notify = krt_rt_notify;
+ /* Not setting rt_notify here to not start exports, must wait for the first scan
+ * and then we can start exports manually */
p->p.iface_sub.if_notify = krt_if_notify;
p->p.reload_routes = krt_reload_routes;
p->p.export_fed = krt_export_fed;
return PS_FLUSH;
/* FIXME we should flush routes even when persist during reconfiguration */
- if (p->initialized && !KRT_CF->persist && (P->down_code != PDC_CMD_GR_DOWN))
+ if ((p->sync_state != KPS_INIT) && !KRT_CF->persist && (P->down_code != PDC_CMD_GR_DOWN))
{
struct rt_export_feeder req = (struct rt_export_feeder)
{
static void
krt_cleanup(struct krt_proto *p)
{
- p->ready = 0;
- p->initialized = 0;
+ p->sync_state = KPS_INIT;
krt_sys_shutdown(p);
rem_node(&p->krt_node);