summaryrefslogtreecommitdiffstats
path: root/pimd
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-03-23 16:25:20 +0100
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-04-20 17:33:23 +0200
commit269c1fe1e75a8ca7c73680b81641d7e05efc4335 (patch)
tree1230e791a88ac853193963664b4f8dd90d086aa6 /pimd
parentpimd: add termination mroutes for each vxlan multicast tunnels (diff)
downloadfrr-269c1fe1e75a8ca7c73680b81641d7e05efc4335.tar.xz
frr-269c1fe1e75a8ca7c73680b81641d7e05efc4335.zip
pimd: update vxlan mroute entries when the lo or peerlink vif is updated
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>
Diffstat (limited to 'pimd')
-rw-r--r--pimd/pim_iface.c8
-rw-r--r--pimd/pim_vxlan.c124
-rw-r--r--pimd/pim_vxlan.h2
3 files changed, 134 insertions, 0 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index a7b5511f3..0fb7f176c 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -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);
/*
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index b51329ea8..02878b505 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -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];
diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h
index ad84fa8e0..0a6e409c7 100644
--- a/pimd/pim_vxlan.h
+++ b/pimd/pim_vxlan.h
@@ -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 */