4.4. PIM Register Messages
The Designated Router (DR) on a LAN or point-to-point link encapsulates multicast packets from local sources to the RP for the relevant group unless it recently received a Register-Stop message for that (S,G) or (*,G) from the RP. When the DR receives a Register-Stop message from the RP, it starts a Register-Stop Timer to maintain this state. Just before the Register-Stop Timer expires, the DR sends a Null-Register Message to the RP to allow the RP to refresh the Register-Stop information at the DR. If the Register- Stop Timer actually expires, the DR will resume encapsulating packets from the source to the RP.4.4.1. Sending Register Messages from the DR
Every PIM-SM router has the capability to be a DR. The state machine below is used to implement Register functionality. For the purposes of specification, we represent the mechanism to encapsulate packets to the RP as a Register-Tunnel interface, which is added to or removed from the (S,G) olist. The tunnel interface then takes part in the normal packet forwarding rules as specified in Section 4.2. If register state is maintained, it is maintained only for directly connected sources and is per-(S,G). There are four states in the DR's per-(S,G) Register state machine: Join (J) The register tunnel is "joined" (the join is actually implicit, but the DR acts as if the RP has joined the DR on the tunnel interface). Prune (P) The register tunnel is "pruned" (this occurs when a Register- Stop is received). Join-Pending (JP) The register tunnel is pruned but the DR is contemplating adding it back. NoInfo (NI) No information. This is the initial state, and the state when the router is not the DR. In addition, a Register-Stop Timer (RST) is kept if the state machine is not in the NoInfo state.
Figure 1: Per-(S,G) register state machine at a DR in tabular form +----------++----------------------------------------------------------+ | || Event | | ++----------+-----------+-----------+-----------+-----------+ |Prev State||Register- | Could | Could | Register- | RP changed| | ||Stop Timer| Register | Register | Stop | | | ||expires | ->True | ->False | received | | +----------++----------+-----------+-----------+-----------+-----------+ |NoInfo ||- | -> J state| - | - | - | |(NI) || | add reg | | | | | || | tunnel | | | | +----------++----------+-----------+-----------+-----------+-----------+ | ||- | - | -> NI | -> P state| -> J state| | || | | state | | | | || | | remove reg| remove reg| update reg| |Join (J) || | | tunnel | tunnel; | tunnel | | || | | | set | | | || | | | Register- | | | || | | | Stop | | | || | | | Timer(*) | | +----------++----------+-----------+-----------+-----------+-----------+ | ||-> J state| - | -> NI | -> P state| -> J state| | || | | state | | | |Join- ||add reg | | | set | add reg | |Pending ||tunnel | | | Register- | tunnel; | |(JP) || | | | Stop | cancel | | || | | | Timer(*) | Register- | | || | | | | Stop Timer| +----------++----------+-----------+-----------+-----------+-----------+ | ||-> JP | - | -> NI | - | -> J state| | ||state | | state | | | | ||set | | | | add reg | |Prune (P) ||Register- | | | | tunnel; | | ||Stop | | | | cancel | | ||Timer(**);| | | | Register- | | ||send Null-| | | | Stop Timer| | ||Register | | | | | +----------++----------+-----------+-----------+-----------+-----------+ Notes: (*) The Register-Stop Timer is set to a random value chosen uniformly from the interval ( 0.5 * Register_Suppression_Time, 1.5 * Register_Suppression_Time) minus Register_Probe_Time.
Subtracting off Register_Probe_Time is a bit unnecessary because it is really small compared to Register_Suppression_Time, but this was in the old spec and is kept for compatibility. (**) The Register-Stop Timer is set to Register_Probe_Time. The following three actions are defined: Add Register Tunnel A Register-Tunnel virtual interface, VI, is created (if it doesn't already exist) with its encapsulation target being RP(G). DownstreamJPState(S,G,VI) is set to Join state, causing the tunnel interface to be added to immediate_olist(S,G) and inherited_olist(S,G). Remove Register Tunnel VI is the Register-Tunnel virtual interface with encapsulation target of RP(G). DownstreamJPState(S,G,VI) is set to NoInfo state, causing the tunnel interface to be removed from immediate_olist(S,G) and inherited_olist(S,G). If DownstreamJPState(S,G,VI) is NoInfo for all (S,G), then VI can be deleted. Update Register Tunnel This action occurs when RP(G) changes. VI_old is the Register-Tunnel virtual interface with encapsulation target old_RP(G). A Register-Tunnel virtual interface, VI_new, is created (if it doesn't already exist) with its encapsulation target being new_RP(G). DownstreamJPState(S,G,VI_old) is set to NoInfo state and DownstreamJPState(S,G,VI_new) is set to Join state. If DownstreamJPState(S,G,VI_old) is NoInfo for all (S,G), then VI_old can be deleted. Note that we cannot simply change the encapsulation target of VI_old because not all groups using that encapsulation tunnel will have moved to the same new RP.
CouldRegister(S,G) The macro "CouldRegister" in the state machine is defined as: bool CouldRegister(S,G) { return ( I_am_DR( RPF_interface(S) ) AND KeepaliveTimer(S,G) is running AND DirectlyConnected(S) == TRUE ) } Note that on reception of a packet at the DR from a directly connected source, KeepaliveTimer(S,G) needs to be set by the packet forwarding rules before computing CouldRegister(S,G) in the register state machine, or the first packet from a source won't be registered. Encapsulating Data Packets in the Register Tunnel Conceptually, the Register Tunnel is an interface with a smaller MTU than the underlying IP interface towards the RP. IP fragmentation on packets forwarded on the Register Tunnel is performed based upon this smaller MTU. The encapsulating DR may perform Path MTU Discovery to the RP to determine the effective MTU of the tunnel. Fragmentation for the smaller MTU should take both the outer IP header and the PIM register header overhead into account. If a multicast packet is fragmented on the way into the Register Tunnel, each fragment is encapsulated individually so it contains IP, PIM, and inner IP headers. In IPv6, the DR MUST perform Path MTU discovery, and an ICMP Packet Too Big message MUST be sent by the encapsulating DR if it receives a packet that will not fit in the effective MTU of the tunnel. If the MTU between the DR and the RP results in the effective tunnel MTU being smaller than 1280 (the IPv6 minimum MTU), the DR MUST send Fragmentation Required messages with an MTU value of 1280 and MUST fragment its PIM register messages as required, using an IPv6 fragmentation header between the outer IPv6 header and the PIM Register header. The TTL of a forwarded data packet is decremented before it is encapsulated in the Register Tunnel. The encapsulating packet uses the normal TTL that the router would use for any locally- generated IP packet. The IP ECN bits should be copied from the original packet to the IP header of the encapsulating packet. They SHOULD NOT be set independently by the encapsulating router.
The Diffserv Code Point (DSCP) should be copied from the original packet to the IP header of the encapsulating packet. It MAY be set independently by the encapsulating router, based upon static configuration or traffic classification. See [12] for more discussion on setting the DSCP on tunnels. Handling Register-Stop(*,G) Messages at the DR An old RP might send a Register-Stop message with the source address set to all zeros. This was the normal course of action in RFC 2362 when the Register message matched against (*,G) state at the RP, and it was defined as meaning "stop encapsulating all sources for this group". However, the behavior of such a Register-Stop(*,G) is ambiguous or incorrect in some circumstances. We specify that an RP should not send Register-Stop(*,G) messages, but for compatibility, a DR should be able to accept one if it is received. A Register-Stop(*,G) should be treated as a Register-Stop(S,G) for all (S,G) Register state machines that are not in the NoInfo state. A router should not apply a Register-Stop(*,G) to sources that become active after the Register-Stop(*,G) was received.
4.4.2. Receiving Register Messages at the RP
When an RP receives a Register message, the course of action is decided according to the following pseudocode: packet_arrives_on_rp_tunnel( pkt ) { if( outer.dst is not one of my addresses ) { drop the packet silently. # Note: this may be a spoofing attempt } if( I_am_RP(G) AND outer.dst == RP(G) ) { sentRegisterStop = FALSE; if ( register.borderbit == TRUE ) { if ( PMBR(S,G) == unknown ) { PMBR(S,G) = outer.src } else if ( outer.src != PMBR(S,G) ) { send Register-Stop(S,G) to outer.src drop the packet silently. } } if ( SPTbit(S,G) OR ( SwitchToSptDesired(S,G) AND ( inherited_olist(S,G) == NULL ))) { send Register-Stop(S,G) to outer.src sentRegisterStop = TRUE; } if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) { if ( sentRegisterStop == TRUE ) { set KeepaliveTimer(S,G) to RP_Keepalive_Period; } else { set KeepaliveTimer(S,G) to Keepalive_Period; } } if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) { decapsulate and forward the inner packet to inherited_olist(S,G,rpt) # Note (+) } } else { send Register-Stop(S,G) to outer.src # Note (*) } } outer.dst is the IP destination address of the encapsulating header. outer.src is the IP source address of the encapsulating header, i.e., the DR's address.
I_am_RP(G) is true if the group-to-RP mapping indicates that this router is the RP for the group. Note (*): This may block traffic from S for Register_Suppression_Time if the DR learned about a new group-to-RP mapping before the RP did. However, this doesn't matter unless we figure out some way for the RP also to accept (*,G) joins when it doesn't yet realize that it is about to become the RP for G. This will all get sorted out once the RP learns the new group-to-rp mapping. We decided to do nothing about this and just accept the fact that PIM may suffer interrupted (*,G) connectivity following an RP change. Note (+): Implementations are advised not to make this a special case, but to arrange that this path rejoin the normal packet forwarding path. All of the appropriate actions from the "On receipt of data from S to G on interface iif" pseudocode in Section 4.2 should be performed. KeepaliveTimer(S,G) is restarted at the RP when packets arrive on the proper tunnel interface and the RP desires to switch to the SPT or the SPTbit is already set. This may cause the upstream (S,G) state machine to trigger a join if the inherited_olist(S,G) is not NULL. An RP should preserve (S,G) state that was created in response to a Register message for at least ( 3 * Register_Suppression_Time ); otherwise, the RP may stop joining (S,G) before the DR for S has restarted sending registers. Traffic would then be interrupted until the Register-Stop Timer expires at the DR. Thus, at the RP, KeepaliveTimer(S,G) should be restarted to ( 3 * Register_Suppression_Time + Register_Probe_Time ). When forwarding a packet from the Register Tunnel, the TTL of the original data packet is decremented after it is decapsulated. The IP ECN bits should be copied from the IP header of the Register packet to the decapsulated packet. The Diffserv Code Point (DSCP) should be copied from the IP header of the Register packet to the decapsulated packet. The RP MAY retain the DSCP of the inner packet or re-classify the packet and apply a different DSCP. Scenarios where each of these might be useful are discussed in [12].
4.5. PIM Join/Prune Messages
A PIM Join/Prune message consists of a list of groups and a list of Joined and Pruned sources for each group. When processing a received Join/Prune message, each Joined or Pruned source for a Group is effectively considered individually, and applies to one or more of the following state machines. When considering a Join/Prune message whose Upstream Neighbor Address field addresses this router, (*,G) Joins and Prunes can affect both the (*,G) and (S,G,rpt) downstream state machines, while (*,*,RP), (S,G), and (S,G,rpt) Joins and Prunes can only affect their respective downstream state machines. When considering a Join/Prune message whose Upstream Neighbor Address field addresses another router, most Join or Prune messages could affect each upstream state machine. In general, a PIM Join/Prune message should only be accepted for processing if it comes from a known PIM neighbor. A PIM router hears about PIM neighbors through PIM Hello messages. If a router receives a Join/Prune message from a particular IP source address and it has not seen a PIM Hello message from that source address, then the Join/Prune message SHOULD be discarded without further processing. In addition, if the Hello message from a neighbor was authenticated using IPsec AH (see Section 6.3), then all Join/Prune messages from that neighbor MUST also be authenticated using IPsec AH. We note that some older PIM implementations incorrectly fail to send Hello messages on point-to-point interfaces, so we also RECOMMEND that a configuration option be provided to allow interoperation with such older routers, but that this configuration option SHOULD NOT be enabled by default.4.5.1. Receiving (*,*,RP) Join/Prune Messages
The per-interface state machine for receiving (*,*,RP) Join/Prune Messages is given below. There are three states: NoInfo (NI) The interface has no (*,*,RP) Join state and no timers running. Join (J) The interface has (*,*,RP) Join state, which will cause the router to forward packets destined for any group handled by RP from this interface except if there is also (S,G,rpt) prune information (see Section 4.5.4) or the router lost an assert on this interface.
Prune-Pending (PP) The router has received a Prune(*,*,RP) on this interface from a downstream neighbor and is waiting to see whether the prune will be overridden by another downstream router. For forwarding purposes, the Prune-Pending state functions exactly like the Join state. In addition, the state machine uses two timers: ExpiryTimer (ET) This timer is restarted when a valid Join(*,*,RP) is received. Expiry of the ExpiryTimer causes the interface state to revert to NoInfo for this RP. Prune-Pending Timer (PPT) This timer is set when a valid Prune(*,*,RP) is received. Expiry of the Prune-Pending Timer causes the interface state to revert to NoInfo for this RP. Figure 2: Downstream per-interface (*,*,RP) state machine in tabular form +------------++--------------------------------------------------------+ | || Event | | ++-------------+-------------+--------------+-------------+ |Prev State ||Receive | Receive | Prune- | Expiry Timer| | ||Join(*,*,RP) | Prune | Pending | Expires | | || | (*,*,RP) | Timer | | | || | | Expires | | +------------++-------------+-------------+--------------+-------------+ | ||-> J state | -> NI state | - | - | |NoInfo (NI) ||start Expiry | | | | | ||Timer | | | | +------------++-------------+-------------+--------------+-------------+ | ||-> J state | -> PP state | - | -> NI state | |Join (J) ||restart | start Prune-| | | | ||Expiry Timer | Pending | | | | || | Timer | | | +------------++-------------+-------------+--------------+-------------+ |Prune- ||-> J state | -> PP state | -> NI state | -> NI state | |Pending (PP)||restart | | Send Prune- | | | ||Expiry Timer | | Echo(*,*,RP) | | +------------++-------------+-------------+--------------+-------------+
The transition events "Receive Join(*,*,RP)" and "Receive Prune(*,*,RP)" imply receiving a Join or Prune targeted to this router's primary IP address on the received interface. If the upstream neighbor address field is not correct, these state transitions in this state machine must not occur, although seeing such a packet may cause state transitions in other state machines. On unnumbered interfaces on point-to-point links, the router's address should be the same as the source address it chose for the Hello message it sent over that interface. However, on point-to- point links we also recommend that for backwards compatibility PIM Join/Prune messages with an upstream neighbor address field of all zeros are also accepted. Transitions from NoInfo State When in NoInfo state, the following event may trigger a transition: Receive Join(*,*,RP) A Join(*,*,RP) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,*,RP) downstream state machine on interface I transitions to the Join state. The Expiry Timer (ET) is started and set to the HoldTime from the triggering Join/Prune message. Note that it is possible to receive a Join(*,*,RP) message for an RP for which we do not have information telling us that it is an RP. In the case of (*,*,RP) state, so long as we have a route to the RP, this will not cause a problem, and the transition should still take place. Transitions from Join State When in Join state, the following events may trigger a transition: Receive Join(*,*,RP) A Join(*,*,RP) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,*,RP) downstream state machine on interface I remains in Join state, and the Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message.
Receive Prune(*,*,RP) A Prune(*,*,RP) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,*,RP) 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. Expiry Timer Expires The Expiry Timer for the (*,*,RP) downstream state machine on interface I expires. The (*,*,RP) downstream state machine on interface I transitions to the NoInfo state. Transitions from Prune-Pending State When in Prune-Pending state, the following events may trigger a transition: Receive Join(*,*,RP) A Join(*,*,RP) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,*,RP) 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 is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Expiry Timer Expires The Expiry Timer for the (*,*,RP) downstream state machine on interface I expires. The (*,*,RP) downstream state machine on interface I transitions to the NoInfo state. Prune-Pending Timer Expires The Prune-Pending Timer for the (*,*,RP) downstream state machine on interface I expires. The (*,*,RP) downstream state machine on interface I transitions to the NoInfo state. A PruneEcho(*,*,RP) is sent onto the subnet connected to interface I.
The action "Send PruneEcho(*,*,RP)" is triggered when the router stops forwarding on an interface as a result of a prune. A PruneEcho(*,*,RP) is simply a Prune(*,*,RP) message sent by the upstream router on a LAN with its own address in the Upstream Neighbor Address field. Its purpose is to add additional reliability so that if a Prune that should have been overridden by another router is lost locally on the LAN, then the PruneEcho may be received and cause the override to happen. A PruneEcho(*,*,RP) need not be sent on an interface that contains only a single PIM neighbor during the time this state machine was in Prune-Pending state.4.5.2. Receiving (*,G) Join/Prune Messages
When a router receives a Join(*,G), it must first check to see whether the RP in the message matches RP(G) (the router's idea of who the RP is). If the RP in the message does not match RP(G), the Join(*,G) should be silently dropped. (Note that other source list entries, such as (S,G,rpt) or (S,G), in the same Group-Specific Set should still be processed.) If a router has no RP information (e.g., has not recently received a BSR message), then it may choose to accept Join(*,G) and treat the RP in the message as RP(G). Received Prune(*,G) messages are processed even if the RP in the message does not match RP(G). The per-interface state machine for receiving (*,G) Join/Prune Messages is given below. There are three states: NoInfo (NI) The interface has no (*,G) Join state and no timers running. Join (J) The interface has (*,G) Join state, which will cause the router to forward packets destined for G from this interface except if there is also (S,G,rpt) prune information (see Section 4.5.4) or the router lost an assert on this interface. Prune-Pending (PP) The router has received a Prune(*,G) on this interface from a downstream neighbor and is waiting to see whether the prune will be overridden by another downstream router. For forwarding purposes, the Prune-Pending state functions exactly like the Join state.
In addition, the state machine uses two timers:
Expiry Timer (ET)
This timer is restarted when a valid Join(*,G) is received.
Expiry of the Expiry Timer causes the interface state to
revert to NoInfo for this group.
Prune-Pending Timer (PPT)
This timer is set when a valid Prune(*,G) is received. Expiry
of the Prune-Pending Timer causes the interface state to
revert to NoInfo for this group.
Figure 3: Downstream per-interface (*,G) state machine in tabular form
+------------++--------------------------------------------------------+
| || Event |
| ++-------------+--------------+-------------+-------------+
|Prev State ||Receive | Receive | Prune- | Expiry Timer|
| ||Join(*,G) | Prune(*,G) | Pending | Expires |
| || | | Timer | |
| || | | Expires | |
+------------++-------------+--------------+-------------+-------------+
| ||-> J state | -> NI state | - | - |
|NoInfo (NI) ||start Expiry | | | |
| ||Timer | | | |
+------------++-------------+--------------+-------------+-------------+
| ||-> J state | -> PP state | - | -> NI state |
|Join (J) ||restart | start Prune- | | |
| ||Expiry Timer | Pending | | |
| || | Timer | | |
+------------++-------------+--------------+-------------+-------------+
|Prune- ||-> J state | -> PP state | -> NI state | -> NI state |
|Pending (PP)||restart | | Send Prune- | |
| ||Expiry Timer | | Echo(*,G) | |
+------------++-------------+--------------+-------------+-------------+
The transition events "Receive Join(*,G)" and "Receive Prune(*,G)"
imply receiving a Join or Prune targeted to this router's primary IP
address on the received interface. If the upstream neighbor address
field is not correct, these state transitions in this state machine
must not occur, although seeing such a packet may cause state
transitions in other state machines.
On unnumbered interfaces on point-to-point links, the router's
address should be the same as the source address it chose for the
Hello message it sent over that interface. However, on point-to-
point links we also recommend that for backwards compatibility PIM Join/Prune messages with an upstream neighbor address field of all zeros are also accepted. Transitions from NoInfo State When in NoInfo state, the following event may trigger a transition: Receive Join(*,G) A Join(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,G) downstream state machine on interface I transitions to the Join state. The Expiry Timer (ET) is started and set to the HoldTime from the triggering Join/Prune message. Transitions from Join State When in Join state, the following events may trigger a transition: Receive Join(*,G) A Join(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,G) downstream state machine on interface I remains in Join state, and the Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Receive Prune(*,G) A Prune(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,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. Expiry Timer Expires The Expiry Timer for the (*,G) downstream state machine on interface I expires. The (*,G) downstream state machine on interface I transitions to the NoInfo state.
Transitions from Prune-Pending State When in Prune-Pending state, the following events may trigger a transition: Receive Join(*,G) A Join(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (*,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 is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Expiry Timer Expires The Expiry Timer for the (*,G) downstream state machine on interface I expires. The (*,G) downstream state machine on interface I transitions to the NoInfo state. Prune-Pending Timer Expires The Prune-Pending Timer for the (*,G) downstream state machine on interface I expires. The (*,G) downstream state machine on interface I transitions to the NoInfo state. A PruneEcho(*,G) is sent onto the subnet connected to interface I. The action "Send PruneEcho(*,G)" is triggered when the router stops forwarding on an interface as a result of a prune. A PruneEcho(*,G) is simply a Prune(*,G) message sent by the upstream router on a LAN with its own address in the Upstream Neighbor Address field. Its purpose is to add additional reliability so that if a Prune that should have been overridden by another router is lost locally on the LAN, then the PruneEcho may be received and cause the override to happen. A PruneEcho(*,G) need not be sent on an interface that contains only a single PIM neighbor during the time this state machine was in Prune-Pending state.
4.5.3. Receiving (S,G) Join/Prune Messages
The per-interface state machine for receiving (S,G) Join/Prune messages is given below and is almost identical to that for (*,G) messages. There are three states: NoInfo (NI) The interface has no (S,G) Join state and no (S,G) timers running. Join (J) The interface has (S,G) Join state, which will cause the router to forward packets from S destined for G from this interface if the (S,G) state is active (the SPTbit is set) except if the router lost an assert on this interface. Prune-Pending (PP) The router has received a Prune(S,G) on this interface from a downstream neighbor and is waiting to see whether the prune will be overridden by another downstream router. For forwarding purposes, the Prune-Pending state functions exactly like the Join state. In addition, there are two timers: Expiry Timer (ET) This timer is set when a valid Join(S,G) is received. Expiry of the Expiry Timer causes this state machine to revert to NoInfo state. Prune-Pending Timer (PPT) This timer is set when a valid Prune(S,G) is received. Expiry of the Prune-Pending Timer causes this state machine to revert to NoInfo state.
Figure 4: Downstream per-interface (S,G) state machine in tabular form +------------++--------------------------------------------------------+ | || Event | | ++-------------+--------------+-------------+-------------+ |Prev State ||Receive | Receive | Prune- | Expiry Timer| | ||Join(S,G) | Prune(S,G) | Pending | Expires | | || | | Timer | | | || | | Expires | | +------------++-------------+--------------+-------------+-------------+ | ||-> J state | -> NI state | - | - | |NoInfo (NI) ||start Expiry | | | | | ||Timer | | | | +------------++-------------+--------------+-------------+-------------+ | ||-> J state | -> PP state | - | -> NI state | |Join (J) ||restart | start Prune- | | | | ||Expiry Timer | Pending | | | | || | Timer | | | +------------++-------------+--------------+-------------+-------------+ |Prune- ||-> J state | -> PP state | -> NI state | -> NI state | |Pending (PP)||restart | | Send Prune- | | | ||Expiry Timer | | Echo(S,G) | | +------------++-------------+--------------+-------------+-------------+ The transition events "Receive Join(S,G)" and "Receive Prune(S,G)" imply receiving a Join or Prune targeted to this router's primary IP address on the received interface. If the upstream neighbor address field is not correct, these state transitions in this state machine must not occur, although seeing such a packet may cause state transitions in other state machines. On unnumbered interfaces on point-to-point links, the router's address should be the same as the source address it chose for the Hello message it sent over that interface. However, on point-to- point links we also recommend that for backwards compatibility PIM Join/Prune messages with an upstream neighbor address field of all zeros are also accepted. Transitions from NoInfo State When in NoInfo state, the following event may trigger a transition: Receive Join(S,G) A Join(S,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I.
The (S,G) downstream state machine on interface I transitions to the Join state. The Expiry Timer (ET) is started and set to the HoldTime from the triggering Join/Prune message. Transitions from Join State When in Join state, the following events may trigger a transition: Receive Join(S,G) A Join(S,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G) downstream state machine on interface I remains in Join state, and the Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Receive Prune(S,G) A Prune(S,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. 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. Expiry Timer Expires The Expiry Timer for the (S,G) downstream state machine on interface I expires. The (S,G) downstream state machine on interface I transitions to the NoInfo state. Transitions from Prune-Pending State When in Prune-Pending state, the following events may trigger a transition: Receive Join(S,G) A Join(S,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I.
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 is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Expiry Timer Expires The Expiry Timer for the (S,G) downstream state machine on interface I expires. The (S,G) downstream state machine on interface I transitions to the NoInfo state. Prune-Pending Timer Expires The Prune-Pending Timer for the (S,G) downstream state machine on interface I expires. The (S,G) downstream state machine on interface I transitions to the NoInfo state. A PruneEcho(S,G) is sent onto the subnet connected to interface I. The action "Send PruneEcho(S,G)" is triggered when the router stops forwarding on an interface as a result of a prune. A PruneEcho(S,G) is simply a Prune(S,G) message sent by the upstream router on a LAN with its own address in the Upstream Neighbor Address field. Its purpose is to add additional reliability so that if a Prune that should have been overridden by another router is lost locally on the LAN, then the PruneEcho may be received and cause the override to happen. A PruneEcho(S,G) need not be sent on an interface that contains only a single PIM neighbor during the time this state machine was in Prune-Pending state.4.5.4. Receiving (S,G,rpt) Join/Prune Messages
The per-interface state machine for receiving (S,G,rpt) Join/Prune messages is given below. There are five states: NoInfo (NI) The interface has no (S,G,rpt) Prune state and no (S,G,rpt) timers running. Prune (P) The interface has (S,G,rpt) Prune state, which will cause the router not to forward packets from S destined for G from this interface even though the interface has active (*,G) Join state.
Prune-Pending (PP) The router has received a Prune(S,G,rpt) on this interface from a downstream neighbor and is waiting to see whether the prune will be overridden by another downstream router. For forwarding purposes, the Prune-Pending state functions exactly like the NoInfo state. PruneTmp (P') This state is a transient state that for forwarding purposes behaves exactly like the Prune state. A (*,G) Join has been received (which may cancel the (S,G,rpt) Prune). As we parse the Join/Prune message from top to bottom, we first enter this state if the message contains a (*,G) Join. Later in the message, we will normally encounter an (S,G,rpt) prune to reinstate the Prune state. However, if we reach the end of the message without encountering such a (S,G,rpt) prune, then we will revert to NoInfo state in this state machine. As no time is spent in this state, no timers can expire. Prune-Pending-Tmp (PP') This state is a transient state that is identical to P' except that it is associated with the PP state rather than the P state. For forwarding purposes, PP' behaves exactly like PP state. In addition, there are two timers: Expiry Timer (ET) This timer is set when a valid Prune(S,G,rpt) is received. Expiry of the Expiry Timer causes this state machine to revert to NoInfo state. Prune-Pending Timer (PPT) This timer is set when a valid Prune(S,G,rpt) is received. Expiry of the Prune-Pending Timer causes this state machine to move on to Prune state.
Figure 5: Downstream per-interface (S,G,rpt) state machine in tabular form +----------++----------------------------------------------------------+ | || Event | | ++---------+----------+----------+--------+--------+--------+ |Prev ||Receive | Receive | Receive | End of | Prune- | Expiry | |State ||Join(*,G)| Join | Prune | Message| Pending| Timer | | || | (S,G,rpt)| (S,G,rpt)| | Timer | Expires| | || | | | | Expires| | +----------++---------+----------+----------+--------+--------+--------+ | ||- | - | -> PP | - | - | - | | || | | state | | | | | || | | start | | | | |NoInfo || | | Prune- | | | | |(NI) || | | Pending | | | | | || | | Timer; | | | | | || | | start | | | | | || | | Expiry | | | | | || | | Timer | | | | +----------++---------+----------+----------+--------+--------+--------+ | ||-> P' | -> NI | -> P | - | - | -> NI | | ||state | state | state | | | state | |Prune (P) || | | restart | | | | | || | | Expiry | | | | | || | | Timer | | | | +----------++---------+----------+----------+--------+--------+--------+ |Prune- ||-> PP' | -> NI | - | - | -> P | - | |Pending ||state | state | | | state | | |(PP) || | | | | | | +----------++---------+----------+----------+--------+--------+--------+ | ||- | - | -> P | -> NI | - | - | |PruneTmp || | | state | state | | | |(P') || | | restart | | | | | || | | Expiry | | | | | || | | Timer | | | | +----------++---------+----------+----------+--------+--------+--------+ | ||- | - | -> PP | -> NI | - | - | |Prune- || | | state | state | | | |Pending- || | | restart | | | | |Tmp (PP') || | | Expiry | | | | | || | | Timer | | | | +----------++---------+----------+----------+--------+--------+--------+ The transition events "Receive Join(S,G,rpt)", "Receive Prune(S,G,rpt)", and "Receive Join(*,G)" imply receiving a Join or Prune targeted to this router's primary IP address on the received interface. If the upstream neighbor address field is not correct,
these state transitions in this state machine must not occur, although seeing such a packet may cause state transitions in other state machines. On unnumbered interfaces on point-to-point links, the router's address should be the same as the source address it chose for the Hello message it sent over that interface. However, on point-to- point links we also recommend that PIM Join/Prune messages with an upstream neighbor address field of all zeros are also accepted. Transitions from NoInfo State When in NoInfo (NI) state, the following event may trigger a transition: Receive Prune(S,G,rpt) A Prune(S,G,rpt) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I transitions to the Prune-Pending state. The Expiry Timer (ET) is started and set to the HoldTime from the triggering Join/Prune message. 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. Transitions from Prune-Pending State When in Prune-Pending (PP) state, the following events may trigger a transition: Receive Join(*,G) A Join(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I transitions to Prune-Pending-Tmp state whilst the remainder of the compound Join/Prune message containing the Join(*,G) is processed. Receive Join(S,G,rpt) A Join(S,G,rpt) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I transitions to NoInfo state. ET and PPT are canceled.
Prune-Pending Timer Expires The Prune-Pending Timer for the (S,G,rpt) downstream state machine on interface I expires. The (S,G,rpt) downstream state machine on interface I transitions to the Prune state. Transitions from Prune State When in Prune (P) state, the following events may trigger a transition: Receive Join(*,G) A Join(*,G) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I transitions to PruneTmp state whilst the remainder of the compound Join/Prune message containing the Join(*,G) is processed. Receive Join(S,G,rpt) A Join(S,G,rpt) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I transitions to NoInfo state. ET and PPT are canceled. Receive Prune(S,G,rpt) A Prune(S,G,rpt) is received on interface I with its Upstream Neighbor Address set to the router's primary IP address on I. The (S,G,rpt) downstream state machine on interface I remains in Prune state. The Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. Expiry Timer Expires The Expiry Timer for the (S,G,rpt) downstream state machine on interface I expires. The (S,G,rpt) downstream state machine on interface I transitions to the NoInfo state. Transitions from Prune-Pending-Tmp State When in Prune-Pending-Tmp (PP') state and processing a compound Join/Prune message, the following events may trigger a transition:
Receive Prune(S,G,rpt) The compound Join/Prune message contains a Prune(S,G,rpt). The (S,G,rpt) downstream state machine on interface I transitions back to the Prune-Pending state. The Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. End of Message The end of the compound Join/Prune message is reached. The (S,G,rpt) downstream state machine on interface I transitions to the NoInfo state. ET and PPT are canceled. Transitions from PruneTmp State When in PruneTmp (P') state and processing a compound Join/Prune message, the following events may trigger a transition: Receive Prune(S,G,rpt) The compound Join/Prune message contains a Prune(S,G,rpt). The (S,G,rpt) downstream state machine on interface I transitions back to the Prune state. The Expiry Timer (ET) is restarted, set to maximum of its current value and the HoldTime from the triggering Join/Prune message. End of Message The end of the compound Join/Prune message is reached. The (S,G,rpt) downstream state machine on interface I transitions to the NoInfo state. ET is canceled. Notes: Receiving a Prune(*,G) does not affect the (S,G,rpt) downstream state machine. Receiving a Join(*,*,RP) does not affect the (S,G,rpt) downstream state machine. If a router has originated Join(*,*,RP) and pruned a source off it using Prune(S,G,rpt), then to receive that source again it should explicitly re-join using Join(S,G,rpt) or Join(*,G). In some LAN topologies it is possible for a router sending a new Join(*,*,RP) to have to wait as much as a Join/Prune Interval before noticing that it needs to override a neighbor's preexisting Prune(S,G,rpt). This is considered acceptable, as (*,*,RP) state is intended to be used only in long-lived and persistent scenarios.