]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Fix for data packet loss when FHR is LHR and RP 18204/head
authorRajesh Varatharaj <rvaratharaj@nvidia.com>
Thu, 17 Aug 2023 20:11:42 +0000 (13:11 -0700)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Thu, 20 Feb 2025 16:57:15 +0000 (16:57 +0000)
Topology:
A single router is acting as the First Hop Router (FHR), Last Hop Router (LHR), and RP.

RC and Issue:
When an upstream S,G is in join state, it sends a register message to the RP.
If the RP has the receiver, it sends a register stop message and switches to the shortest path.
When the register stop message is processed, it removes pimreg, moves to prune,
and starts the reg stop timer.

When the reg stop timer expires, PIM changes S,G state to Join Pending and sends out a NULL
register message to RP. RP receives it and fails to send Reg stop because SPT is not set at that point.

The problem is when the register stop timer pops and state is in Join Pending.
According to https://www.rfc-editor.org/rfc/rfc4601#section-4.4.1,
we need to put back the pimreg reg tunnel into the S,G mroute.
This causes data to be sent to the control plane and subsequently interrupts the line rate.

Fix:
If the router is FHR and RP to the group,
ignore SPT status and send out a register stop message back to the DR (in this context, the same router).

Ticket: #3506780

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Signed-off-by: Rajesh Varatharaj <rvaratharaj@nvidia.com>
(cherry picked from commit 8280257cc99e071c205e469399f2fb41671b30eb)

pimd/pim_register.c

index b149b5a2a97c236ecd45167aebf00ec60a0388b5..ad0c71a23406c2ac13012195e60f1c52e3f0e21a 100644 (file)
@@ -186,8 +186,9 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
                 */
                for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) {
                        if (PIM_DEBUG_PIM_REG)
-                               zlog_debug("Executing Reg stop for %s",
-                                          child->sg_str);
+                               zlog_debug(
+                                       "Executing Reg stop for upstream child %s",
+                                       child->sg_str);
 
                        pim_reg_stop_upstream(pim, child);
                }
@@ -208,8 +209,9 @@ int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
                frr_each (rb_pim_upstream, &pim->upstream_head, up) {
                        if (pim_addr_cmp(up->sg.grp, sg.grp) == 0) {
                                if (PIM_DEBUG_PIM_REG)
-                                       zlog_debug("Executing Reg stop for %s",
-                                                  up->sg_str);
+                                       zlog_debug(
+                                               "Executing Reg stop for upstream %s",
+                                               up->sg_str);
                                pim_reg_stop_upstream(pim, up);
                        }
                }
@@ -682,9 +684,12 @@ int pim_register_recv(struct interface *ifp, pim_addr dest_addr,
                        }
                }
 
-               if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
-                   || ((SwitchToSptDesiredOnRp(pim, &sg))
-                       && pim_upstream_inherited_olist(pim, upstream) == 0)) {
+               if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
+                   (PIM_UPSTREAM_FLAG_TEST_FHR(upstream->flags) && i_am_rp) ||
+                   ((SwitchToSptDesiredOnRp(pim, &sg)) &&
+                    pim_upstream_inherited_olist(pim, upstream) == 0)) {
+                       zlog_debug("sending pim register stop message :  %s ",
+                                  upstream->sg_str);
                        pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
                        sentRegisterStop = 1;
                } else {