summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-06 09:31:00 -0800
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-02-14 09:18:30 -0800
commit650d9ad1acf68b1c017a54139bddf5888fe3c835 (patch)
tree86f4b707a864d02665c42d3ef7e26ff9f7cfddb2
parent20fcf61c376282fb94b894dbe1c61a8136cca039 (diff)
pimd: handle ipmr-lo operational state changes
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>
-rw-r--r--pimd/pim_iface.c8
-rw-r--r--pimd/pim_vxlan.c105
-rw-r--r--pimd/pim_vxlan.h6
-rw-r--r--pimd/pim_vxlan_instance.h1
4 files changed, 76 insertions, 44 deletions
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index c615540149..8cc720c535 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -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);
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index bd6998c4b8..1de0dda9da 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -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)
diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h
index 7adba2eee2..198d1c3281 100644
--- a/pimd/pim_vxlan.h
+++ b/pimd/pim_vxlan.h
@@ -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);
diff --git a/pimd/pim_vxlan_instance.h b/pimd/pim_vxlan_instance.h
index 3f99483fbe..5b35bcbeaa 100644
--- a/pimd/pim_vxlan_instance.h
+++ b/pimd/pim_vxlan_instance.h
@@ -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;
};