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) {