From: Sarita Patra Date: Tue, 3 Mar 2020 09:51:03 +0000 (-0800) Subject: pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received X-Git-Tag: frr-8.0.1~1021^2 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=fa8c500f547ee96475be0fd993d36ab47f59d463;p=mirror_frr.git pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received Issue: After SPT switchover, do shut and no-shut the received connected interface, traffic stops. R2 | | + + Client-----R1--------R3----Source R2 is RP. Root cause: Client is sending join for G and Source is sending traffic for G. Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover, traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets created. first is (*, G) ifchannel which gets created because of (*, G) join received from R1, second is (S, G) ifchannel which gets created because of (s,g,rpt) prune received from R1 Shut the receiver connected interface on R1, R1 will send a (*, G) prune towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel. (s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer expires. Before this timer expires, do noshut the received connected inrterface on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G), but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow stops. Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune received, as (*,G) prune indicates that the router no longer wishes to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G) ifchannel, which was created because of (S,G,RPT) prune received Signed-off-by: Sarita Patra --- diff --git a/pimd/pim_join.c b/pimd/pim_join.c index fbb547c80..6ba18d540 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -170,6 +170,8 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, uint8_t *pastend; int remain; int group; + struct pim_ifchannel *child = NULL; + struct listnode *ch_node, *nch_node; buf = tlv_buf; pastend = tlv_buf + tlv_buf_size; @@ -335,9 +337,24 @@ int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh, */ sg_ch = pim_ifchannel_find(ifp, &sg); + if (!sg_ch) + continue; + + /* (*,G) prune received */ + for (ALL_LIST_ELEMENTS(sg_ch->sources, ch_node, + nch_node, child)) { + if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) { + if (child->ifjoin_state + == PIM_IFJOIN_PRUNE_PENDING_TMP) + THREAD_OFF( + child->t_ifjoin_prune_pending_timer); + PIM_IF_FLAG_UNSET_S_G_RPT(child->flags); + child->ifjoin_state = PIM_IFJOIN_NOINFO; + } + } + /* Received SG-RPT Prune delete oif from specific S,G */ - if (starg_ch && sg_ch - && (msg_source_flags & PIM_RPT_BIT_MASK) + if (starg_ch && (msg_source_flags & PIM_RPT_BIT_MASK) && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) { struct pim_upstream *up = sg_ch->upstream; PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags);