Tech-invite3GPPspecsGlossariesIETFRFCsGroupsSIPABNFsWorld Map

RFC 8220

 
 
 

Protocol Independent Multicast (PIM) over Virtual Private LAN Service (VPLS)

Part 2 of 2, p. 24 to 43
Prev Section

 


prevText      Top      ToC       Page 24 
2.7.  Bidirectional PIM (BIDIR-PIM)

   Bidirectional PIM (BIDIR-PIM) is a variation of PIM-SM.  The main
   differences between PIM-SM and BIDIR-PIM are as follows:

   o  There are no source-based trees, and SSM is not supported (i.e.,
      no (S,G) states) in BIDIR-PIM.

   o  Multicast traffic can flow up the shared tree in BIDIR-PIM.

   o  To avoid forwarding loops, one router on each link is elected as
      the Designated Forwarder (DF) for each RP in BIDIR-PIM.

   The main advantage of BIDIR-PIM is that it scales well for
   many-to-many applications.  However, the lack of source-based trees
   means that multicast traffic is forced to remain on the shared tree.

   As described in RFC 5015 [BIDIR-PIM], parts of a BIDIR-PIM-enabled
   network may forward traffic without exchanging Join/Prune messages --
   for instance, between DFs and the Rendezvous Point Link (RPL).

   As the described procedures for PIM snooping rely on the presence of
   Join/Prune messages, enabling PIM snooping on BIDIR-PIM networks
   could break the BIDIR-PIM functionality.  Deploying PIM snooping on
   BIDIR-PIM-enabled networks will require some further study.  Some
   thoughts on this topic are discussed in Appendix A.

2.8.  Interaction with IGMP Snooping

   Whenever IGMP snooping is enabled in conjunction with PIM snooping in
   the same VPLS instance, the PE SHOULD follow these rules:

   o  To maintain the list of multicast routers and ports on which they
      are attached, the PE SHOULD NOT use the rules described in
      RFC 4541 [IGMP-SNOOP] but SHOULD rely on the neighbors discovered
      by PIM snooping.  This list SHOULD then be used to apply the first
      forwarding rule (rule 1) listed in Section 2.1.1 of RFC 4541
      [IGMP-SNOOP].

Top      Up      ToC       Page 25 
   o  If the PE supports proxy reporting, an IGMP membership learned
      only on a port to which a PIM neighbor is attached (i.e., not
      learned elsewhere) SHOULD NOT be included in the summarized
      upstream report sent to that port.

2.9.  PIM-DM

   The key characteristic of PIM-DM is flood-and-prune behavior.
   Shortest-path trees are built as a multicast source starts
   transmitting.

2.9.1.  Building PIM-DM States

   PIM-DM states are built by snooping on the PIM-DM Join, Prune, Graft,
   and State Refresh messages received on ACs/PWs and State Refresh
   messages sent on ACs/PWs.  By snooping on these PIM-DM messages, a PE
   builds the following states per (S,G,N) where S is the address of the
   multicast source, G is the group address, and N is the upstream
   neighbor to which Prunes/Grafts are sent by downstream CEs:

   Per PIM(S,G,N):

      Port PIM(S,G,N) Prune State:

      *  DownstreamPState(S,G,N,Port): One of {"NoInfo" (NI),
         "Pruned" (P), "Prune-Pending" (PP)}

      *  Prune-Pending Timer (PPT)

      *  Prune Timer (PT)

      *  Upstream Port (valid if the PIM(S,G,N) Prune state is "Pruned")

2.9.2.  PIM-DM Downstream Per-Port PIM(S,G,N) State Machine

   The downstream per-port PIM(S,G,N) state machine is as defined in
   Section 4.4.2 of RFC 3973 [PIM-DM], with a few changes relevant to
   PIM snooping.  When reading Section 4.4.2 of RFC 3973 [PIM-DM],
   please be aware that, for the purposes of PIM snooping, the
   downstream states are built per (S,G,N,Downstream-Port) in PIM
   snooping and not per (Downstream-Interface,S,G) as in a PIM-DM
   router.  As noted in Section 2.9.1, the states (DownstreamPState) and
   timers (PPT and PT) are per (S,G,N,Port).

Top      Up      ToC       Page 26 
2.9.3.  Triggering Assert Election in PIM-DM

   Since PIM-DM is a flood-and-prune protocol, traffic is flooded to all
   routers unless explicitly pruned.  Since PIM-DM routers do not prune
   on non-RPF interfaces, PEs should typically not receive Prunes on
   Port(RPF-Neighbor).  So, the asserting routers should typically be in
   pim_oiflist(S,G).  In most cases, Assert election should occur
   naturally without any special handling, since data traffic will be
   forwarded to the asserting routers.

   However, there are some scenarios where a Prune might be received on
   a port that is also an upstream port.  If we prune the port from
   pim_oiflist(S,G), then it would not be possible for the asserting
   routers to determine if traffic arrived on their downstream port.
   This can be fixed by adding pim_iifs(S,G) to pim_oiflist(S,G) so that
   data traffic flows to the upstream ports.

2.10.  PIM Proxy

   As noted earlier, PIM snooping will work correctly only if Join
   suppression is disabled in the VPLS.  If Join suppression is enabled
   in the VPLS, then PEs MUST do PIM relay/proxying for VPLS multicast
   to work correctly.  This section applies specifically to full
   proxying and not to relay.

2.10.1.  Upstream PIM Proxy Behavior

   A PIM proxying PE consumes Join/Prune messages and regenerates PIM
   Join/Prune messages to be sent upstream by implementing the Upstream
   FSM as specified in Section 4.5.4 of RFC 7761 [PIM-SM].  This is the
   only difference from PIM relay.

   The source IP address in PIM packets sent upstream SHOULD be the
   address of a PIM downstream neighbor in the corresponding Join/Prune
   state.  The chosen address MUST NOT be the Upstream Neighbor field to
   be encoded in the packet.  The Layer 2 encapsulation for the selected
   source IP address MUST be the encapsulation recorded in the PIM
   Neighbor Database for that IP address.

2.11.  Directly Connected Multicast Source

   PIM snooping/relay/proxying could be enabled on a LAN that connects a
   multicast source and a PIM First-Hop Router (FHR).  As the FHR
   will not send any downstream Join/Prune messages, we will not be able
   to establish any forwarding states for that source.  Therefore, if
   there is a source in the CE network that connects directly into the
   VPLS instance, then multicast traffic from that source MUST be sent
   to all PIM routers on the VPLS instance in addition to the IGMP

Top      Up      ToC       Page 27 
   receivers in the VPLS.  If there is already (S,G) or (*,G) snooping
   state that is formed on any PE, this will not happen per the current
   forwarding rules and guidelines.  So, in order to determine if
   traffic needs to be flooded to all routers, a PE must be able to
   determine if the traffic came from a host on that LAN.  There are
   three ways to address this problem:

   o  The PE would have to do IPv4 ARP snooping and/or IPv6 Neighbor
      Discovery snooping to determine if a source is directly connected.

   o  Another option is to configure all PEs to indicate that there are
      CE sources that are directly connected to the VPLS instance and
      disallow snooping for the groups for which the source is going to
      send traffic.  This way, traffic from that source to those groups
      will always be flooded within the provider network.

   o  A third option is to require that sources of CE multicast traffic
      must be behind a router.

   This document recommends the third option -- sources of traffic must
   be behind a router.

2.12.  Data-Forwarding Rules

   First, we define the rules that are common to PIM-SM and PIM-DM PEs.
   Forwarding rules for each protocol type are specified in the
   subsections below.

   If there is no matching forwarding state, then the PE SHOULD discard
   the packet, i.e., the UserDefinedPortList (Sections 2.12.1 and
   2.12.2) SHOULD be empty.

   The following general rules MUST be followed when forwarding
   multicast traffic in a VPLS:

   o  Traffic arriving on a port MUST NOT be forwarded back onto the
      same port.

   o  Due to VPLS split-horizon rules, traffic ingressing on a PW
      MUST NOT be forwarded to any other PW.

Top      Up      ToC       Page 28 
2.12.1.  PIM-SM Data-Forwarding Rules

   Per the rules in RFC 7761 [PIM-SM] and per the additional rules
   specified in this document,

   OutgoingPortList(*,G) = immediate_olist(*,G) (+)
                           UpstreamPorts(*,G) (+)
                           Port(PimDR)

   OutgoingPortList(S,G) = inherited_olist(S,G) (+)
                           UpstreamPorts(S,G) (+)
                           (UpstreamPorts(*,G) (-)
                           UpstreamPorts(S,G,rpt)) (+)
                           Port(PimDR)

   RFC 7761 [PIM-SM] specifies how immediate_olist(*,G) and
   inherited_olist(S,G) are built.  PimDR is the IP address of the
   PIM DR in the VPLS.

   The PIM-SM snooping data-forwarding rules are defined below in
   pseudocode:

   BEGIN
       iif is the incoming port of the multicast packet.
       S is the source IP address of the multicast packet.
       G is the destination IP address of the multicast packet.

       If there is (S,G) state on the PE
       Then
           OutgoingPortList = OutgoingPortList(S,G)
       Else if there is (*,G) state on the PE
       Then
           OutgoingPortList = OutgoingPortList(*,G)
       Else
           OutgoingPortList = UserDefinedPortList
       Endif

       If iif is an AC
       Then
           OutgoingPortList = OutgoingPortList (-) iif
       Else
           ## iif is a PW
           OutgoingPortList = OutgoingPortList (-) PWPorts
       Endif

       Forward the packet to OutgoingPortList.
   END

Top      Up      ToC       Page 29 
   First, if there is (S,G) state on the PE, then the set of outgoing
   ports is OutgoingPortList(S,G).

   Otherwise, if there is (*,G) state on the PE, then the set of
   outgoing ports is OutgoingPortList(*,G).

   The packet is forwarded to the selected set of outgoing ports while
   observing the general rules above in Section 2.12.

2.12.2.  PIM-DM Data-Forwarding Rules

   The PIM-DM snooping data-forwarding rules are defined below in
   pseudocode:

   BEGIN
       iif is the incoming port of the multicast packet.
       S is the source IP address of the multicast packet.
       G is the destination IP address of the multicast packet.

       If there is (S,G) state on the PE
       Then
           OutgoingPortList = olist(S,G)
       Else
           OutgoingPortList = UserDefinedPortList
       Endif

       If iif is an AC
       Then
           OutgoingPortList = OutgoingPortList (-) iif
       Else
           ## iif is a PW
           OutgoingPortList = OutgoingPortList (-) PWPorts
       Endif

       Forward the packet to OutgoingPortList.
   END

   If there is forwarding state for (S,G), then forward the packet to
   olist(S,G) while observing the general rules above in Section 2.12.

   RFC 3973 [PIM-DM] specifies how olist(S,G) is constructed.

3.  IANA Considerations

   This document does not require any IANA actions.

Top      Up      ToC       Page 30 
4.  Security Considerations

   Security considerations provided in the VPLS solution documents
   (i.e., RFC 4762 [VPLS-LDP] and RFC 4761 [VPLS-BGP]) apply to this
   document as well.

5.  References

5.1.  Normative References

   [BIDIR-PIM]
              Handley, M., Kouvelas, I., Speakman, T., and L. Vicisano,
              "Bidirectional Protocol Independent Multicast
              (BIDIR-PIM)", RFC 5015, DOI 10.17487/RFC5015,
              October 2007, <https://www.rfc-editor.org/info/rfc5015>.

   [JOIN-ATTR]
              Boers, A., Wijnands, I., and E. Rosen, "The Protocol
              Independent Multicast (PIM) Join Attribute Format",
              RFC 5384, DOI 10.17487/RFC5384, November 2008,
              <https://www.rfc-editor.org/info/rfc5384>.

   [PIM-DM]   Adams, A., Nicholas, J., and W. Siadak, "Protocol
              Independent Multicast - Dense Mode (PIM-DM): Protocol
              Specification (Revised)", RFC 3973, DOI 10.17487/RFC3973,
              January 2005, <https://www.rfc-editor.org/info/rfc3973>.

   [PIM-SM]   Fenner, B., Handley, M., Holbrook, H., Kouvelas, I.,
              Parekh, R., Zhang, Z., and L. Zheng, "Protocol Independent
              Multicast - Sparse Mode (PIM-SM): Protocol Specification
              (Revised)", STD 83, RFC 7761, DOI 10.17487/RFC7761,
              March 2016, <https://www.rfc-editor.org/info/rfc7761>.

   [PIM-SSM]  Holbrook, H. and B. Cain, "Source-Specific Multicast for
              IP", RFC 4607, DOI 10.17487/RFC4607, August 2006,
              <https://www.rfc-editor.org/info/rfc4607>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/info/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in
              RFC 2119 Key Words", BCP 14, RFC 8174,
              DOI 10.17487/RFC8174, May 2017,
              <https://www.rfc-editor.org/info/rfc8174>.

