From: saravanank Date: Tue, 17 Mar 2020 06:48:05 +0000 (-0700) Subject: pimd: Handling prune received during join state and join during prune pending X-Git-Tag: base_7.6~410^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=48484e587524e3f42dfc1e1d08d65c59af892668;p=mirror%2Ffrr.git pimd: Handling prune received during join state and join during prune pending 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 --- diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 44d4ee7192..d6a9ba266b 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -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);