]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: handle ipmr-lo operational state changes
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Thu, 6 Feb 2020 17:31:00 +0000 (09:31 -0800)
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Fri, 14 Feb 2020 17:18:30 +0000 (09:18 -0800)
ipmr-lo is an internally added device used for multicast vxlan tunnel
termination. This device is not expected to be managed by the admin
however in the case it is accidentally shut we need to be able handle
it by recovering when it is "no shut" again.

Ticket: CM-24985

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
pimd/pim_iface.c
pimd/pim_vxlan.c
pimd/pim_vxlan.h
pimd/pim_vxlan_instance.h

index c615540149621e2ad70d314d81082bb2a70abcdc..8cc720c5354ff369526401cb62b735e95820d178 100644 (file)
@@ -498,6 +498,7 @@ void pim_if_addr_add(struct connected *ifc)
        struct pim_interface *pim_ifp;
        struct interface *ifp;
        struct in_addr ifaddr;
+       bool vxlan_term;
 
        zassert(ifc);
 
@@ -635,7 +636,8 @@ void pim_if_addr_add(struct connected *ifc)
          address assigned, then try to create a vif_index.
        */
        if (pim_ifp->mroute_vif_index < 0) {
-               pim_if_add_vif(ifp, false, false /*vxlan_term*/);
+               vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
+               pim_if_add_vif(ifp, false, vxlan_term);
        }
        pim_ifchannel_scan_forward_start(ifp);
 }
@@ -730,6 +732,7 @@ void pim_if_addr_add_all(struct interface *ifp)
        int v4_addrs = 0;
        int v6_addrs = 0;
        struct pim_interface *pim_ifp = ifp->info;
+       bool vxlan_term;
 
 
        /* PIM/IGMP enabled ? */
@@ -768,7 +771,8 @@ void pim_if_addr_add_all(struct interface *ifp)
         * address assigned, then try to create a vif_index.
         */
        if (pim_ifp->mroute_vif_index < 0) {
-               pim_if_add_vif(ifp, false, false /*vxlan_term*/);
+               vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
+               pim_if_add_vif(ifp, false, vxlan_term);
        }
        pim_ifchannel_scan_forward_start(ifp);
 
index bd6998c4b8c5081577bf027c641a86db4df459f8..1de0dda9dad77128204f16e64f0a787aafa99ef0 100644 (file)
@@ -1012,6 +1012,45 @@ static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
        }
 }
 
+static void pim_vxlan_term_mr_oif_update(struct hash_backet *backet, void *arg)
+{
+       struct interface *ifp = (struct interface *)arg;
+       struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+
+       if (pim_vxlan_is_orig_mroute(vxlan_sg))
+               return;
+
+       if (vxlan_sg->term_oif == ifp)
+               return;
+
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("vxlan SG %s term oif changed from %s to %s",
+                       vxlan_sg->sg_str,
+                       vxlan_sg->term_oif ? vxlan_sg->term_oif->name : "-",
+                       ifp ? ifp->name : "-");
+
+       pim_vxlan_term_mr_del(vxlan_sg);
+       vxlan_sg->term_oif = ifp;
+       pim_vxlan_term_mr_add(vxlan_sg);
+}
+
+static void pim_vxlan_term_oif_update(struct pim_instance *pim,
+               struct interface *ifp)
+{
+       if (pim->vxlan.term_if == ifp)
+               return;
+
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("vxlan term oif changed from %s to %s",
+                       pim->vxlan.term_if ? pim->vxlan.term_if->name : "-",
+                       ifp ? ifp->name : "-");
+
+       pim->vxlan.term_if = ifp;
+       if (pim->vxlan.sg_hash)
+               hash_iterate(pim->vxlan.sg_hash,
+                               pim_vxlan_term_mr_oif_update, ifp);
+}
+
 void pim_vxlan_add_vif(struct interface *ifp)
 {
        struct pim_interface *pim_ifp = ifp->info;
@@ -1026,6 +1065,9 @@ void pim_vxlan_add_vif(struct interface *ifp)
        if (vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED &&
                        (ifp == vxlan_mlag.peerlink_rif))
                pim_vxlan_set_peerlink_rif(pim, ifp);
+
+       if (pim->vxlan.term_if_cfg == ifp)
+               pim_vxlan_term_oif_update(pim, ifp);
 }
 
 void pim_vxlan_del_vif(struct interface *ifp)
@@ -1041,76 +1083,56 @@ void pim_vxlan_del_vif(struct interface *ifp)
 
        if (pim->vxlan.peerlink_rif == ifp)
                pim_vxlan_set_peerlink_rif(pim, NULL);