Top      Up      ToC       Page 31 
   [RPF-VECTOR]
              Wijnands, IJ., Boers, A., and E. Rosen, "The Reverse Path
              Forwarding (RPF) Vector TLV", RFC 5496,
              DOI 10.17487/RFC5496, March 2009,
              <https://www.rfc-editor.org/info/rfc5496>.

5.2.  Informative References

   [IGMP-SNOOP]
              Christensen, M., Kimball, K., and F. Solensky,
              "Considerations for Internet Group Management Protocol
              (IGMP) and Multicast Listener Discovery (MLD) Snooping
              Switches", RFC 4541, DOI 10.17487/RFC4541, May 2006,
              <https://www.rfc-editor.org/info/rfc4541>.

   [VPLS-BGP]
              Kompella, K., Ed., and Y. Rekhter, Ed., "Virtual Private
              LAN Service (VPLS) Using BGP for Auto-Discovery and
              Signaling", RFC 4761, DOI 10.17487/RFC4761, January 2007,
              <https://www.rfc-editor.org/info/rfc4761>.

   [VPLS-LDP]
              Lasserre, M., Ed., and V. Kompella, Ed., "Virtual Private
              LAN Service (VPLS) Using Label Distribution Protocol (LDP)
              Signaling", RFC 4762, DOI 10.17487/RFC4762, January 2007,
              <https://www.rfc-editor.org/info/rfc4762>.

   [VPLS-MCAST]
              Aggarwal, R., Ed., Kamite, Y., Fang, L., Rekhter, Y., and
              C. Kodeboniya, "Multicast in Virtual Private LAN Service
              (VPLS)", RFC 7117, DOI 10.17487/RFC7117, February 2014,
              <https://www.rfc-editor.org/info/rfc7117>.

   [VPLS-MCAST-REQ]
              Kamite, Y., Ed., Wada, Y., Serbest, Y., Morin, T., and L.
              Fang, "Requirements for Multicast Support in Virtual
              Private LAN Services", RFC 5501, DOI 10.17487/RFC5501,
              March 2009, <https://www.rfc-editor.org/info/rfc5501>.

Top      Up      ToC       Page 32 
Appendix A.  BIDIR-PIM Considerations

   This appendix describes some guidelines that may be used to preserve
   BIDIR-PIM functionality in combination with PIM snooping.

   In order to preserve BIDIR-PIM snooping, routers need to set up
   forwarding states so that:

   o  on the RPL, all traffic is forwarded to all Port(N) ports.

   o  on any other interface, traffic is always forwarded to the DF.

   The information needed to set up these states may be obtained by:

   o  determining the mapping between the group (range) and the RP.

   o  snooping and storing DF election information.

   o  determining where the RPL is.  This could be achieved by static
      configuration or by combining the information mentioned in the two
      bullet items above.

A.1.  BIDIR-PIM Data-Forwarding Rules

   The BIDIR-PIM snooping data-forwarding rules are defined below in
   pseudocode:

   BEGIN
       iif is the incoming port of the multicast packet.
       G is the destination IP address of the multicast packet.

       If there is forwarding state for G
       Then
           OutgoingPortList = olist(G)
       Else
           OutgoingPortList = UserDefinedPortList
       Endif

       If iif is an AC
       Then
           OutgoingPortList = OutgoingPortList (-) iif
       Else
           ## iif is a PW
           OutgoingPortList = OutgoingPortList (-) PWPorts
       Endif

       Forward the packet to OutgoingPortList.
   END

Top      Up      ToC       Page 33 
   If there is forwarding state for G, then forward the packet to
   olist(G) while observing the general rules above in Section 2.12.

   RFC 5015 [BIDIR-PIM] specifies how olist(G) is constructed.

Appendix B.  Example Network Scenario

   Let us consider the scenario in Figure 3.

                                            +------+ AC3 +------+
                                            |  PE2 |-----| CE3  |
                                           /|      |     +------+
                                          / +------+         |
                                         /     |             |
                                        /      |             |
                                       /PW12   |             |
                                      /        |           /---\
                                     /         |PW23       | S |
                                    /          |           \---/
                                   /           |             |
                                  /            |             |
                                 /             |             |
                       +------+ /           +------+         |
          +------+     |  PE1 |/   PW13     |  PE3 |     +------+
          | CE1  |-----|      |-------------|      |-----| CE4  |
          +------+ AC1 +------+             +------+ AC4 +------+
                           |
                           |AC2
                       +------+
                       | CE2  |
                       +------+

           Figure 3: An Example Network for Triggering an Assert

   In the examples below, JT(Port,S,G,N) is the downstream Join Expiry
   Timer on the specified Port for the (S,G) with upstream neighbor N.

