]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: update vxlan mroute entries when the lo or peerlink vif is updated
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Sat, 23 Mar 2019 15:25:20 +0000 (08:25 -0700)
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Sat, 20 Apr 2019 15:33:23 +0000 (08:33 -0700)
For vxlan origination mroutes the IIF is pinned to
a. lo for single VTEPs
b. peerlink-rif for anycast VTEPs

This commit includes the changes to react to  pim-vifi add/del for these
devices.

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

index a7b5511f3536add3789e297e4b5bf095d601aee5..0fb7f176ce8e843989b56ee21f5ba0d469060bf5 100644 (file)
@@ -47,6 +47,7 @@
 #include "pim_nht.h"
 #include "pim_jp_agg.h"
 #include "pim_igmp_join.h"
+#include "pim_vxlan.h"
 
 static void pim_if_igmp_join_del_all(struct interface *ifp);
 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
@@ -977,6 +978,10 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
        }
 
        pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
+
+       /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
+       pim_vxlan_add_vif(ifp);
+
        return 0;
 }
 
@@ -991,6 +996,9 @@ int pim_if_del_vif(struct interface *ifp)
                return -1;
        }
 
+       /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
+       pim_vxlan_del_vif(ifp);
+
        pim_mroute_del_vif(ifp);
 
        /*
index b51329ea86f68bf28b89c52d014536e2bc0a5403..02878b50537c61255ab6a2b6b65ec071039aff3e 100644 (file)
@@ -468,6 +468,34 @@ static void pim_vxlan_orig_mr_del(struct pim_vxlan_sg *vxlan_sg)
        pim_vxlan_orig_mr_up_del(vxlan_sg);
 }
 
+static void pim_vxlan_orig_mr_iif_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;
+       struct interface *old_iif = vxlan_sg->iif;
+
+       if (!pim_vxlan_is_orig_mroute(vxlan_sg))
+               return;
+
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("vxlan SG %s iif changed from %s to %s",
+                               vxlan_sg->sg_str,
+                               old_iif ? old_iif->name : "-",
+                               ifp ? ifp->name : "-");
+
+       if (pim_vxlan_orig_mr_add_is_ok(vxlan_sg)) {
+               if (vxlan_sg->up) {
+                       /* upstream exists but iif changed */
+                       pim_vxlan_orig_mr_up_iif_update(vxlan_sg);
+               } else {
+                       /* install mroute */
+                       pim_vxlan_orig_mr_install(vxlan_sg);
+               }
+       } else {
+               pim_vxlan_orig_mr_del(vxlan_sg);
+       }
+}
+
 /**************************** vxlan termination mroutes ***********************
  * For every bum-mcast-grp registered by evpn a *G termination
  * mroute is setup by pimd. The purpose of this mroute is to pull down vxlan
@@ -682,6 +710,102 @@ void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg)
        XFREE(MTYPE_PIM_VXLAN_SG, vxlan_sg);
 }
 
+/****************************** misc callbacks *******************************/
+static void pim_vxlan_set_default_iif(struct pim_instance *pim,
+                               struct interface *ifp)
+{
+       struct interface *old_iif;
+
+       if (pim->vxlan.default_iif == ifp)
+               return;
+
+       old_iif = pim->vxlan.default_iif;
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("%s: vxlan default iif changed from %s to %s",
+                       __PRETTY_FUNCTION__,
+                       old_iif ? old_iif->name : "-",
+                       ifp ? ifp->name : "-");
+
+       old_iif = pim_vxlan_orig_mr_iif_get(pim);
+       pim->vxlan.default_iif = ifp;
+       ifp = pim_vxlan_orig_mr_iif_get(pim);
+       if (old_iif == ifp)
+               return;
+
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("%s: vxlan orig iif changed from %s to %s",
+                       __PRETTY_FUNCTION__, old_iif ? old_iif->name : "-",
+                       ifp ? ifp->name : "-");
+
+       /* add/del upstream entries for the existing vxlan SG when the
+        * interface becomes available
+        */
+       hash_iterate(pim->vxlan.sg_hash, pim_vxlan_orig_mr_iif_update, ifp);
+}
+
+static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
+                       struct interface *ifp)
+{
+       struct interface *old_iif;
+
+       if (pim->vxlan.peerlink_rif == ifp)
+               return;
+
+       old_iif = pim->vxlan.peerlink_rif;
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("%s: vxlan peerlink_rif changed from %s to %s",
+                       __PRETTY_FUNCTION__, old_iif ? old_iif->name : "-",
+                       ifp ? ifp->name : "-");
+
+       old_iif = pim_vxlan_orig_mr_iif_get(pim);
+       pim->vxlan.peerlink_rif = ifp;
+       ifp = pim_vxlan_orig_mr_iif_get(pim);
+       if (old_iif == ifp)
+               return;
+
+       if (PIM_DEBUG_VXLAN)
+               zlog_debug("%s: vxlan orig iif changed from %s to %s",
+                       __PRETTY_FUNCTION__, old_iif ? old_iif->name : "-",
+                       ifp ? ifp->name : "-");
+
+       /* add/del upstream entries for the existing vxlan SG when the
+        * interface becomes available
+        */
+       hash_iterate(pim->vxlan.sg_hash, pim_vxlan_orig_mr_iif_update, ifp);
+}
+
+void pim_vxlan_add_vif(struct interface *ifp)
+{
+       struct pim_interface *pim_ifp = ifp->info;
+       struct pim_instance *pim = pim_ifp->pim;
+
+       pim = ((struct pim_interface *)ifp->info)->pim;
+       if (pim->vrf_id != VRF_DEFAULT)
+               return;
+
+       if (if_is_loopback_or_vrf(ifp))
+               pim_vxlan_set_default_iif(pim, ifp);
+
+       if (vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED &&
+                       (ifp == vxlan_mlag.peerlink_rif))
+               pim_vxlan_set_peerlink_rif(pim, ifp);
+}
+
+void pim_vxlan_del_vif(struct interface *ifp)
+{
+       struct pim_interface *pim_ifp = ifp->info;
+       struct pim_instance *pim = pim_ifp->pim;
+
+       if (pim->vrf_id != VRF_DEFAULT)
+               return;
+
+       if (pim->vxlan.default_iif == ifp)
+               pim_vxlan_set_default_iif(pim, NULL);
+
+       if (pim->vxlan.peerlink_rif == ifp)
+               pim_vxlan_set_peerlink_rif(pim, NULL);
+}
+
 void pim_vxlan_init(struct pim_instance *pim)
 {
        char hash_name[64];
index ad84fa8e04014cc115562af64db04fc01d419113..0a6e409c73495e48c85322ad679fb3bbb28458e6 100644 (file)
@@ -123,5 +123,7 @@ extern void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg);
 extern void pim_vxlan_update_sg_reg_state(struct pim_instance *pim,
                struct pim_upstream *up, bool reg_join);
 extern struct pim_interface *pim_vxlan_get_term_ifp(struct pim_instance *pim);
+extern void pim_vxlan_add_vif(struct interface *ifp);
+extern void pim_vxlan_del_vif(struct interface *ifp);
 
 #endif /* PIM_VXLAN_H */