mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:37:21 +00:00
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>
This commit is contained in:
parent
11913c322b
commit
60eb7e6b80
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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("<group?>",
|
||||
channel_oil->oil.mfcc_mcastgrp,
|
||||
group_str, sizeof(group_str));
|
||||
pim_inet4_dump("<source?>",
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user