B.1.  PIM Snooping Example

   In the network depicted in Figure 3, S is the source of a multicast
   stream (S,G).  CE1 and CE2 both have two ECMP routes to reach the
   source.

   1.  CE1 sends a Join(S,G) with UpstreamNeighbors(S,G) = CE3.

   2.  PE1 snoops on the Join(S,G) and builds forwarding state, since it
       is received on an AC.  It also floods the Join(S,G) in the VPLS.
       PE2 snoops on the Join(S,G) and builds forwarding state, since

Top      Up      ToC       Page 34 
       the Join(S,G)is targeting a neighbor residing on an AC.  PE3
       does not create forwarding state for (S,G) because this is a
       PW-only Join and there is neither an existing (*,G) state with an
       AC in UpstreamPorts(*,G) nor an existing (S,G) state with an AC
       in UpstreamPorts(S,G).  Both PE2 and PE3 will also flood the
       Join(S,G) in the VPLS.

       The resulting states at the PEs are as follows:

       PE1 states:
          JT(AC1,S,G,CE3)        = JP_HoldTime
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW12 }
          OutgoingPortList(S,G)  = { AC1, PW12 }

       PE2 states:
          JT(PW12,S,G,CE3)       = JP_HoldTime
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { AC3 }
          OutgoingPortList(S,G)  = { PW12, AC3 }

       PE3 states:
          No (S,G) state

   3.  The multicast stream (S,G) flows along CE3 -> PE2 -> PE1 -> CE1.

   4.  Now CE2 sends a Join(S,G) with UpstreamNeighbors(S,G) = CE4.

   5.  All PEs snoop on the Join(S,G), build forwarding state, and flood
       the Join(S,G) in the VPLS.  Note that for PE2, even though this
       is a PW-only Join, forwarding state is built on this Join(S,G),
       since PE2 has an existing (S,G) state with an AC in
       UpstreamPorts(S,G).

       The resulting states at the PEs are as follows:

       PE1 states:
          JT(AC1,S,G,CE3)        = active
          JT(AC2,S,G,CE4)        = JP_HoldTime
          UpstreamNeighbors(S,G) = { CE3, CE4 }
          UpstreamPorts(S,G)     = { PW12, PW13 }
          OutgoingPortList(S,G)  = { AC1, PW12, AC2, PW13 }

Top      Up      ToC       Page 35 
       PE2 states:
          JT(PW12,S,G,CE4)       = JP_HoldTime
          JT(PW12,S,G,CE3)       = active
          UpstreamNeighbors(S,G) = { CE3, CE4 }
          UpstreamPorts(S,G)     = { AC3, PW23 }
          OutgoingPortList(S,G)  = { PW12, AC3, PW23 }

       PE3 states:
          JT(PW13,S,G,CE4)       = JP_HoldTime
          UpstreamNeighbors(S,G) = { CE4 }
          UpstreamPorts(S,G)     = { AC4 }
          OutgoingPortList(S,G)  = { PW13, AC4 }

   6.  The multicast stream (S,G) flows into the VPLS from two of the
       CEs -- CE3 and CE4.  PE2 forwards the stream received from CE3 to
       PW23, and PE3 forwards the stream to AC4.  This helps the CE
       routers to trigger Assert election.  Let us say that CE3 becomes
       the Assert winner.

   7.  CE3 sends an Assert message to the VPLS.  The PEs flood the
       Assert message without examining it.

   8.  CE4 stops sending the multicast stream to the VPLS.

   9.  CE2 notices an RPF change due to the Assert and sends a
       Prune(S,G) with upstream neighbor = CE4.  CE2 also sends a
       Join(S,G) with upstream neighbor = CE3.

   10. All the PEs start a Prune-Pending timer on the ports on which
       they received the Prune(S,G).  When the Prune-Pending timer
       expires, all PEs will remove the downstream (S,G,CE4) states.

       The resulting states at the PEs are as follows:

       PE1 states:
          JT(AC1,S,G,CE3)        = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW12 }
          OutgoingPortList(S,G)  = { AC1, AC2, PW12 }

       PE2 states:
          JT(PW12,S,G,CE3)       = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { AC3 }
          OutgoingPortList(S,G)  = { PW12, AC3 }

Top      Up      ToC       Page 36 
       PE3 states:
          JT(PW13,S,G,CE3)       = JP_HoldTime
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW23 }
          OutgoingPortList(S,G)  = { PW13, PW23 }

       Note that at this point at PE3, since there is no AC in
       OutgoingPortList(S,G) and no (*,G) or (S,G) state with an AC in
       UpstreamPorts(*,G) or UpstreamPorts(S,G), respectively, the
       existing (S,G) state at PE3 can also be removed.  So, finally:

       PE3 states:
          No (S,G) state

   Note that at the end of the Assert election, there should be no
   duplicate traffic forwarded downstream, and traffic should flow only
   on the desired path.  Also note that there are no unnecessary (S,G)
   states on PE3 after the Assert election.

B.2.  PIM Proxy Example with (S,G) / (*,G) Interaction

   In the same network, let us assume that CE4 is the upstream neighbor
   towards the RP for G.

   JPST(S,G,N) is the JP sending timer for the (S,G) with upstream
   neighbor N.

   1.  CE1 sends a Join(S,G) with UpstreamNeighbors(S,G) = CE3.

   2.  PE1 consumes the Join(S,G) and builds forwarding state, since the
       Join(S,G) is received on an AC.

       PE2 consumes the Join(S,G) and builds forwarding state, since the
       Join(S,G) is targeting a neighbor residing on an AC.

       PE3 consumes the Join(S,G) but does not create forwarding state
       for (S,G), since this is a PW-only Join and there is neither an
       existing (*,G) state with an AC in UpstreamPorts(*,G) nor an
       existing (S,G) state with an AC in UpstreamPorts(S,G).

Top      Up      ToC       Page 37 
       The resulting states at the PEs are as follows:

       PE1 states:
          JT(AC1,S,G,CE3)        = JP_HoldTime
          JPST(S,G,CE3)          = t_periodic
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW12 }
          OutgoingPortList(S,G)  = { AC1, PW12 }

       PE2 states:
          JT(PW12,S,G,CE3)       = JP_HoldTime
          JPST(S,G,CE3)          = t_periodic
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { AC3 }
          OutgoingPortList(S,G)  = { PW12, AC3 }

       PE3 states:
          No (S,G) state

       Joins are triggered as follows:
       PE1 triggers a Join(S,G) targeting CE3.  Since the Join(S,G) was
       received on an AC and is targeting a neighbor that is residing
       across a PW, the triggered Join(S,G) is sent on all PWs.

       PE2 triggers a Join(S,G) targeting CE3.  Since the Join(S,G) is
       targeting a neighbor residing on an AC, it only sends the Join
       on AC3.

       PE3 ignores the Join(S,G), since this is a PW-only Join and there
       is neither an existing (*,G) state with an AC in
       UpstreamPorts(*,G) nor an existing (S,G) state with an AC in
       UpstreamPorts(S,G).

   3.  The multicast stream (S,G) flows along CE3 -> PE2 -> PE1 -> CE1.

   4.  Now let us say that CE2 sends a Join(*,G) with
       UpstreamNeighbors(*,G) = CE4.

   5.  PE1 consumes the Join(*,G) and builds forwarding state, since the
       Join(*,G) is received on an AC.

       PE2 consumes the Join(*,G); although this is a PW-only Join,
       forwarding state is built on this Join(*,G), since PE2 has an
       existing (S,G) state with an AC in UpstreamPorts(S,G).  However,
       since this is a PW-only Join, PE2 only adds the PW towards PE3
       (PW23) into UpstreamPorts(*,G) and hence into
       OutgoingPortList(*,G).  It does not add the PW towards PE1 (PW12)
       into OutgoingPortList(*,G).

