]> git.proxmox.com Git - mirror_frr.git/commitdiff
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
authorSarita Patra <saritap@vmware.com>
Tue, 3 Mar 2020 09:51:03 +0000 (01:51 -0800)
committerSarita Patra <saritap@vmware.com>
Fri, 5 Jun 2020 04:49:07 +0000 (21:49 -0700)
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 <saritap@vmware.com>
pimd/pim_join.c

index fbb547c80e797e64b669321a91cba1e723199d1f..6ba18d540a83ffe2e28a37390a9572a1d8c9267d 100644 (file)
@@ -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);