Subject: Swich back from SPT to RPT

From: [email-masked]
Date: Wed, 28 Feb 2001 13:00:18 -0800

Hi all:

     Does the current pim-sm draft support "switch-back" from SPT to RPT?   In
the following scenario, switch-back can not be accomplished with the current
definition of JoinDesired(S,G) in the spec:

                           S ------------------------- RP
                           |                           |
                            ----------- R1 ------------
                                        |
                                        R2
                                        |
                            ----------------------------
                                 |              |
                                R3              R4

Initially, R3 sends join(S,G) toward S and R4 sends join(*,G) toward RP and
create SPT and RPT. After R1 starts receiving (S,G) traffic from S, it will send
prune(S,G,rpt) toward RP and switch-over from RPT to SPT.

Now if R3 sends prune(S,G) toward S (e.g. R3 receives igmp_prune(S,G)), R2 will
NOT propagate the prune(S,G) to R1. This is because of the definition of
JoinDesired(S,G):

bool JoinDesired(S,G) {
     return( immediate_olist(S,G) != NULL
             OR ( KeepaliveTimer(S,G) is running
                  AND inherited_olist(S,G) != NULL ) )
}

In the above scenario at R2, immediate_olist(S,G) equals NULL. However,
inherited_olist(S,G) does not equal to NULL and KeepALiveTimer(S,G) is running
as long as S keeps sending (S,G) traffic.  So JoinDesired(S,G) will remain TRUE
and the upstream (S,G) state-machine of R2 will remain in the joined state and
will not send prune(S,G) to R1.

I believe this problem can be fixed by changing the definition of
JoinDesired(S,G) as follows:

bool JoinDesired(S,G) {
     return( immediate_olist(S,G) != NULL
             OR ( KeepaliveTimer(S,G) is running
                  AND inherited_olist(S,G) != NULL
                  AND ((I_am_RP(G))
                       OR (I_am_DR(S))
                       OR (RPF_interface(S) is in inherited_olist(S,G,rpt))) )
}

There are four situations where JoinDesired(S,G) should equal to TRUE.
(1) immediate_olist(S,G) != NULL

(2) KeepaliveImer(S,G) running AND (inherited_olist(S,G) != NULL) AND I_am_RP(G)
This will allow RP to send join(S,G) toward S as soon as the first join(*,G) is
received.

(3) KeepaliveImer(S,G) running AND (inherited_olist(S,G) != NULL)  AND
I_am_DR(S)
This will allow DR(S) to send register messages toward RP through the register
tunnel

(4) KeepaliveImer(S,G) running AND (inherited_olist(S,G) != NULL)  AND
(RPF_interface(S) is in inherited_olist(S,G,rpt))
This will allow the turn-around router to send join(S,G) toward S in the
turn-around scenario.

With this modified definition of JoinDesired(S,G),  When R2 receives prune(S,G)
from R3, JoinDesired(S,G) will become FALSE.  So R2 will move its upstream (S,G)
state-machine from the Joined state to the notJoined state, clear SPTbit(S,G),
and send a Prune(S,G) toward S.   Similarly, when R1 receives prune(S,G) from
R2, JoinDesired(S,G) will become FALSE.  So R1 will move its upstream (S,G)
state-machine from the Joined state to the notJoined state, clear SPTbit(S,G),
and send a Prune(S,G) toward S.  Now PruneDesird(S,G,rpt) at R1 becomes FALSE,
so R1 will move its upstream (S,G,rpt) state-machine from the Pruned state to
the NotPruned state and send a join(S,G,rpt) toward RP. When RP receives
join(S,G,rpt) from R1, it will move its downstream per-interface (S,G,rpt)
state-machine from the Pruned state to the NoInfo state.  This completes the
switch-back process

.
-- James Huang