Top      Up      ToC       Page 38 
       PE3 consumes the Join(*,G) and builds forwarding state, since the
       Join(*,G) is targeting a neighbor residing on an AC.

       The resulting states at the PEs are as follows:

       PE1 states:
          JT(AC1,*,G,CE4)        = JP_HoldTime
          JPST(*,G,CE4)          = t_periodic
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { PW13 }
          OutgoingPortList(*,G)  = { AC2, PW13 }

          JT(AC1,S,G,CE3)        = active
          JPST(S,G,CE3)          = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW12 }
          OutgoingPortList(S,G)  = { AC1, PW12, PW13 }

       PE2 states:
          JT(PW12,*,G,CE4)       = JP_HoldTime
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(G)       = { PW23 }
          OutgoingPortList(*,G)  = { PW23 }

          JT(PW12,S,G,CE3)       = active
          JPST(S,G,CE3)          = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { AC3 }
          OutgoingPortList(S,G)  = { PW12, AC3, PW23 }

       PE3 states:
          JT(PW13,*,G,CE4)       = JP_HoldTime
          JPST(*,G,CE4)          = t_periodic
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { AC4 }
          OutgoingPortList(*,G)  = { PW13, AC4 }

       Joins are triggered as follows:
       PE1 triggers a Join(*,G) targeting CE4.  Since the Join(*,G) was
       received on an AC and is targeting a neighbor that is residing
       across a PW, the triggered Join(S,G) is sent on all PWs.

       PE2 does not trigger a Join(*,G) based on this Join, since this
       is a PW-only Join.

       PE3 triggers a Join(*,G) targeting CE4.  Since the Join(*,G) is
       targeting a neighbor residing on an AC, it only sends the Join
       on AC4.

Top      Up      ToC       Page 39 
   6.  If traffic is not flowing yet (i.e., step 3 is delayed so that it
       occurs after step 6) and in the interim JPST(S,G,CE3) on PE1
       expires, causing it to send a refresh Join(S,G) targeting CE3,
       since the refresh Join(S,G) is targeting a neighbor that is
       residing across a PW, the refresh Join(S,G) is sent on all PWs.

   7.  Note that PE1 refreshes its JT based on reception of refresh
       Joins from CE1 and CE2.

       PE2 consumes the Join(S,G) and refreshes the JT(PW12,S,G,CE3)
       timer.

       PE3 consumes the Join(S,G).  It also builds forwarding state on
       this Join(S,G), even though this is a PW-only Join, since now PE2
       has an existing (*,G) state with an AC in UpstreamPorts(*,G).
       However, since this is a PW-only Join, PE3 only adds the PW
       towards PE2 (PW23) into UpstreamPorts(S,G) and hence into
       OutgoingPortList(S,G).  It does not add the PW towards PE1 (PW13)
       into OutgoingPortList(S,G).

       PE3 states:
          JT(PW13,*,G,CE4)       = active
          JPST(S,G,CE4)          = active
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { AC4 }
          OutgoingPortList(*,G)  = { PW13, AC4 }

          JT(PW13,S,G,CE3)       = JP_HoldTime
          UpstreamNeighbors(*,G) = { CE3 }
          UpstreamPorts(*,G)     = { PW23 }
          OutgoingPortList(*,G)  = { PW13, AC4, PW23 }

       Joins are triggered as follows:
       PE2 already has (S,G) state, so it does not trigger a Join(S,G)
       based on reception of this refresh Join.

       PE3 does not trigger a Join(S,G) based on this Join, since this
       is a PW-only Join.

   8.  The multicast stream (S,G) flows into the VPLS from two of the
       CEs -- CE3 and CE4.  PE2 forwards the stream received from CE3 to
       PW12 and PW23.  At the same time, PE3 forwards the stream
       received from CE4 to PW13 and PW23.

       The stream received over PW12 and PW13 is forwarded by PE1 to AC1
       and AC2.

Top      Up      ToC       Page 40 
       The stream received by PE3 over PW23 is forwarded to AC4.  The
       stream received by PE2 over PW23 is forwarded to AC3.  Either of
       these helps the CE routers to trigger Assert election.

   9.  CE3 and/or CE4 send(s) Assert message(s) to the VPLS.  The PEs
       flood the Assert message(s) without examining it.

   10. CE3 becomes the (S,G) Assert winner, and CE4 stops sending the
       multicast stream to the VPLS.

   11. CE2 notices an RPF change due to the Assert and sends a
       Prune(S,G,rpt) with upstream neighbor = CE4.

   12. PE1 consumes the Prune(S,G,rpt), and since
       PruneDesired(S,G,Rpt,CE4) is TRUE, it triggers a Prune(S,G,rpt)
       to CE4.  Since the Prune is targeting a neighbor across a PW, it
       is sent on all PWs.

       PE2 consumes the Prune(S,G,rpt) and does not trigger any Prune
       based on this Prune(S,G,rpt), since this was a PW-only Prune.

       PE3 consumes the Prune(S,G,rpt), and since
       PruneDesired(S,G,rpt,CE4) is TRUE, it sends the Prune(S,G,rpt)
       on AC4.

       PE1 states:
          JT(AC2,*,G,CE4)        = active
          JPST(*,G,CE4)          = active
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { PW13 }
          OutgoingPortList(*,G)  = { AC2, PW13 }

          JT(AC2,S,G,CE4)        = JP_HoldTime with S,G,rpt prune flag
          JPST(S,G,CE4)          = none, since this is sent along
                                   with the Join(*,G) to CE4 based
                                   on JPST(*,G,CE4) expiry
          UpstreamPorts(S,G,rpt) = { PW13 }
          UpstreamNeighbors(S,G,rpt) = { CE4 }

          JT(AC1,S,G,CE3)        = active
          JPST(S,G,CE3)          = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW12 }
          OutgoingPortList(S,G)  = { AC1, PW12, AC2 }

