krt_pool = rp_new(&root_pool, "Kernel Syncer");
krt_filter_lp = lp_new(krt_pool, 4080);
init_list(&krt_proto_list);
+ krt_sys_io_init();
}
/*
* Interfaces
*/
+struct kif_proto *kif_proto;
static struct kif_config *kif_cf;
-static struct kif_proto *kif_proto;
static timer *kif_scan_timer;
static bird_clock_t kif_last_shot;
net *n = (net *) f;
rte *e, **ee, *best, **pbest, *old_best;
- old_best = n->routes;
+ /*
+ * Note that old_best may be NULL even if there was an old best route in
+ * the previous step, because it might be replaced in krt_learn_scan().
+ * But in that case there is a new valid best route.
+ */
+
+ old_best = NULL;
best = NULL;
pbest = NULL;
ee = &n->routes;
while (e = *ee)
{
+ if (e->u.krt.best)
+ old_best = e;
+
if (!e->u.krt.seen)
{
*ee = e->next;
rte_free(e);
continue;
}
+
if (!best || best->u.krt.metric > e->u.krt.metric)
{
best = e;
pbest = ee;
}
+
e->u.krt.seen = 0;
+ e->u.krt.best = 0;
ee = &e->next;
}
if (!n->routes)
{
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
if (old_best)
- {
- krt_learn_announce_delete(p, n);
- n->n.flags &= ~KRF_INSTALLED;
- }
+ krt_learn_announce_delete(p, n);
+
FIB_ITERATE_PUT(&fit, f);
fib_delete(fib, f);
goto again;
}
+
+ best->u.krt.best = 1;
*pbest = best->next;
best->next = n->routes;
n->routes = best;
- if (best != old_best || !(n->n.flags & KRF_INSTALLED) || p->reload)
+
+ if ((best != old_best) || p->reload)
{
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
krt_learn_announce_update(p, best);
- n->n.flags |= KRF_INSTALLED;
}
else
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
best = n->routes;
bestp = &n->routes;
for(gg=&n->routes; g=*gg; gg=&g->next)
+ {
if (best->u.krt.metric > g->u.krt.metric)
{
best = g;
bestp = gg;
}
+
+ g->u.krt.best = 0;
+ }
+
if (best)
{
+ best->u.krt.best = 1;
*bestp = best->next;
best->next = n->routes;
n->routes = best;
}
+
if (best != old_best)
{
DBG("krt_learn_async: distributing change\n");
if (best)
- {
- krt_learn_announce_update(p, best);
- n->n.flags |= KRF_INSTALLED;
- }
+ krt_learn_announce_update(p, best);
else
- {
- n->routes = NULL;
- krt_learn_announce_delete(p, n);
- n->n.flags &= ~KRF_INSTALLED;
- }
+ krt_learn_announce_delete(p, n);
}
}
static void
krt_dump_attrs(rte *e)
{
- debug(" [m=%d,p=%d,t=%d]", e->u.krt.metric, e->u.krt.proto, e->u.krt.type);
+ debug(" [m=%d,p=%d]", e->u.krt.metric, e->u.krt.proto);
}
#endif
static struct rte *
krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
{
- struct filter *filter = p->p.main_ahook->out_filter;
+ struct announce_hook *ah = p->p.main_ahook;
+ struct filter *filter = ah->out_filter;
rte *rt;
+ if (p->p.accept_ra_types == RA_MERGED)
+ return rt_export_merged(ah, net, rt_free, tmpa, krt_filter_lp, 1);
+
rt = net->routes;
*rt_free = NULL;
if (filter == FILTER_ACCEPT)
goto accept;
- if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) > F_ACCEPT)
+ if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT)
goto reject;
}
static void
-krt_scan_timer_stop(struct krt_proto *p)
+krt_scan_timer_stop(struct krt_proto *p UNUSED)
{
krt_scan_count--;
}
static int
-krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool)
+krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
{
struct krt_proto *p = (struct krt_proto *) P;
rte *e = *new;
struct krt_config *krt_cf;
static struct proto *
-krt_init(struct proto_config *c)
+krt_init(struct proto_config *C)
{
- struct krt_proto *p = proto_new(c, sizeof(struct krt_proto));
+ struct krt_proto *p = proto_new(C, sizeof(struct krt_proto));
+ struct krt_config *c = (struct krt_config *) C;
- p->p.accept_ra_types = RA_OPTIMAL;
+ p->p.accept_ra_types = c->merge_paths ? RA_MERGED : RA_OPTIMAL;
+ p->p.merge_limit = c->merge_paths;
p->p.import_control = krt_import_control;
p->p.rt_notify = krt_rt_notify;
p->p.if_notify = krt_if_notify;
krt_learn_init(p);
#endif
- krt_sys_start(p);
+ if (!krt_sys_start(p))
+ {
+ rem_node(&p->krt_node);
+ return PS_START;
+ }
krt_scan_timer_start(p);
p->ready = 0;
p->initialized = 0;
- krt_sys_shutdown(p);
+ if (p->p.proto_state == PS_START)
+ return PS_DOWN;
+ krt_sys_shutdown(p);
rem_node(&p->krt_node);
return PS_DOWN;
return 0;
/* persist, graceful restart need not be the same */
- return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
+ return o->scan_time == n->scan_time && o->learn == n->learn &&
+ o->devroutes == n->devroutes && o->merge_paths == n->merge_paths;
}
static void