From 9443810eef5d2de2d932600cf058ee030baa6d47 Mon Sep 17 00:00:00 2001 From: Sarita Patra Date: Mon, 2 Mar 2020 00:55:22 -0800 Subject: pimd: fix OIL not removed after IGMP prune Issue: Client1------LHR-----(int-1)RP(int-2)------client2 Client2 send IGMP join for group G. Client1 send IGMP join for group G. verify show ip mroute in RP, will have 2 OIL. Client2 send IGMP leave. Verify show ip mroute in RP, will still have 2. Root cause: When RP receives IGMP join from client2, it creates a (s,g) channel oil and add the interface int-2 into oil list and set the flag PIM_OIF_FLAG_PROTO_IGMP to int-2 Client1 send IGMP join, LHR will send a (*,G) join to RP. RP will add the interface int-1 into the oil list of (s,g) channel_oil and will set the flag PIM_OIF_FLAG_PROTO_IGMP and PIM_OIF_FLAG_PROTO_PIM to the int-1 and set PIM_OIF_FLAG_PROTO_PIM to int-2 as well. It is happening because of the pim_upstream_inherited_olist_decide() and forward_on() get all the oil and update the flag wrongly. So now when client 2 sends IGMP prune, RP will not remove the int-2 from oil list since both PIM_OIF_FLAG_PROTO_PIM & PIM_OIF_FLAG_PROTO_IGMP are set, it just unset the flag PIM_OIF_FLAG_PROTO_IGMP. Fix: Introduced new flags in if_channel, PIM_IF_FLAG_MASK_PROTO_PIM & PIM_IF_FLAG_MASK_PROTO_IGMP. If a if_channel is created because of pim join or pim (s,g,rpt) prune received, then set the flag PIM_IF_FLAG_MASK_PROTO_PIM. If a if_channel is created becuase of IGMP join received, then set the flag PIM_IF_FLAG_MASK_PROTO_IGMP. When an interface needs to be added into the oil list check if PIM_IF_FLAG_MASK_PROTO_PIM or PIM_IF_FLAG_MASK_PROTO_IGMP is set, then update oil flag accordingly. Signed-off-by: Sarita Patra --- pimd/pim_zebra.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'pimd/pim_zebra.c') diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e791500ede..8355c2099d 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -835,7 +835,7 @@ void igmp_source_forward_stop(struct igmp_source *source) void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + uint32_t mask = 0; if (PIM_DEBUG_PIM_TRACE) { char source_str[INET_ADDRSTRLEN]; @@ -853,9 +853,12 @@ void pim_forward_start(struct pim_ifchannel *ch) inet_ntoa(up->upstream_addr)); } - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) mask = PIM_OIF_FLAG_PROTO_IGMP; + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + mask |= PIM_OIF_FLAG_PROTO_PIM; + pim_channel_add_oif(up->channel_oil, ch->interface, mask, __func__); } -- cgit v1.2.3