summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nest/route.h2
-rw-r--r--sysdep/bsd/krt-sock.c5
-rw-r--r--sysdep/linux/netlink.c3
-rw-r--r--sysdep/unix/krt.c46
4 files changed, 34 insertions, 22 deletions
diff --git a/nest/route.h b/nest/route.h
index c435b9e0..9368808f 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -223,8 +223,8 @@ typedef struct rte {
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
s8 src; /* Alleged route source (see krt.h) */
u8 proto; /* Kernel source protocol ID */
- u8 type; /* Kernel route type */
u8 seen; /* Seen during last scan */
+ u8 best; /* Best route in network, propagated to core */
u32 metric; /* Kernel metric */
} krt;
} u;
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index 29203d1b..6ff3b2b7 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -493,9 +493,8 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
e->net = net;
e->u.krt.src = src;
e->u.krt.proto = src2;
-
- /* These are probably too Linux-specific */
- e->u.krt.type = 0;
+ e->u.krt.seen = 0;
+ e->u.krt.best = 0;
e->u.krt.metric = 0;
if (scan)
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 640d1877..1ffdff07 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -1102,7 +1102,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
e->net = net;
e->u.krt.src = src;
e->u.krt.proto = i->rtm_protocol;
- e->u.krt.type = i->rtm_type;
+ e->u.krt.seen = 0;
+ e->u.krt.best = 0;
e->u.krt.metric = 0;
if (a[RTA_PRIORITY])
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 5e78586b..f5dee877 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -417,46 +417,58 @@ again:
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);
@@ -515,31 +527,31 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
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);
}
}
@@ -564,7 +576,7 @@ krt_dump(struct proto *P)
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