From ab465d24bd864c7ab9f5841af89c108e03e768ac Mon Sep 17 00:00:00 2001 From: Stephen Worley Date: Mon, 31 Jan 2022 16:12:01 -0500 Subject: zebra: only clear pd_reason on shutdown/sweep Only clear protodown reason on shutdown/sweep, retain protodown state. This is to retain traditional and expected behavior with daemons like vrrpd setting protodown. They expet it to be set on shutdown and retained on bring up to prevent traffic from being dropped. We must cleanup our reason code though to prevent us from blocking others. Signed-off-by: Stephen Worley --- zebra/interface.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'zebra/interface.c') diff --git a/zebra/interface.c b/zebra/interface.c index 6fb34d59ac..167f1b4587 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -63,6 +63,8 @@ DEFINE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp), static void if_down_del_nbr_connected(struct interface *ifp); +static int zebra_if_update_protodown(struct interface *ifp, bool new_down, + uint32_t new_protodown_rc); static void if_zebra_speed_update(struct thread *thread) { @@ -261,11 +263,12 @@ static int if_zebra_delete_hook(struct interface *ifp) if (ifp->info) { zebra_if = ifp->info; - /* If we set protodown, clear it now from the kernel */ - if (ZEBRA_IF_IS_PROTODOWN(zebra_if) && + /* If we set protodown, clear our reason now from the kernel */ + if (ZEBRA_IF_IS_PROTODOWN(zebra_if) && zebra_if->protodown_rc && !ZEBRA_IF_IS_PROTODOWN_ONLY_EXTERNAL(zebra_if)) - zebra_if_set_protodown(ifp, false, ZEBRA_PROTODOWN_ALL); - + zebra_if_update_protodown(ifp, true, + (zebra_if->protodown_rc & + ~ZEBRA_PROTODOWN_ALL)); /* Free installed address chains tree. */ if (zebra_if->ipv4_subnets) @@ -1291,19 +1294,13 @@ static bool if_ignore_set_protodown(const struct interface *ifp, bool new_down, return false; } -int zebra_if_set_protodown(struct interface *ifp, bool new_down, - enum protodown_reasons new_reason) +static int zebra_if_update_protodown(struct interface *ifp, bool new_down, + uint32_t new_protodown_rc) { struct zebra_if *zif; - uint32_t new_protodown_rc; zif = ifp->info; - if (new_down) - new_protodown_rc = zif->protodown_rc | new_reason; - else - new_protodown_rc = zif->protodown_rc & ~new_reason; - /* Check if we already have this state or it's queued */ if (if_ignore_set_protodown(ifp, new_down, new_protodown_rc)) return 1; @@ -1328,6 +1325,22 @@ int zebra_if_set_protodown(struct interface *ifp, bool new_down, return 0; } +int zebra_if_set_protodown(struct interface *ifp, bool new_down, + enum protodown_reasons new_reason) +{ + struct zebra_if *zif; + uint32_t new_protodown_rc; + + zif = ifp->info; + + if (new_down) + new_protodown_rc = zif->protodown_rc | new_reason; + else + new_protodown_rc = zif->protodown_rc & ~new_reason; + + return zebra_if_update_protodown(ifp, new_down, new_protodown_rc); +} + /* * Handle an interface events based on info in a dplane context object. * This runs in the main pthread, using the info in the context object to @@ -1410,18 +1423,18 @@ static void zebra_if_update_ctx(struct zebra_dplane_ctx *ctx, { enum zebra_dplane_result dp_res; struct zebra_if *zif; - uint32_t r_bitfield; + bool pd_reason_val; bool down; dp_res = dplane_ctx_get_status(ctx); - r_bitfield = dplane_ctx_get_intf_r_bitfield(ctx); + pd_reason_val = dplane_ctx_get_intf_pd_reason_val(ctx); down = dplane_ctx_intf_is_protodown(ctx); if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s: %s: if %s(%u) ctx-protodown %s ctx-reason 0x%x", + zlog_debug("%s: %s: if %s(%u) ctx-protodown %s ctx-reason %d", __func__, dplane_op2str(dplane_ctx_get_op(ctx)), ifp->name, ifp->ifindex, down ? "on" : "off", - r_bitfield); + pd_reason_val); zif = ifp->info; if (!zif) { -- cgit v1.2.3