]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Handling prune received during join state and join during prune pending
authorsaravanank <saravanank@vmware.com>
Tue, 17 Mar 2020 06:48:05 +0000 (23:48 -0700)
committersaravanank <saravanank@vmware.com>
Wed, 18 Mar 2020 02:12:28 +0000 (19:12 -0700)
RCA:
1. Prune processing during join state was putting of join expiry timer
2. Join received during prune pending state was not comparing hold time with remaining expiry timer.

Fix:
Fixed as per RFC 4601/7761

Signed-off-by: Saravanan K <saravanank@vmware.com>
pimd/pim_ifchannel.c

index 44d4ee7192bd1b62610b198d31ab238dd31d35db..d6a9ba266be7e3bd9ef7b68904bccaadcda14dee 100644 (file)
@@ -944,14 +944,41 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                        pim_ifchannel_ifjoin_handler(ch, pim_ifp);
                break;
        case PIM_IFJOIN_PRUNE_PENDING:
+               /*
+                * Transitions from Prune-Pending State (Receive Join)
+                * RFC 7761 Sec 4.5.2:
+                *    The (S,G) downstream state machine on interface I
+                * transitions to the Join state.  The Prune-Pending Timer is
+                * canceled (without triggering an expiry event).  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.
+                */
                THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
                if (source_flags & PIM_ENCODE_RPT_BIT) {
+                       /*
+                        * Transitions from Prune-Pending State (Rcv SGRpt Join)
+                        * RFC 7761 Sec 4.5.3:
+                        * The (S,G,rpt) downstream state machine on interface
+                        * I transitions to the NoInfo state.The ET and PPT are
+                        * cancelled.
+                        */
                        THREAD_OFF(ch->t_ifjoin_expiry_timer);
                        pim_ifchannel_ifjoin_switch(__func__, ch,
                                                    PIM_IFJOIN_NOINFO);
-               } else {
-                       pim_ifchannel_ifjoin_handler(ch, pim_ifp);
+                       return;
                }
+
+               pim_ifchannel_ifjoin_handler(ch, pim_ifp);
+
+               if (ch->t_ifjoin_expiry_timer) {
+                       unsigned long remain = thread_timer_remain_second(
+                               ch->t_ifjoin_expiry_timer);
+
+                       if (remain > holdtime)
+                               return;
+               }
+
                break;
        case PIM_IFJOIN_PRUNE_TMP:
                break;
@@ -1028,7 +1055,14 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
                /* nothing to do */
                break;
        case PIM_IFJOIN_JOIN:
-               THREAD_OFF(ch->t_ifjoin_expiry_timer);
+               /*
+                * The (S,G) downstream state machine on interface I
+                * transitions to the Prune-Pending state.  The
+                * Prune-Pending Timer is started.  It is set to the
+                * J/P_Override_Interval(I) if the router has more than one
+                * neighbor on that interface; otherwise, it is set to zero,
+                * causing it to expire immediately.
+                */
 
                pim_ifchannel_ifjoin_switch(__func__, ch,
                                            PIM_IFJOIN_PRUNE_PENDING);