summaryrefslogtreecommitdiff
path: root/pimd/pim_ifchannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_ifchannel.c')
-rw-r--r--pimd/pim_ifchannel.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index e7ff434f4b..cdaf7bcdd4 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -550,8 +550,21 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
struct pim_upstream *up;
ch = pim_ifchannel_find(ifp, sg);
- if (ch)
+ if (ch) {
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
+ PIM_IF_FLAG_SET_PROTO_PIM(ch->flags);
+
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags);
+
+ if (ch->upstream)
+ ch->upstream->flags |= up_flags;
+ else if (PIM_DEBUG_EVENTS)
+ zlog_debug("%s:%s No Upstream found", __func__,
+ pim_str_sg_dump(sg));
+
return ch;
+ }
pim_ifp = ifp->info;
@@ -642,6 +655,12 @@ static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)
{
pim_forward_stop(ch, !ch_del);
pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
+
+ if (ch->upstream)
+ PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags);
+
+ PIM_IF_FLAG_UNSET_PROTO_PIM(ch->flags);
+
if (ch_del)
delete_on_noinfo(ch);
}
@@ -710,6 +729,21 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
pim_jp_agg_single_upstream_send(&parent->rpf,
parent, true);
+ /*
+ * SGRpt prune pending expiry has to install
+ * SG entry with empty olist to drop the SG
+ * traffic incase no other intf exists.
+ * On that scenario, SG entry wouldn't have
+ * got installed until Prune pending timer
+ * expired. So install now.
+ */
+ pim_channel_del_oif(
+ ch->upstream->channel_oil, ifp,
+ PIM_OIF_FLAG_PROTO_STAR, __func__);
+ if (!ch->upstream->channel_oil->installed)
+ pim_upstream_mroute_add(
+ ch->upstream->channel_oil,
+ __PRETTY_FUNCTION__);
}
}
/* from here ch may have been deleted */
@@ -1094,6 +1128,24 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
case PIM_IFJOIN_PRUNE:
if (source_flags & PIM_ENCODE_RPT_BIT) {
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
+ /*
+ * While in Prune State, Receive SGRpt Prune.
+ * RFC 7761 Sec 4.5.3:
+ * The (S,G,rpt) downstream state machine on interface I
+ * remains in Prune state. The Expiry Timer (ET) is
+ * restarted and is then set to the maximum of its
+ * current value and the HoldTime from the triggering
+ * Join/Prune message.
+ */
+ if (ch->t_ifjoin_expiry_timer) {
+ unsigned long rem = thread_timer_remain_second(
+ ch->t_ifjoin_expiry_timer);
+
+ if (rem > holdtime)
+ return;
+ THREAD_OFF(ch->t_ifjoin_expiry_timer);
+ }
+
thread_add_timer(router->master, on_ifjoin_expiry_timer,
ch, holdtime,
&ch->t_ifjoin_expiry_timer);
@@ -1272,6 +1324,13 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
* parent' delete_no_info */
}
}
+
+ /* Resettng the IGMP flags here */
+ if (orig->upstream)
+ PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(orig->upstream->flags);
+
+ PIM_IF_FLAG_UNSET_PROTO_IGMP(orig->flags);
+
delete_on_noinfo(orig);
}