Top      Up      ToC       Page 41 
       PE2 states:
          JT(PW12,*,G,CE4)       = active
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { PW23 }
          OutgoingPortList(*,G)  = { PW23 }

          JT(PW12,S,G,CE4)       = JP_HoldTime with S,G,rpt prune flag
          JPST(S,G,CE4)          = none, since this was created
                                   off a PW-only Prune
          UpstreamPorts(S,G,rpt) = { PW23 }
          UpstreamNeighbors(S,G,rpt) = { CE4 }

          JT(PW12,S,G,CE3)       = active
          JPST(S,G,CE3)          = active
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { AC3 }
          OutgoingPortList(*,G)  = { PW12, AC3 }

       PE3 states:
          JT(PW13,*,G,CE4)       = active
          JPST(*,G,CE4)          = active
          UpstreamNeighbors(*,G) = { CE4 }
          UpstreamPorts(*,G)     = { AC4 }
          OutgoingPortList(*,G)  = { PW13, AC4 }

          JT(PW13,S,G,CE4)       = JP_HoldTime with S,G,rpt prune flag
          JPST(S,G,CE4)          = none, since this is sent along
                                   with the Join(*,G) to CE4 based
                                   on JPST(*,G,CE4) expiry
          UpstreamNeighbors(S,G,rpt) = { CE4 }
          UpstreamPorts(S,G,rpt) = { AC4 }

          JT(PW13,S,G,CE3)       = active
          JPST(S,G,CE3)          = none, since this state is
                                   created by a PW-only Join
          UpstreamNeighbors(S,G) = { CE3 }
          UpstreamPorts(S,G)     = { PW23 }
          OutgoingPortList(S,G)  = { PW23 }

   Even in this example, at the end of the (S,G) / (*,G) Assert
   election, there should be no duplicate traffic forwarded downstream,
   and traffic should flow only to the desired CEs.

   However, we don't have duplicate traffic because one of the CEs stops
   sending traffic due to the Assert, not because we don't have any
   forwarding state in the PEs to do this forwarding.

Top      Up      ToC       Page 42 
Acknowledgements

   Many members of the former L2VPN and PIM working groups have
   contributed to, and provided valuable comments and feedback on, this
   document, including Vach Kompella, Shane Amante, Sunil Khandekar, Rob
   Nath, Marc Lasserre, Yuji Kamite, Yiqun Cai, Ali Sajassi, Jozef
   Raets, Himanshu Shah (Ciena), and Himanshu Shah (Cisco).

Contributors

   Yetik Serbest and Suresh Boddapati coauthored earlier draft versions
   of this document.

   Karl (Xiangrong) Cai and Princy Elizabeth made significant
   contributions to bring the specification to its current state,
   especially in the area of Join forwarding rules.

Top      Up      ToC       Page 43 
Authors' Addresses

   Olivier Dornon
   Nokia
   Copernicuslaan 50
   B-2018  Antwerp
   Belgium

   Email: olivier.dornon@nokia.com


   Jayant Kotalwar
   Nokia
   701 East Middlefield Rd.
   Mountain View, CA  94043
   United States of America

   Email: jayant.kotalwar@nokia.com


   Venu Hemige
   Nokia

   Email: vhemige@gmail.com


   Ray Qiu
   mistnet.io

   Email: ray@mistnet.io


   Jeffrey Zhang
   Juniper Networks, Inc.
   10 Technology Park Drive
   Westford, MA  01886
   United States of America

   Email: zzhang@juniper.net