diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ac53808af3..182cf33223 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -162,10 +162,10 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources, up_node, child)) - pim_channel_del_oif(child->channel_oil, - ch->interface, - PIM_OIF_FLAG_PROTO_STAR, - __func__); + pim_channel_del_inherited_oif( + child->channel_oil, + ch->interface, + __func__); } } @@ -305,9 +305,8 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, */ if (c_oil->oil.mfcc_ttls [pim_ifp->mroute_vif_index]) - pim_channel_del_oif( + pim_channel_del_inherited_oif( c_oil, ch->interface, - PIM_OIF_FLAG_PROTO_STAR, __func__); } } @@ -1182,24 +1181,19 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, child->sg_str); ch = pim_ifchannel_find(ifp, &child->sg); - if (c_oil - && !pim_upstream_evaluate_join_desired_interface( - child, ch, starch)) - pim_channel_del_oif(c_oil, ifp, - PIM_OIF_FLAG_PROTO_STAR, - __func__); - /* * If the S,G has no if channel and the c_oil still * has output here then the *,G was supplying the * implied * if channel. So remove it. */ - if (!chchannel && c_oil - && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]) - pim_channel_del_oif(c_oil, ifp, - PIM_OIF_FLAG_PROTO_STAR, - __func__); + if (!pim_upstream_evaluate_join_desired_interface( + child, ch, starch) || + (!chchannel && + c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])) { + pim_channel_del_inherited_oif(c_oil, ifp, + __func__); + } /* Child node removal/ref count-- will happen as part of * parent' delete_no_info */ diff --git a/pimd/pim_join.c b/pimd/pim_join.c index fcd93bcf24..53bfb28228 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -337,10 +337,9 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, "%s: SGRpt flag is set, del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str); - pim_channel_del_oif( + pim_channel_del_inherited_oif( up->channel_oil, starg_ch->interface, - PIM_OIF_FLAG_PROTO_STAR, __func__); } } diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index ed4ef6e700..ed404ba498 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -352,6 +352,21 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif, return 0; } +void pim_channel_del_inherited_oif(struct channel_oil *c_oil, + struct interface *oif, const char *caller) +{ + struct pim_upstream *up = c_oil->up; + + pim_channel_del_oif(c_oil, oif, PIM_OIF_FLAG_PROTO_STAR, + caller); + + /* if an inherited OIF is being removed join-desired can change + * if the inherited OIL is now empty and KAT is running + */ + if (up && up->sg.src.s_addr != INADDR_ANY && + pim_upstream_empty_inherited_olist(up)) + pim_upstream_update_join_desired(up->pim, up); +} static bool pim_channel_eval_oif_mute(struct channel_oil *c_oil, struct pim_interface *pim_ifp) diff --git a/pimd/pim_oil.h b/pimd/pim_oil.h index 20c94b65bc..de7fde05da 100644 --- a/pimd/pim_oil.h +++ b/pimd/pim_oil.h @@ -136,4 +136,7 @@ void pim_channel_update_oif_mute(struct channel_oil *c_oil, struct pim_interface *pim_ifp); void pim_channel_oil_upstream_deref(struct channel_oil *c_oil); +void pim_channel_del_inherited_oif(struct channel_oil *c_oil, + struct interface *oif, const char *caller); + #endif /* PIM_OIL_H */