]> git.puffer.fish Git - matthieu/frr.git/commitdiff
pimd: Send immediate join( with possible SG RPT prune bit set
authorDonald Sharp <sharpd@nvidia.com>
Thu, 31 Mar 2022 17:07:06 +0000 (13:07 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Fri, 1 Apr 2022 13:01:38 +0000 (09:01 -0400)
When pimd has this setup:

src ----- rtr ------ receiver
           |
          rp

And the receiver sends a *,G join to rtr.  When the
src starts sending a S,G, rtr can wait up to one join/prune
interval before sending a S,G rpt prune.  This interval
causes the pimreg device to be in the S,G OIL as that the
RP does not know to prune this leg off.

before:

Timestamp: Thu Mar 31 10:15:18 2022 288767 usec
[MROUTE](10.103.0.5,239.0.0.4)           Iif: rtr-lan_src Oifs: rtr-lan  State: resolved Table: default
Timestamp: Thu Mar 31 10:15:18 2022 288777 usec
[MROUTE](10.103.0.5,239.0.0.4)           Iif: rtr-lan_src Oifs: rtr-lan rtr-lan-1  State: resolved Table: default
Timestamp: Thu Mar 31 10:15:18 2022 288789 usec
[MROUTE](10.103.0.5,239.0.0.4)           Iif: rtr-lan_src Oifs: pimreg rtr-lan rtr-lan-1  State: resolved Table: default
Timestamp: Thu Mar 31 10:15:49 2022 324995 usec
[MROUTE](10.103.0.5,239.0.0.4)           Iif: rtr-lan_src Oifs: rtr-lan rtr-lan-1  State: resolved Table: default
<31 seconds>

After:

Timestamp: Thu Mar 31 12:56:15 2022 501921 usec
(10.103.0.5,239.0.0.27)          Iif: rtr-lan_src Oifs: pimreg rtr-lan  State: resolved Table: default
Timestamp: Thu Mar 31 12:56:15 2022 501930 usec
(10.103.0.5,239.0.0.27)          Iif: rtr-lan_src Oifs: pimreg rtr-lan rtr-lan-1  State: resolved Table: default
Timestamp: Thu Mar 31 12:56:15 2022 502181 usec
(10.103.0.5,239.0.0.27)          Iif: rtr-lan_src Oifs: rtr-lan rtr-lan-1  State: resolved Table: default
<sub second>

What is actually happening:

rtr receives a *,G igmp join, sends a *,G join towards the rp
rtr receives a S,G packet <WRVIFWHOLE>
creates the S,G upstream, sends the register packet to the rp
the rp sees that it still has downstream interest so it forwards the packet on
After (up to 60 seconds ) the rtr, sends the normally scheduled join for
the G and sends the S,GRPT prune as part of it.

What is being done to fix it:

In wrvifwhole handling, when pimd detects that this is the FHR
and is not the RP *and* the incoming interface for the *,G
is different than the incomding interface for the S,G immediately
send a single join packet for the G( which will have the S,G RPT
prune in it ).  Only do this on the first time receiving the
WRVIFWHOLE.

Ticket: #2755650
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
pimd/pim_mroute.c

index 7fc4f12d27678804f89bd80d664d5b0cc5aa8159..3015c4a61bc2f8cca869b1cbc1e395c75e23ba2c 100644 (file)
@@ -437,6 +437,28 @@ int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf)
                                                pim_ifp->primary_address,
                                                up->upstream_register);
                                up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
+                       } else {
+                               /*
+                                * At this point pimd is connected to
+                                * the source, it has a parent, we are not
+                                * the RP  and the SPTBIT should be set
+                                * since we know *the* S,G is on the SPT.
+                                * The first time this happens, let's cause
+                                * an immediate join to go out so that
+                                * the RP can trim this guy immediately
+                                * if necessary, instead of waiting
+                                * one join/prune send cycle
+                                */
+                               if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE &&
+                                   up->parent &&
+                                   up->rpf.source_nexthop.interface !=
+                                           up->parent->rpf.source_nexthop
+                                                   .interface) {
+                                       up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
+                                       pim_jp_agg_single_upstream_send(
+                                               &up->parent->rpf, up->parent,
+                                               true);
+                               }
                        }
                        pim_upstream_keep_alive_timer_start(
                                up, pim_ifp->pim->keep_alive_time);