-}
-
-static void pim_vxlan_term_mr_oif_update(struct hash_backet *backet, void *arg)
-{
-       struct interface *ifp = (struct interface *)arg;
-       struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
-
-       if (pim_vxlan_is_orig_mroute(vxlan_sg))
-               return;
-
-       if (vxlan_sg->term_oif == ifp)
-               return;
-
-       if (PIM_DEBUG_VXLAN)
-               zlog_debug("vxlan SG %s term oif changed from %s to %s",
-                       vxlan_sg->sg_str,
-                       vxlan_sg->term_oif ? vxlan_sg->term_oif->name : "-",
-                       ifp ? ifp->name : "-");
 
-       pim_vxlan_term_mr_del(vxlan_sg);
-       vxlan_sg->term_oif = ifp;
-       pim_vxlan_term_mr_add(vxlan_sg);
+       if (pim->vxlan.term_if == ifp)
+               pim_vxlan_term_oif_update(pim, NULL);
 }
 
+/* enable pim implicitly on the termination device add */
 void pim_vxlan_add_term_dev(struct pim_instance *pim,
                struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
 
-       if (pim->vxlan.term_if == ifp)
+       if (pim->vxlan.term_if_cfg == ifp)
                return;
 
        if (PIM_DEBUG_VXLAN)
-               zlog_debug("vxlan term oif changed from %s to %s",
-                       pim->vxlan.term_if ? pim->vxlan.term_if->name : "-",
-                       ifp->name);
+               zlog_debug("vxlan term oif cfg changed from %s to %s",
+                               pim->vxlan.term_if_cfg ?
+                               pim->vxlan.term_if_cfg->name : "-",
+                               ifp->name);
+
+       pim->vxlan.term_if_cfg = ifp;
 
        /* enable pim on the term ifp */
        pim_ifp = (struct pim_interface *)ifp->info;
        if (pim_ifp) {
                PIM_IF_DO_PIM(pim_ifp->options);
+               /* ifp is already oper up; activate it as a term dev */
+               if (pim_ifp->mroute_vif_index >= 0)
+                       pim_vxlan_term_oif_update(pim, ifp);
        } else {
-               pim_ifp = pim_if_new(ifp, false /*igmp*/, true /*pim*/,
-                               false /*pimreg*/, true /*vxlan_term*/);
-               /* ensure that pimreg existss before using the newly created
+               /* ensure that pimreg exists before using the newly created
                 * vxlan termination device
                 */
                pim_if_create_pimreg(pim);
+               pim_ifp = pim_if_new(ifp, false /*igmp*/, true /*pim*/,
+                               false /*pimreg*/, true /*vxlan_term*/);
        }
-
-       pim->vxlan.term_if = ifp;
-
-       if (pim->vxlan.sg_hash)
-               hash_iterate(pim_ifp->pim->vxlan.sg_hash,
-                               pim_vxlan_term_mr_oif_update, ifp);
 }
 
+/* disable pim implicitly, if needed, on the termination device deletion */
 void pim_vxlan_del_term_dev(struct pim_instance *pim)
 {
-       struct interface *ifp = pim->vxlan.term_if;
+       struct interface *ifp = pim->vxlan.term_if_cfg;
        struct pim_interface *pim_ifp;
 
        if (PIM_DEBUG_VXLAN)
-               zlog_debug("vxlan term oif changed from %s to -", ifp->name);
+               zlog_debug("vxlan term oif cfg changed from %s to -",
+                               ifp->name);
 
-       pim->vxlan.term_if = NULL;
-
-       if (pim->vxlan.sg_hash)
-               hash_iterate(pim->vxlan.sg_hash,
-                               pim_vxlan_term_mr_oif_update, NULL);
+       pim->vxlan.term_if_cfg = NULL;
 
        pim_ifp = (struct pim_interface *)ifp->info;
        if (pim_ifp) {
@@ -1118,7 +1140,6 @@ void pim_vxlan_del_term_dev(struct pim_instance *pim)
                if (!PIM_IF_TEST_IGMP(pim_ifp->options))
                        pim_if_delete(ifp);
        }
-
 }
 
 void pim_vxlan_init(struct pim_instance *pim)
index 7adba2eee2d029f348a69a504b42522aaf4e62f0..198d1c3281dc4d63744fa2a43f8644e9242fbd77 100644 (file)
@@ -119,6 +119,12 @@ static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)
                if_is_loopback_or_vrf(up->rpf.source_nexthop.interface);
 }
 
+static inline bool pim_vxlan_is_term_dev_cfg(struct pim_instance *pim,
+                       struct interface *ifp)
+{
+       return pim->vxlan.term_if_cfg == ifp;
+}
+
 extern struct pim_vxlan *pim_vxlan_p;
 extern struct pim_vxlan_sg *pim_vxlan_sg_find(struct pim_instance *pim,
                                            struct prefix_sg *sg);
index 3f99483fbe19c4a2841699231a36bb3b4f0afb17..5b35bcbeaa51cd627413eecd7fe078424e073f69 100644 (file)
@@ -36,6 +36,7 @@ struct pim_vxlan_instance {
        /* device used by the dataplane to terminate multicast encapsulated
         * vxlan traffic
         */
+       struct interface *term_if_cfg;
        struct interface *term_if;
 };