]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: fix evpn mh bond member proto reinstall
authorChirag Shah <chirag@nvidia.com>
Wed, 19 Jun 2024 00:21:49 +0000 (17:21 -0700)
committerChirag Shah <chirag@nvidia.com>
Thu, 20 Jun 2024 16:09:21 +0000 (09:09 -0700)
In case of EVPN MH bond, a member port going in
protodown state due to external reason (one case being linkflap),
frr updates the state correctly but upon manually
clearing external reason trigger FRR to reinstate
protodown without any reason code.

Fix is to ensure if the protodown reason was external
and new state is to have protodown 'off' then do no reinstate
protodown.

Ticket: #3947432
Testing:
switch:#ip link show swp1
4: swp1: <NO-CARRIER,BROADCAST,MULTICAST,SLAVE,UP> mtu 9216 qdisc
   pfifo_fast master bond1 state DOWN mode DEFAULT group default qlen
   1000
       link/ether 1c:34:da:2c:aa:68 brd ff:ff:ff:ff:ff:ff protodown on
       protodown_reason <linkflap>

switch:#ip link set swp1 protodown off protodown_reason linkflap off
switch:#ip link show swp1
 4: swp1: <NO-CARRIER,BROADCAST,MULTICAST,SLAVE,UP> mtu 9216 qdisc
    pfifo_fast master bond1 state DOWN mode DEFAULT group default qlen
    1000
        link/ether 1c:34:da:2c:aa:68 brd ff:ff:ff:ff:ff:ff

Signed-off-by: Chirag Shah <chirag@nvidia.com>
zebra/interface.c

index b824977f9e13157278f06fc1f5f138b6bf2a8660..f1f24cc29f16421fecc0c0cc4e0bb76a354331b2 100644 (file)
@@ -1656,8 +1656,10 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
                                   uint32_t rc_bitfield)
 {
        struct zebra_if *zif = ifp->info;
-       bool old_protodown;
+       bool old_protodown, reason_extern;
 
+       reason_extern = !!CHECK_FLAG(zif->protodown_rc,
+                                    ZEBRA_PROTODOWN_EXTERNAL);
        /*
         * Set our reason code to note it wasn't us.
         * If the reason we got from the kernel is ONLY frr though, don't
@@ -1673,8 +1675,8 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
                return;
 
        if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE)
-               zlog_debug("interface %s dplane change, protodown %s",
-                          ifp->name, protodown ? "on" : "off");
+               zlog_debug("interface %s dplane change, protodown %s curr reason_extern %u",
+                          ifp->name, protodown ? "on" : "off", reason_extern);
 
        /* Set protodown, respectively */
        COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown);
@@ -1699,6 +1701,13 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
                        return;
                }
 
+               if (!protodown && reason_extern) {
+                       if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+                               zlog_debug("bond member %s has protodown reason external and clear the reason, skip reinstall.",
+                                          ifp->name);
+                       return;
+               }
+
                if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug(
                                "bond mbr %s reinstate protodown %s in the dplane",