pimd: fix problem with oif being re-added during ifchannel del

Series of events leading to the problem -
1. (S,G) has been pruned on the rp on downlink-1
2. a (*,G) join is rxed on downlink-1 without the source S. This
results in the (S,G,rpt) prune state being cleared on downlink-1.
As a part of the clear the ifchannel associated with downlink-1
is deleted.
3. The ifchannel_delete handling is expected to add downlink-1
as an inherited OIF to the channel OIL (which it does). However
it is also added in as an immediate OIF (accidentally) as the
ifchannel is still present (in the process of being deleted).

To avoid the problem defer pim_upstream_update_join_desired
evaluation until after the channel is deleted.

Relevant debug logs -
PIM: pim_ifchannel_delete: ifchannel entry (27.0.0.15,239.1.1.106)(downlink-1) del start
PIM: pim_channel_add_oif(pim_ifchannel_delete): (S,G)=(27.0.0.15,239.1.1.106): proto_mask=4 OIF=downlink-1 vif_index=7: DONE
PIM: pimd/pim_oil.c pim_channel_del_oif: no existing protocol mask 2(4) for requested OIF downlink-1 (vif_index=7, min_ttl=1) for channel (S,G)=(27.0.0.15,239.1.1.106)
PIM: pim_upstream_switch: PIM_UPSTREAM_(27.0.0.15,239.1.1.106): (S,G) old: NotJoined new: Joined
PIM: pim_channel_add_oif(pim_upstream_inherited_olist_decide): (S,G)=(27.0.0.15,239.1.1.106): proto_mask=2 OIF=downlink-1 vif_index=7 added to 0x6  >>>>>>>>>>>>>>>>>>
PIM: pim_upstream_del(pim_ifchannel_delete): Delete (27.0.0.15,239.1.1.106)[default] ref count: 2 , flags: 81 c_oil ref count 1 (Pre decrement)
PIM: pim_ifchannel_delete: ifchannel entry (27.0.0.15,239.1.1.106)(downlink-1) del end

Ticket: CM-26732

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
Anuradha Karuppiah 2019-10-14 16:02:36 -07:00 committed by Donald Sharp
parent b900ad16ee
commit 0f31a82a11

View File

@ -128,6 +128,7 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
void pim_ifchannel_delete(struct pim_ifchannel *ch)
{
struct pim_interface *pim_ifp;
struct pim_upstream *up;
pim_ifp = ch->interface->info;
@ -201,14 +202,14 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
listnode_delete(ch->upstream->ifchannels, ch);
pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
up = ch->upstream;
/* upstream is common across ifchannels, check if upstream's
ifchannel list is empty before deleting upstream_del
ref count will take care of it.
*/
if (ch->upstream->ref_count > 0)
pim_upstream_del(pim_ifp->pim, ch->upstream, __func__);
up = pim_upstream_del(pim_ifp->pim, ch->upstream, __func__);
else {
if (PIM_DEBUG_PIM_TRACE)
@ -237,6 +238,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
ch->sg_str);
XFREE(MTYPE_PIM_IFCHANNEL, ch);
if (up)
pim_upstream_update_join_desired(pim_ifp->pim, up);
}
void pim_ifchannel_delete_all(struct interface *ifp)