summaryrefslogtreecommitdiff
path: root/sysdep/unix
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2015-04-25 20:43:43 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2015-04-25 20:43:43 +0200
commitc5ff44a703e4ab810a5bd45cf9140643a50fb3ec (patch)
tree9da170899ebd1d1afea30a358c031bc704c47d0d /sysdep/unix
parent90097f4fb924922b416247abf291fb21f39dc8e1 (diff)
KRT: Fixes learning of preferred kernel routes.
When a new route was imported from kernel and chosen as preferred, then the old best route was propagated as a withdraw to the kernel protocol. Under some circumstances such withdraw propagated to the BSD kernel could remove the new alien route and thus reverting the import.
Diffstat (limited to 'sysdep/unix')
-rw-r--r--sysdep/unix/krt.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 0a223a4f..7cec28c8 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -961,7 +961,21 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
rte *e = *new;
if (e->attrs->src->proto == P)
+ {
+#ifdef CONFIG_SINGLE_ROUTE
+ /*
+ * Implicit withdraw - when the imported kernel route becomes the best one,
+ * we know that the previous one exported to the kernel was already removed,
+ * but if we processed the update as usual, we would send withdraw to the
+ * kernel, which would remove the new imported route instead.
+ *
+ * We will remove KRT_INSTALLED flag, which stops such withdraw to be
+ * processed in krt_rt_notify() and krt_replace_rte().
+ */
+ e->net->n.flags &= ~KRF_INSTALLED;
+#endif
return -1;
+ }
if (!KRT_CF->devroutes &&
(e->attrs->dest == RTD_DEVICE) &&