summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@cumulusnetworks.com>2019-02-19 20:11:04 +0000
committerQuentin Young <qlyoung@cumulusnetworks.com>2019-05-17 00:27:08 +0000
commit89f3420409aa72b0053f5cd0cd2ffd647432bcc7 (patch)
tree7a2f350672667a301ab49fb061df2336b8dd3505
parent114a413efa7bca86645e514cf568a8ac30023bb9 (diff)
vrrpd: ignore address deletion if iface is down
See code comment for explanation Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
-rw-r--r--vrrpd/vrrp.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
index 5d97199f40..d22c245afe 100644
--- a/vrrpd/vrrp.c
+++ b/vrrpd/vrrp.c
@@ -1961,7 +1961,42 @@ void vrrp_if_address_add(struct interface *ifp)
void vrrp_if_address_del(struct interface *ifp)
{
- vrrp_autoconfig_if_address_del(ifp);
+ /*
+ * Zebra is stupid and sends us address deletion notifications
+ * when any of the following condition sets are met:
+ *
+ * - IFF_UP && address deleted
+ * - IFF_UP -> !IFF_UP
+ *
+ * Note that the second one is nonsense, because Zebra behaves as
+ * though an interface going down means all the addresses on that
+ * interface got deleted. Which is a problem for autoconfig because all
+ * the addresses on an interface going away means the VRRP session goes
+ * to Initialize. However interfaces go down whenever we transition to
+ * Backup, so this effectively means that for autoconfigured instances
+ * we actually end up in Initialize whenever we try to go into Backup.
+ *
+ * Also, Zebra does NOT send us notifications when:
+ * - !IFF_UP && address deleted
+ *
+ * Which means if we're in backup and an address is deleted out from
+ * under us, we won't even know.
+ *
+ * The only solution here is to only resynchronize our address list
+ * when:
+ *
+ * - An interfaces comes up
+ * - An interface address is added
+ * - An interface address is deleted AND the interface is up
+ *
+ * Even though this is only a problem with autoconfig at the moment I'm
+ * papering over Zebra's braindead semantics here. Every piece of code
+ * in this function should be protected by a check that the interface
+ * is up.
+ */
+ if (CHECK_FLAG(ifp->flags, IFF_UP)) {
+ vrrp_autoconfig_if_address_del(ifp);
+ }
}
/* Other ------------------------------------------------------------------- */