From 60eb7e6b803910dae00217009ded98d7c93186cd Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Fri, 15 Nov 2019 11:46:04 -0800 Subject: [PATCH] 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 --- pimd/pim_cmd.c | 5 +++++ pimd/pim_mroute.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_mroute.h | 2 ++ pimd/pim_oil.c | 43 ------------------------------------------- 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 25ea42473b..e49566089f 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5405,6 +5405,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, & PIM_OIF_FLAG_MUTE) continue; + if (c_oil->oil.mfcc_parent == oif_vif_index && + !pim_mroute_allow_iif_in_oil(c_oil, + oif_vif_index)) + continue; + ifp_out = pim_if_find_by_vif_index(pim, oif_vif_index); pim_time_uptime( mroute_uptime, sizeof(mroute_uptime), 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 diff --git a/pimd/pim_mroute.h b/pimd/pim_mroute.h index eadd39eece..2d8e1b01fb 100644 --- a/pimd/pim_mroute.h +++ b/pimd/pim_mroute.h @@ -183,4 +183,6 @@ void pim_static_mroute_iif_update(struct channel_oil *c_oil, int pim_mroute_del(struct channel_oil *c_oil, const char *name); void pim_mroute_update_counters(struct channel_oil *c_oil); +bool pim_mroute_allow_iif_in_oil(struct channel_oil *c_oil, + int oif_index); #endif /* PIM_MROUTE_H */ diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index ed404ba498..178ba27bc8 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -460,7 +460,6 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, { struct pim_interface *pim_ifp; int old_ttl; - bool allow_iif_in_oil = false; /* * If we've gotten here we've gone bad, but let's @@ -473,48 +472,6 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif, pim_ifp = oif->info; -#ifdef PIM_ENFORCE_LOOPFREE_MFC - /* - 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. - */ - if ((channel_oil->up && - PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(channel_oil->up->flags)) || - ((proto_mask == PIM_OIF_FLAG_PROTO_IGMP) && PIM_I_am_DR(pim_ifp))) { - allow_iif_in_oil = true; - } - - if (!allow_iif_in_oil && - pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) { - channel_oil->oil_inherited_rescan = 1; - if (PIM_DEBUG_MROUTE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("", - channel_oil->oil.mfcc_mcastgrp, - group_str, sizeof(group_str)); - pim_inet4_dump("", - channel_oil->oil.mfcc_origin, source_str, - sizeof(source_str)); - zlog_debug( - "%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, proto_mask, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -2; - } -#endif - /* Prevent single protocol from subscribing same interface to channel (S,G) multiple times */ if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {