summaryrefslogtreecommitdiff
path: root/pimd/pim_mroute.c
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-11-15 11:46:04 -0800
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2019-11-15 14:16:08 -0800
commit60eb7e6b803910dae00217009ded98d7c93186cd (patch)
tree0a7d4129b42fd27c94dbc21178b16a3ef0f2cfb7 /pimd/pim_mroute.c
parent11913c322be9ebb1f2a99806f182125d7036af7f (diff)
pimd: enforce PIM_ENFORCE_LOOPFREE_MFC at the time of MFC programming
This is needed for two reasons - 1. The inherited OIL needs to be setup independent of the RPF interface to allow correct computation of the JoinDesired macro. 2. The RPF interface is computed at the time of MFC programming so it is not possible to permanently evict the OIF at that time oif_add Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Diffstat (limited to 'pimd/pim_mroute.c')
-rw-r--r--pimd/pim_mroute.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 7b8ea5f7f7..39ced27278 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -878,6 +878,46 @@ int pim_mroute_del_vif(struct interface *ifp)
return 0;
}
+/*
+ * Prevent creating MFC entry with OIF=IIF.
+ *
+ * This is a protection against implementation mistakes.
+ *
+ * PIM protocol implicitely ensures loopfree multicast topology.
+ *
+ * IGMP must be protected against adding looped MFC entries created
+ * by both source and receiver attached to the same interface. See
+ * TODO T22.
+ * We shall allow igmp to create upstream when it is DR for the intf.
+ * Assume RP reachable via non DR.
+ */
+bool pim_mroute_allow_iif_in_oil(struct channel_oil *c_oil,
+ int oif_index)
+{
+#ifdef PIM_ENFORCE_LOOPFREE_MFC
+ struct interface *ifp_out;
+ struct pim_interface *pim_ifp;
+
+ if (c_oil->up &&
+ PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(c_oil->up->flags))
+ return true;
+
+ ifp_out = pim_if_find_by_vif_index(c_oil->pim, oif_index);
+ if (!ifp_out)
+ return false;
+ pim_ifp = ifp_out->info;
+ if (!pim_ifp)
+ return false;
+ if ((c_oil->oif_flags[oif_index] & PIM_OIF_FLAG_PROTO_IGMP) &&
+ PIM_I_am_DR(pim_ifp))
+ return true;
+
+ return false;
+#else
+ return true;
+#endif
+}
+
static inline void pim_mroute_copy(struct mfcctl *oil,
struct channel_oil *c_oil)
{
@@ -888,6 +928,12 @@ static inline void pim_mroute_copy(struct mfcctl *oil,
oil->mfcc_parent = c_oil->oil.mfcc_parent;
for (i = 0; i < MAXVIFS; ++i) {
+ if ((oil->mfcc_parent == i) &&
+ !pim_mroute_allow_iif_in_oil(c_oil, i)) {
+ oil->mfcc_ttls[i] = 0;
+ continue;
+ }
+
if (c_oil->oif_flags[i] & PIM_OIF_FLAG_MUTE)
oil->mfcc_ttls[i] = 0;
else