Subject: Re: Reset SPTbit(S,G) on topology change events

From: Mark Handley <[email-masked]>
Date: Wed, 07 Mar 2001 17:12:43 -0800

>From:  James Huang@MITEL on 03/07/2001 05:09 PM PST
>Mark:
>
>     In your first scenario, I do not understand why D will forward (S,G)
>traffic it receives from the LAN to B and create a forwarding loop.  According
>to section 4.2 of the new draft, (S,G) traffic received from RPF_intf(RP) (whe
>SPTbit(S,G) == 0) should be forwarded to inherited_olist(S,G,rpt).  In this
>case, B sends (S,G) join instead of (*,G) join to D,  so the interface to B wi
>ll
>not be included in the inherited_olist(S,G,rpt) at D.
>
>Did I mis-understand something?

No, you're correct.  I tried to simplify a diagram on my whiteboard to
do it in ASCII art, and got it wrong.

 - Mark

---

From: [email-masked]
Date: Wed, 7 Mar 2001 17:09:27 -0800

In your first scenario, I do not understand why D will forward (S,G)
traffic it receives from the LAN to B and create a forwarding loop.  According
to section 4.2 of the new draft, (S,G) traffic received from RPF_intf(RP) (when
SPTbit(S,G) == 0) should be forwarded to inherited_olist(S,G,rpt).  In this
case, B sends (S,G) join instead of (*,G) join to D,  so the interface to B will
not be included in the inherited_olist(S,G,rpt) at D.

-- James Huang

Mark Handley <[email-masked]> on 03/07/2001 04:19:18 PM

To:   James Huang/USA/Mitel@Mitel
cc:   [email-masked]

Subject:  Re: Reset SPTbit(S,G) on topology change events

>Mark:
>     Can you tell me more about this routing loop scenario?

Ok, this is hard in ASCII art.

         J(S)->   J(S)->
     RP ------- A ----------------B
         <-J(*) |                 |J(S)
                |                 ||
             ^  |                 |V
           J(*) |           <-J(*)|
               LAN----------------D------>
                |                 |  I1  to
             ^  |               ^ |I2    S
           J(*) R2            J(*)o------>
                                  |
                                  R1

The starting situation is that R1 and R2 have done (*,G) Joins, and
the RP has joined to S (through B, for whatever reason).  D has sent
an (S,G,rpt) prune on the LAN to A, but R2 overrode the prune, so
traffic from S is still arriving on the LAN from A.  D doesn't have
any downstream join state on the LAN interface, so it doesn't
assert. D's iif towards S is I2.

Now the RPF_interface to S changes to I1.

D sends a Join(S,G) on I1, but for some reason the join fails to
complete (say the join packet is lost).

Now if D clears SPTbit, then traffic from the LAN will immediately be
accepted by D, and forwarded around the loop.  Whatever traffic was
already in the D->B->A->LAN loop will circulate until its TTL
decrements to zero.

Fortunately no new traffic can enter the loop, so this is a transient
event.  Not a disaster, but undesirable.

>If routing loop
>does occur in your scenario, don't we have the same problem during some initia
>SPT setup where both (*,G) and (S,G) join state exists in the same downstream
>interface, RPF_intf(RP) != RPF_intf(S), and SPTbit(S,G) == 0. Under this
>condition, the router will try to join the SPT by sending join(S,G) to
>RPF'(S,G).  But before (S,G) traffic starts arriving from the SPT, the router
>will accept (S,G) traffic from the RPT and foward it down to the interface whe
>both (S,G) and (*,G) join state exists. In this situation, traffic DOES go fro
>being forwarded on (*,G) state (by this router) to being forwarded on (S,G)
>state (by downstream routers with upstream (S,G) join state on the interface
>where both (S,G) and (*,G) join state exists)

Yes, that is indeed the case:

              <-J(S)
         S----------------RP
         |                |
         |                |^
         |                |J(*)
         |                |
         |      J(*)->    |
         A----------------B---------R2
         |                |
         |                |
       ^ |                |
     J(*)|                |
         |                |
         C----------------+
       ^ |
     J(*)|
         |
        R1

In this situation, R1 has done a Join(*,G), and RP has joined to S
directly.

Now R2 does a Join(S,G), which is routed via C:

              <-J(S)
         S----------------RP
         |                |
         X                |^
      ^  |                |J(*)
     J(S)|                |
         |      J(*)->    |
         A----------------B---------R2
         |                |   <-J(S)
         |                |
       ^ | ^              |J(S)
     J(*)|J(S)            |V
         |                |
         C----------------+
       ^ |     <J(S)
     J(*)|
         |
        R1

But between A and S, the Join fails for whatever reason (say the Join
packet is lost).

Now SPTbit at C and B is set by arriving traffic, but SPTbit at
A is not set.

Traffic loops from B->A->C->B.  However as the SPTbit at B is set, it
doesn't accept any more traffic from the RP, so no new traffic is
accepted into the loop.  Thus, although it's undesirable, it's not a
disaster either.

I think this has always been an issue with PIM-SM.  We cured quite a
few problems when writing the new spec, but this wasn't one we could
solve and stay completely compatible.  C simply cannot tell that an
upstream router is accepting packets from the RPT when they're
arriving on its RPF_interface towards S.

To solve the problem you'd need either:

 - a downstream message that says "SPT incomplete" when this scenario
   is detected, or

 - a downstream message in the normal case that says "SPT complete"
   and that triggers the SPTbit being set.

The former could be added as a negotiated extension if we believe this
is a significant issue; the latter would probably have been the better
solution, but isn't backwards compatible with existing deployed code.

However the first case (when RPF_interface(S) changes) is easily
preventable by not clearing the SPTbit when it's unsafe to do so.

Cheers,
     Mark