]> git.proxmox.com Git - mirror_frr.git/commitdiff
eigrpd, ospfd, pimd: Fix assumption that interface may not be up
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 24 Oct 2019 19:09:18 +0000 (15:09 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 4 Dec 2019 19:23:20 +0000 (14:23 -0500)
Commit: ddbf3e60604019d4b38d51226700e2244cc531b6

This commit modified the interface up handling code in
ZAPI such that the zclient handled the decoding for you.
Prior to this commit ospf assumed that it could use the
old ifp pointer to know state before reading the stream.
This lead to a situation where ospf would `smartly` track
and do the right thing in this situation.  This commit
changed this assumption and in certain scenarios, say
a interface was changed after it was already up would
lead to situations where ospf would not properly handle
the new interface up.

Modify ospf to track data that is important to it in
it's interface->info pointer.

This code pattern was followed in both eigrp and pim.
In eigrp's case it was just behaving weirdly in any event
so fixing this pattern is not a big deal.  In pim's
case it was not properly using this so it's a no-op
to fix.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
eigrpd/eigrp_interface.c
eigrpd/eigrp_structs.h
ospfd/ospf_interface.c
ospfd/ospf_interface.h
pimd/pim_iface.c

index 6294c0dd0fb0c59af252fccfdaa1ef095bc82dbf..ece0b4b0c4c4a4aeecadfc2415b6c056acdd01b4 100644 (file)
@@ -99,6 +99,9 @@ struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp,
        ei->params.auth_type = EIGRP_AUTH_TYPE_NONE;
        ei->params.auth_keychain = NULL;
 
+       ei->curr_bandwidth = ifp->bandwidth;
+       ei->curr_mtu = ifp->mtu;
+
        return ei;
 }
 
