From e3d901f8638dec32eac4c2690912138963ae5a05 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Tue, 11 May 2021 15:57:39 -0400 Subject: [PATCH] lib,zebra: Use a flag to track down status for connected addrs Track 'down' state of connected addresses with a new flag. We may have multiple addresses on an interface that share a prefix; in those cases, we need to determine when the first address is valid, to install a connected route, and similarly detect when the last address goes 'down', to remove the connected route. Signed-off-by: Mark Stapp --- lib/if.h | 3 +++ zebra/connected.c | 28 +++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/if.h b/lib/if.h index f425ba8bce..0d689fe14b 100644 --- a/lib/if.h +++ b/lib/if.h @@ -393,6 +393,7 @@ struct connected { #define ZEBRA_IFC_REAL (1 << 0) #define ZEBRA_IFC_CONFIGURED (1 << 1) #define ZEBRA_IFC_QUEUED (1 << 2) +#define ZEBRA_IFC_DOWN (1 << 3) /* The ZEBRA_IFC_REAL flag should be set if and only if this address exists in the kernel and is actually usable. (A case where it exists @@ -406,6 +407,8 @@ struct connected { in the kernel. It may and should be set although the address might not be usable yet. (compare with ZEBRA_IFC_REAL) + The ZEBRA_IFC_DOWN flag is used to record that an address is + present, but down/unavailable. */ /* Flags for connected address. */ diff --git a/zebra/connected.c b/zebra/connected.c index 1e03f8b639..883334d509 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -38,7 +38,6 @@ #include "zebra/connected.h" #include "zebra/rtadv.h" #include "zebra/zebra_mpls.h" -#include "zebra/debug.h" #include "zebra/zebra_errors.h" #include "zebra/zebra_router.h" @@ -223,6 +222,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; + /* Ensure 'down' flag is cleared */ + UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); + PREFIX_COPY(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ @@ -280,7 +282,8 @@ void connected_up(struct interface *ifp, struct connected *ifc) PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); apply_mask(&cp); - if (prefix_same(&cp, &p)) + if (prefix_same(&cp, &p) && + !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN)) count++; if (count >= 2) @@ -390,7 +393,7 @@ void connected_down(struct interface *ifp, struct connected *ifc) if (!zvrf) { flog_err( EC_ZEBRA_VRF_NOT_FOUND, - "%s: Received Up for interface but no associated zvrf: %d", + "%s: Received Down for interface but no associated zvrf: %d", __func__, ifp->vrf_id); return; } @@ -398,6 +401,17 @@ void connected_down(struct interface *ifp, struct connected *ifc) if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; + /* Skip if we've already done this; this can happen if we have a + * config change that takes an interface down, then we receive kernel + * notifications about the downed interface and its addresses. + */ + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_DOWN)) { + if (IS_ZEBRA_DEBUG_RIB) + zlog_debug("%s: ifc %p, %pFX already DOWN", + __func__, ifc, ifc->address); + return; + } + PREFIX_COPY(&p, CONNECTED_PREFIX(ifc)); /* Apply mask to the network. */ @@ -423,6 +437,9 @@ void connected_down(struct interface *ifp, struct connected *ifc) break; } + /* Mark the address as 'down' */ + SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); + /* * It's possible to have X number of addresses * on a interface that all resolve to the same @@ -436,10 +453,11 @@ void connected_down(struct interface *ifp, struct connected *ifc) PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); apply_mask(&cp); - if (prefix_same(&p, &cp)) + if (prefix_same(&p, &cp) && + !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN)) count++; - if (count >= 2) + if (count >= 1) return; }