@@ -139,45 +142,40 @@ static int eigrp_ifp_create(struct interface *ifp)
 
 static int eigrp_ifp_up(struct interface *ifp)
 {
-       /* Interface is already up. */
-       if (if_is_operative(ifp)) {
-               /* Temporarily keep ifp values. */
-               struct interface if_tmp;
-               memcpy(&if_tmp, ifp, sizeof(struct interface));
+       struct eigrp_interface *ei = ifp->info;
 
-               if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
-                       zlog_debug("Zebra: Interface[%s] state update.",
-                                  ifp->name);
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+               zlog_debug("Zebra: Interface[%s] state change to up.",
+                          ifp->name);
 
-               if (if_tmp.bandwidth != ifp->bandwidth) {
-                       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
-                               zlog_debug(
-                                       "Zebra: Interface[%s] bandwidth change %d -> %d.",
-                                       ifp->name, if_tmp.bandwidth,
-                                       ifp->bandwidth);
+       if (!ei)
+               return 0;
 
-                       //          eigrp_if_recalculate_output_cost (ifp);
-               }
+       if (ei->curr_bandwidth != ifp->bandwidth) {
+               if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+                       zlog_debug(
+                               "Zebra: Interface[%s] bandwidth change %d -> %d.",
+                               ifp->name, ei->curr_bandwidth,
+                               ifp->bandwidth);
 
-               if (if_tmp.mtu != ifp->mtu) {
-                       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
-                               zlog_debug(
-                                       "Zebra: Interface[%s] MTU change %u -> %u.",
-                                       ifp->name, if_tmp.mtu, ifp->mtu);
+               ei->curr_bandwidth = ifp->bandwidth;
+               // eigrp_if_recalculate_output_cost (ifp);
+       }
 
-                       /* Must reset the interface (simulate down/up) when MTU
-                        * changes. */
-                       eigrp_if_reset(ifp);
-               }
+       if (ei->curr_mtu != ifp->mtu) {
+               if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+                       zlog_debug(
+                               "Zebra: Interface[%s] MTU change %u -> %u.",
+                               ifp->name, ei->curr_mtu, ifp->mtu);
+
+               ei->curr_mtu = ifp->mtu;
+               /* Must reset the interface (simulate down/up) when MTU
+                * changes. */
+               eigrp_if_reset(ifp);
                return 0;
        }
 
-       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
-               zlog_debug("Zebra: Interface[%s] state change to up.",
-                          ifp->name);
-
-       if (ifp->info)
-               eigrp_if_up(ifp->info);
+       eigrp_if_up(ifp->info);
 
        return 0;
 }
index e50858f0715288b4627a25c052841f91ad81a16f..82bddaaae3bbd5dbe51ecb6f857776278b5e48a3 100644 (file)
@@ -176,6 +176,8 @@ struct eigrp_interface {
 
        /* To which multicast groups do we currently belong? */
 
+       uint32_t curr_bandwidth;
+       uint32_t curr_mtu;
 
        uint8_t multicast_memberships;
 
index 7ddffbcdbdc36d289b076f7a8ac27cd2d762cae1..cfcffcdb3dddce0d6b0d19a476380c2553045fe3 100644 (file)
@@ -636,9 +636,13 @@ void ospf_if_update_params(struct interface *ifp, struct in_addr addr)
 int ospf_if_new_hook(struct interface *ifp)
 {
        int rc = 0;
+       struct ospf_if_info *oii;
 
        ifp->info = XCALLOC(MTYPE_OSPF_IF_INFO, sizeof(struct ospf_if_info));
 
+       oii = ifp->info;
+       oii->curr_mtu = ifp->mtu;
+
        IF_OIFS(ifp) = route_table_init();
        IF_OIFS_PARAMS(ifp) = route_table_init();
 
@@ -1261,31 +1265,21 @@ static int ospf_ifp_up(struct interface *ifp)
 {
        struct ospf_interface *oi;
        struct route_node *rn;
+       struct ospf_if_info *oii = ifp->info;
 
-       /* Interface is already up. */
-       if (if_is_operative(ifp)) {
-               /* Temporarily keep ifp values. */
-               struct interface if_tmp;
-               memcpy(&if_tmp, ifp, sizeof(struct interface));
+       ospf_if_recalculate_output_cost(ifp);
 
+       if (oii && oii->curr_mtu != ifp->mtu) {
                if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
                        zlog_debug(
-                               "Zebra: Interface[%s] state update speed %u -> %u, bw  %d -> %d",
-                               ifp->name, if_tmp.speed, ifp->speed,
-                               if_tmp.bandwidth, ifp->bandwidth);
+                               "Zebra: Interface[%s] MTU change %u -> %u.",
+                               ifp->name, oii->curr_mtu, ifp->mtu);
 
-               ospf_if_recalculate_output_cost(ifp);
+               oii->curr_mtu = ifp->mtu;
+               /* Must reset the interface (simulate down/up) when MTU
+                * changes. */
+               ospf_if_reset(ifp);
 
-               if (if_tmp.mtu != ifp->mtu) {
-                       if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
-                               zlog_debug(
-                                       "Zebra: Interface[%s] MTU change %u -> %u.",
-                                       ifp->name, if_tmp.mtu, ifp->mtu);
-
-                       /* Must reset the interface (simulate down/up) when MTU
-                        * changes. */
-                       ospf_if_reset(ifp);
-               }
                return 0;
        }
 
index cde52dbb9e3c21904692f09b45459a9e8c53f0ce..4b3dbcc5c27284e4fe1c051e6676f373a035874c 100644 (file)
@@ -117,6 +117,8 @@ struct ospf_if_info {
        struct route_table *oifs;
        unsigned int
                membership_counts[MEMBER_MAX]; /* multicast group refcnts */
+
+       uint32_t curr_mtu;
 };
 
 struct ospf_interface;
index 3ee9caebcf6c17d3fe1890d95038b690fe8db817..c615540149621e2ad70d314d81082bb2a70abcdc 100644 (file)
@@ -1481,6 +1481,13 @@ void pim_if_create_pimreg(struct pim_instance *pim)
 
                pim_if_new(pim->regiface, false, false, true,
                        false /*vxlan_term*/);
+               /*
+                * On vrf moves we delete the interface if there
+                * is nothing going on with it.  We cannot have
+                * the pimregiface deleted.
+                */
+               pim->regiface->configured = true;
+
        }
 }
 
@@ -1581,6 +1588,7 @@ int pim_ifp_create(struct interface *ifp)
 
 int pim_ifp_up(struct interface *ifp)
 {
+       struct pim_interface *pim_ifp;
        struct pim_instance *pim;
        uint32_t table_id;
 
@@ -1593,24 +1601,21 @@ int pim_ifp_up(struct interface *ifp)
        }
 
        pim = pim_get_pim_instance(ifp->vrf_id);
-       if (if_is_operative(ifp)) {
-               struct pim_interface *pim_ifp;
 
-               pim_ifp = ifp->info;
-               /*
-                * If we have a pim_ifp already and this is an if_add
-                * that means that we probably have a vrf move event
-                * If that is the case, set the proper vrfness.
-                */
-               if (pim_ifp)
-                       pim_ifp->pim = pim;
+       pim_ifp = ifp->info;
+       /*
+        * If we have a pim_ifp already and this is an if_add
+        * that means that we probably have a vrf move event
+        * If that is the case, set the proper vrfness.
+        */
+       if (pim_ifp)
+               pim_ifp->pim = pim;
 
-               /*
-                 pim_if_addr_add_all() suffices for bringing up both IGMP and
-                 PIM
-               */
-               pim_if_addr_add_all(ifp);
-       }
+       /*
+         pim_if_addr_add_all() suffices for bringing up both IGMP and
+         PIM
+       */
+       pim_if_addr_add_all(ifp);
 
        /*
         * If we have a pimreg device callback and it's for a specific