RFC 2715

Interoperability Rules for Multicast Routing Protocols

๐Ÿ“… published October 1999, from ietf

Interoperability Rules for Multicast Routing Protocols ๐ŸŽ€

okay bestie, the title block first ๐Ÿ’– this is RFC 2715, written by D. Thaler at Microsoft, filed under Informational, dated October 1999. It doesn't list anything it obsoletes or updates, so there's nothing to chase there โœจ

Status of this Memo ๐Ÿ“œ

This memo is for the Internet community as information ๐ŸŒธ It does not specify an Internet standard of any kind, and distribution of this memo is unlimited ๐Ÿฆ‹

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐Ÿ’…

Abstract ๐Ÿ”ฎ

The rules in this doc let multiple independent multicast routing domains interoperate efficiently, and they're totally iconic for it ๐Ÿ‘‘ Concrete versions of the rules are given for DVMRP, MOSPF, PIM-DM, PIM-SM, and CBT, plus IGMP-only links โœจ Future protocols, including ones that don't exist yet, can describe their interoperability by saying how these rules apply to them ๐Ÿงš


1. Introduction ๐Ÿฆ‹

okay so, for sources and receivers inside several autonomous multicast routing domains (or "regions") to talk to each other, the domains have to be hooked up through multicast border routers (MBRs) ๐ŸŒˆ To avoid black holes or routing loops between domains, we assume the domains are organized into one of these two topologies:

  • A tree (or star) topology (figure 1) with a backbone domain at the root, stub domains at the leaves, and possibly "transit" domains as branches between the root and the leaves. Each pair of adjacent domains is connected by one or more MBRs. The root of each subtree of domains receives all globally-scoped traffic originated anywhere within the subtree, and forwards traffic to its parent and children where needed. Each parent domain's MBR injects a default route into its child domains, while child domains' MBRs inject actual (but potentially aggregated) routes into parent domains. Thus, the arrows in the figure indicate both the direction in which the default route points, as well as the direction in which all globally-scoped traffic is sent. ๐ŸŒธ
                           +--------+
                    +----|        |----+
    +---+    +---+  |  ===>      <===  |
    |   |    |   |  +----|   #    |----+
    |   |    | # |     +-----#------+
    | # |  +---#-------|     v      |-----------+
   +--#----|   v       |            |           |-----+
   |  v  ===>        ===> Backbone <===        <===   |
   +-------|   ^       |            |     ^     |-----+
           +---#-------|     ^      |-----#-----+
             | # |     +-----#------+ |   #    |-----+
             |   |       |   #    |   |       <===   |
             +---+   +---|        |   |        |-----+
                     | ===>       |   +--------+
                     +---+--------+

           Figure 1: Tree Topology of Domains
  • An arbitrary topology, in which a higher level (inter-domain) routing protocol, such as HDVMRP [1] or BGMP [9], is used to calculate paths among domains. Each pair of adjacent domains is connected by one or more MBRs. ๐Ÿ“

Section 2 describes rules that let existing multicast routing protocols [2,3,4,5,6] interoperate. These rules cut the interoperability problem from O(N^2) potential protocol interactions down to just N (1 per protocol) instantiations of the same set of invariant rules ๐Ÿง โœจ This document specifically applies to Multicast Border Routers (MBRs) that meet these assumptions:

  • The MBR has two or more active multicast routing components, each running an instance of some multicast routing protocol. No assumption is made about the type of multicast routing protocol (e.g., broadcast-and-prune vs. explicit-join) any component runs, or about the nature of a "component". Multiple components running the same protocol are allowed. ๐Ÿ’œ
  • The router is configured to forward packets between two or more independent domains. The router has one or more active interfaces in each domain, and one component per domain. The router also has an inter-component "alert dispatcher", which we cover in Section 3. ๐Ÿซถ
  • Only one multicast routing protocol is active per interface (we do not consider mixed multicast protocol LANs). Each interface on which multicast is enabled is thus "owned" by exactly one of the components. ๐ŸŽ€
  • All components share a common forwarding cache of (S,G) entries, which are created when data packets are received, and can be deleted at any time. Only the component owning an interface may change information about that interface in the forwarding cache. Each forwarding cache entry has a single incoming interface (iif) and a list of outgoing interfaces (oiflist). Each component typically keeps a separate multicast routing table with any type of entries. ๐Ÿ”ฅ

Note that the guidelines in this document are implementation-independent. The same rules given in Section 2 apply in some form, regardless of the implementation. For example, they apply to each of these architectural models:

  • Single process (e.g., GateD): Several routing components in the same user-space process, running on top of a multicast-capable kernel. ๐Ÿงš
  • Multiple peer processes: Several routing components, each as a separate user-space process, all sitting on top of a multicast-capable kernel, with N*(N-1) interaction channels. ๐Ÿ’…
  • Multiple processes with arbiter: Multiple independent peer routing component processes which interact with each other and with the kernel solely through an independent arbitration daemon. ๐Ÿ‘‘
  • Monolith: Several routing components which are part of the "kernel" itself. ๐ŸŒˆ

We describe all interactions between components in terms of "alerts". The nature of an alert is implementation-dependent (e.g., it may consist of a simple function call, writing to shared memory, use of IPC, or some other method), but alerts of some form exist in every model. Similarly, the originator of an alert is also implementation-dependent. For example, alerts may be originated by a component effecting a change, by an independent arbiter, or by the kernel. ๐Ÿฆ‹

1.1. Specification Language ๐Ÿ“

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. ๐Ÿ’–


2. Requirements ๐Ÿ‘‘

To make sure an MBR that fits the assumptions above shows correct interdomain routing behavior, each MBR component MUST adhere to the following rules ๐Ÿ’…

Rule 1: All components must agree on which component owns the incoming interface (iif) for a forwarding cache entry. This component, which we call the "iif owner", is determined by the dispatcher (see Section 3). The incoming component may select ANY interface it owns as the iif, according to its own rules. โœจ

When a routing change makes the iif switch to an interface owned by a different component, both the component that previously owned the entry's iif and the component that owns it afterwards MUST notice the change (so the first can prune upstream and the second can join/graft upstream, for example). Typically, noticing such changes happens as a result of normal protocol behavior. ๐Ÿ”„

Rule 2: The component owning an interface specifies the criteria for which packets received on that interface are to be accepted or dropped (e.g., whether to perform an RPF check, and what scoped boundaries exist on that interface). Once a packet is accepted, however, it is processed according to the forwarding rules of all components. ๐ŸŽ€

Furthermore, some multicast routing protocols (e.g. PIM) also require the ability to react to packets received on the "wrong" interface. To support these protocols, an MBR must allow a component to place any of its interfaces in "WrongIf Alert Mode". If a packet arrives on such an interface and is not accepted according to Rule 2, then the component owning the interface MUST be alerted [(S,G) WrongIf alert]. Typically, WrongIf alerts must be rate-limited. ๐Ÿšจ

Rule 3: Whenever a new (S,G) forwarding cache entry is to be created (e.g., upon accepting a packet destined to a non-local group), all components MUST be alerted [(S,G) Creation alert] so that they can set the forwarding state on their own outgoing interfaces (oifs) before the packet is forwarded. ๐ŸŒธ

Note that (S,G) Creation alerts are not necessarily generated by one of the protocol components themselves. ๐Ÿ™ˆ

Rule 4: When a component removes the last oif from an (S,G) forwarding cache entry whose iif is owned by another component, or when such an (S,G) forwarding cache entry is created with an empty oif list, the component owning the iif MUST be alerted [(S,G) Prune alert] (so it can send a prune, for example). โœ‚๏ธ

Rule 5: When the first oif is added to an (S,G) forwarding cache entry whose iif is owned by another component, the component owning the iif MUST be alerted [(S,G) Join alert] (so it can send a join or graft, for example). ๐Ÿช„

The oif list in rules 4 and 5 must also logically include any virtual encapsulation interfaces, such as those used for tunneling or for sending encapsulated packets to an RP/core. ๐Ÿงš

Rule 6: Unless a component reports the aggregate group membership in the direction of its interfaces, it MUST be a "wildcard receiver" for all sources whose RPF interface is owned by another component ("externally-reached" sources). In addition, a component MUST be a "wildcard receiver" for all sources whose RPF interface is owned by that component ("internally-reached" sources) if any other component of the MBR is a wildcard receiver for externally-reached sources. This will happen naturally as a result of Rule 5 when it receives a (,) Join alert. ๐Ÿ’œ

For example, if the backbone does not keep global membership information, all MBR components in the backbone in a tree topology of domains, as well as all components owning the RPF interface towards the backbone, are wildcard receivers for externally-reached sources. ๐ŸŒณ

MBRs need not be wildcard receivers (for internally- or externally-reached sources) if a higher-level routing protocol, such as BGMP, is used for routing between domains. ๐Ÿฆ‹

2.1. Deleting Forwarding Cache Entries ๐Ÿงš

okay so this one is a big deal, bestie ๐Ÿ˜ญ Rules 4 and 5 need extra care when forwarding cache entries can be deleted whenever they feel like it. A component must be able to figure out when the combined oiflist for (S,G) goes from null to non-null, and also when it goes back the other way. no cap, that's the whole game ๐ŸŽ€

There are a bunch of ways to pull this off, and each implementation gets to pick its own vibe. Here are a couple of options, not an exhaustive list:

  • Whenever a component would modify the oiflist of a single forwarding cache entry if one existed, one is created first. Then the oiflist gets modified and Rules 4 and 5 are applied after an (S,G) Creation alert goes out to all components and every component has updated the oiflist. OR,
  • When a forwarding cache entry is about to be deleted, a new alert, [(S,G) Deletion alert], goes out to all components, and the entry only gets deleted if every component gives the green light. Each component can only give permission if it has no (S,G) route table entry. โœจ

2.2. Additional Recommendation ๐Ÿ’…

this one is lowkey iconic. Using (*,G) Join alerts and (*,G) Prune alerts can cut down on bandwidth by skipping the broadcast-and-prune behavior between domains when it isn't needed ๐Ÿ“ The catch is that every component has to be able to tell which other components care about any given group.

How you do that is up to the implementation, but one example is a shared table called the Component-Group Table ๐Ÿฆ‹ It's indexed by group-prefix and lists which components are interested in each group(prefix). Any components that are wildcard receivers for externally-reached sources (so, the ones whose RPF interface is owned by a different component) get listed in every entry of this table, including a default entry. The table is kind of like a forwarding cache of (*,G) entries, except it doesn't care about incoming versus outgoing interfaces. slay ๐Ÿ’–


3. Alert Dispatchers ๐ŸŒธ

okay picture this: every MBR gets its own "alert dispatcher," which is basically the main character managing the drama ๐Ÿ‘‘ The dispatcher picks, for each (S,G) entry in the shared forwarding cache, the component that owns the iif. It also decides which component or components should receive a given alert.

3.1. The "Interop" Dispatcher ๐ŸŽ€

this is the one you use when there's no inter-domain multicast routing protocol around, so domains in a tree topology can still get along ๐Ÿซถ If an inter-domain multicast routing protocol is in use, use a different dispatcher instead. The Interop dispatcher doesn't own any interfaces, which is giving very humble energy ๐Ÿ™ˆ

To pick the iif of an (S,G) entry, the iif owner is the component that owns the next-hop interface toward S in the multicast RIB.

The "iif owner" of (*,G) and (*,*) entries is the Interop dispatcher itself. That way, the Interop dispatcher can still receive the alerts it needs without owning any interfaces. iykyk ๐Ÿงš

3.1.1. Processing Alerts

when the Interop dispatcher gets an (S,G) Creation alert, it doesn't add any interfaces to the entry's oif list, since it doesn't own any. nothing to add, bestie ๐Ÿ’…

When the Interop dispatcher gets a (*,G) Prune alert, it does different things depending on the number of components N that want data for G. If N has just changed from 2 to 1, a (*,G) Prune alert goes to the remaining component. If N has just changed from 1 to 0, a (*,G) Prune alert goes to ALL components other than the 1. ๐Ÿ˜ญ

When the Interop dispatcher gets a (*,G) Join alert, it again looks at N, the number of components that want data for G. If N has just changed from 0 to 1, a (*,G) Join alert goes to ALL components other than the 1. If N has just changed from 1 to 2, a (*,G) Join alert goes to the original (1) component. ๐Ÿ”ฅ

3.2. "BGMP" Dispatcher ๐Ÿฆ‹

this one is for use with an inter-domain multicast routing protocol that allows global (S,G) and (*,G) trees, like BGMP ๐Ÿ’œ

The iif owner of an (S,G) entry is the component that owns the next-hop interface toward S in the multicast RIB.

The iif owner of a (*,G) entry is the component that owns the next-hop interface toward G in the multicast RIB. โœจ

3.2.1. Processing Alerts

this dispatcher is simple and honestly I respect it ๐Ÿซถ It just forwards every (S,G) and (*,G) alert to the iif owner of the associated entry. no drama, just delivery ๐Ÿ“ฌ


4. Multicast Routing Protocol Components ๐ŸŒˆ

in this section we look at how the rules in section 2 apply to the current versions of a few protocols. Future versions and other protocols should explain how the rules apply in a separate document, so that's a them problem for later ๐Ÿงš

4.1. DVMRP ๐ŸŒŠ

in this section we walk through how the rules in section 2 apply to DVMRP. We're assuming you already know normal DVMRP behavior, which is specified in [2]. ๐Ÿค“

Like all broadcast-and-prune protocols, DVMRP components are automatically wildcard receivers for internally-reached sources, so they're always in the group chat ๐Ÿ’ฌ Unless some form of Domain-Wide-Reports (DWRs) [10] (which is the same thing as the Regional-Membership-Reports described in [1]) gets added to DVMRP later, all DVMRP components also act as wildcard receivers for externally-reached sources. If DWRs are available in the domain, then a DVMRP component only acts as a wildcard receiver for externally-reached sources if there are internally-reached domains that don't support some form of DWRs. โœจ

One simple shortcut for approximating DWRs is to assume that if there are any internally-reached members, at least one of them is a sender. With this shortcut, the presence of any (S,G) state for internally-reached sources can be used instead. Sending a data packet to a group is then the same as sending a DWR for that group. it's giving efficiency ๐Ÿ’–

4.1.1. Generating Alerts

A (*,*) Join alert goes to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when the first component becomes a wildcard receiver for external sources. This can happen when a DVMRP component starts up without support for some form of DWRs. ๐ŸŒธ

A (*,*) Prune alert goes to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when all components are no longer wildcard receivers for external sources. This can happen when a DVMRP component without support for some form of DWRs shuts down. ๐Ÿ‘‹

An (S,G) Prune alert goes to the component that owns the iif for a forwarding cache entry whenever the last oif is removed from the entry, and that iif is owned by another component. In DVMRP, this can happen when:

  • A DVMRP (S,G) Prune message is received on the logical interface.

An (S,G) Join alert goes to the component that owns the iif for a forwarding cache entry whenever the first logical oif is added to an entry, and that iif is owned by another component. In DVMRP, this can happen when any of the following occur:

  • The oif's prune timer expires, or
  • A DVMRP (S,G) Graft message is received on the logical interface, or
  • IGMP [7] tells DVMRP that directly-connected members of G now exist on the interface.

When it's known, for a group G, that there are no longer any members in the DVMRP domain who receive data for externally-reached sources from the local router, a (*,G) Prune alert goes to the "iif owner" for (*,G) according to the dispatcher. In DVMRP, this can happen when:

  • The DWR for G times out, or
  • The members-are-senders approximation is being used and the last (S,G) entry for G times out.

When it's first known that there are members of a group G in the DVMRP domain, a (*,G) Join alert goes to the "iif owner" of (*,G). In DVMRP, this can happen when either of the following occurs:

  • A DWR is received for G, or
  • The members-are-senders approximation is being used and a data packet for G is received on one of the component's interfaces. ๐Ÿ”ฅ

4.1.2. Processing Alerts

when a DVMRP component gets an (S,G) Creation alert, it adds all of the component's interfaces to the entry's oif list (following normal DVMRP behavior) EXCEPT:

  • the iif,
  • interfaces without local members of the entry's group, and for which DVMRP (S,G) Prune messages have been received from all downstream dependent neighbors,
  • interfaces for which the router is not the designated forwarder for S,
  • and interfaces with scoped boundaries covering the group. ๐Ÿ™…โ€โ™€๏ธ

When a DVMRP component gets an (S,G) Prune alert, and the forwarding cache entry's oiflist is empty, it sends a DVMRP (S,G) Prune message to the upstream neighbor, following normal DVMRP behavior. ๐ŸŒ™

When a DVMRP component gets a (*,G) or (*,*) Prune alert, it's treated as if an (S,G) Prune alert arrived for every existing DVMRP (S,G) entry it covers. On top of that, if DWRs are being used, a DWR Leave message is sent within its domain. bye bye energy ๐Ÿ‘‹

When a DVMRP component gets an (S,G) Join alert, and a prune was previously sent upstream, it sends a DVMRP (S,G) Graft message to the upstream neighbor, following normal DVMRP behavior. ๐Ÿฆ‹

When a DVMRP component gets a (*,G) or (*,*) Join alert, it's treated as if an (S,G) Join alert arrived for every existing DVMRP (S,G) entry it covers. Also, if DWRs are being used, the component sends a DWR Join message within its domain. ๐Ÿ’–

4.2. MOSPF ๐ŸŒท

in this section we look at how the rules in section 2 apply to MOSPF. We're assuming you already know normal MOSPF behavior, as specified in [3]. Quick note: MOSPF can join and prune entire groups, but it can't do that for individual sources within groups ๐Ÿ™ƒ

Interoperability between MOSPF and dense-mode protocols (like DVMRP) is specified in [3], but we describe here how an MOSPF implementation can interoperate with all other multicast routing protocols. ๐Ÿซถ

An MOSPF component acts as a wildcard receiver for internally-reached sources if and only if some other component is a wildcard receiver for externally-reached sources. An MOSPF component acts as a wildcard receiver for externally-reached sources only if there are internally-reached domains that don't support some form of Domain-Wide-Reports (DWRs) [10]. Since MOSPF floods membership information throughout the domain, MOSPF itself is considered to support a form of DWRs natively. โœจ

4.2.1. Generating Alerts

A (*,*) Join alert goes to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when the first component becomes a wildcard receiver for external sources. This can happen when an MOSPF component starts up and decides to take on that role. ๐ŸŒธ

A (*,*) Prune alert goes to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when all components are no longer wildcard receivers for external sources. This can happen when an MOSPF component that was playing that role shuts down. ๐Ÿ‘‹

When it's known that there are no longer any members of a group G in the MOSPF domain, a (*,G) Prune alert goes to the "iif owner" for (*,G) according to the dispatcher. In MOSPF, this can happen when either:

  • IGMP tells MOSPF that there are no longer any directly-connected group members on an interface, or
  • Any router's group-membership-LSA for G is aged out.

When it's first known that there are members of a group G in the MOSPF domain, a (*,G) Join alert goes to the "iif owner" of (*,G), according to the dispatcher. In MOSPF, this can happen when any of the following occur:

  • IGMP tells MOSPF that directly-connected group members now exist on the interface, or
  • A group-membership-LSA is received for G. ๐Ÿ”ฅ

4.2.2. Processing Alerts

okay so when an MOSPF component gets an (S,G) Creation alert, it works out the shortest path tree for the whole MOSPF domain โœจ, then adds the downstream interfaces to the entry's oif list the normal MOSPF way ๐Ÿ—บ๏ธ

when an MOSPF component gets an (S,G) Prune alert, it just ignores it ๐Ÿ™ˆ bc MOSPF can only prune entire groups at once, so a single-source prune doesn't really fit ๐Ÿ’€

when an MOSPF component gets a (*,G) Prune alert, and there are no directly-connected members on any MOSPF interface, the router "prematurely ages" out its group-membership-LSA for G in the MOSPF domain, following normal MOSPF behavior ๐Ÿ“

when an MOSPF component gets either an (S,G) Join alert or a (*,G) Join alert, and G wasn't already in the router's group-membership-LSA (and the component is NOT a wildcard multicast receiver), it originates a group-membership-LSA in the MOSPF domain, again the normal MOSPF way ๐Ÿฆ‹

when an MOSPF component gets a (,) Prune alert, it stops being a wildcard multicast receiver in its domain ๐Ÿซถ

when an MOSPF component gets a (,) Join alert, it becomes a wildcard multicast receiver in its domain ๐Ÿ‘‘


4.3. PIM-DM

in this section we go over how the rules in section 2 apply to Dense-mode PIM ๐ŸŒธ we're assuming you already know normal PIM-DM behavior, as specified in [6] ๐Ÿ’…

okay so, like with ALL broadcast-and-prune protocols, PIM-DM components are automatically wildcard receivers for internally-reached sources โœจ unless some form of Domain-Wide-Reports (DWRs) [10] gets added to PIM-DM in the future, all PIM-DM components also act as wildcard receivers for externally-reached sources ๐Ÿ˜ญ and if DWRs are available for the domain, then a PIM-DM component only acts as a wildcard receiver for externally-reached sources if there are internally-reached domains that don't support some form of DWRs ๐Ÿ”ฅ

one simple heuristic to approximate DWRs is to assume that if there are any internally-reached members, then at least one of them is a sender ๐Ÿงš with this heuristic, the presense of any (S,G) state for internally-reached sources can be used instead ๐Ÿ’œ sending a data packet to a group is then equivalent to sending a DWR for the group ๐ŸŽ€

4.3.1. Generating Alerts

a (,) Join alert gets sent to the iif owner of the (,) entry (e.g., the Interop dispatcher) when the first component becomes a wildcard receiver for external sources ๐ŸŒˆ this can happen when a PIM-DM component starts up and doesn't support some form of DWRs ๐Ÿ’–

a (,) Prune alert gets sent to the iif owner of the (,) entry (e.g., the Interop dispatcher) when all components are no longer wildcard receivers for external sources ๐Ÿ˜” this can happen when a PIM-DM component that doesn't support some form of DWRs shuts down ๐Ÿซ 

an (S,G) Prune alert gets sent to the component owning the iif for a forwarding cache entry whenever the last oif is removed from the forwarding cache entry, and the iif is owned by another component โœจ in PIM-DM, that can happen when:

  • A PIM (S,G) Join/Prune message with S in the prune list is received on a point-to-point interface.
  • The Oif-Timer in an (S,G) route table entry expires.
  • A PIM (S,G) Assert message from a preferred neighbor is received on the interface.

an (S,G) Join alert gets sent to the component owning the iif for a forwarding cache entry whenever the first oif is added to an entry, and the iif is owned by another component ๐Ÿฆ‹ in PIM-DM, this can happen when any of these go down:

  • The oif's prune timer expires, or
  • A PIM-DM (S,G) Graft message is received on the interface, or
  • IGMP notifies PIM-DM that directly-connected group members now exist on the interface.

when it's known that there are no longer any members of a group G in the PIM-DM domain that receive data for externally-reached sources from the local router, a (,G) Prune alert gets sent to the "iif owner" for (,G) according to the dispatcher ๐Ÿ“ in PIM-DM, that can happen when:

  • The DWR for G times out.
  • The members-are-senders approximation is being used and PIM-DM's last (S,G) entry for G is timed out.

when it's first known that there are members of a group G in the PIM-DM domain, a (,G) Join alert gets sent to the "iif owner" of (,G), according to the dispatcher ๐ŸŒธ in PIM-DM, this can happen when either of these happens:

  • A DWR is received for G.
  • The members-are-senders approximation is being used and a data packet for G is received on one of the component's interfaces.

4.3.2. Processing Alerts

when a PIM-DM component gets an (S,G) Creation alert, it adds the component's interfaces to the entry's oif list (following normal PIM-DM behavior) EXCEPT for:

  • the iif,
  • leaf networks without local members of the entry's group,
  • and interfaces with scoped boundaries covering the group. ๐Ÿšง

when a PIM-DM component gets an (S,G) Prune alert, and the forwarding cache entry's oiflist is empty, it sends a PIM-DM (S,G) Prune message to the upstream neighbor, the normal PIM-DM way ๐Ÿ’…

when a PIM-DM component gets a (,G) or (,*) Prune alert, it's treated as if an (S,G) Prune alert were received for every matching (S,G) entry ๐Ÿซถ

when a PIM-DM component gets an (S,G) Join alert, and an (S,G) prune was previously sent upstream, it sends a PIM-DM (S,G) Graft message to the upstream neighbor, normal PIM-DM style โœจ

when a PIM-DM component gets a (,G) or (,*) Join alert, then for each matching (S,G) entry in the PIM-DM routing table where a prune was previously sent upstream, it sends a PIM-DM (S,G) Graft message to the upstream neighbor according to normal PIM-DM behavior ๐Ÿ”ฅ and on top of that, if DWR's are being used, the component sends a DWR Join message within its domain ๐Ÿ‘‘


4.4. PIM-SM

in this section we talk about how the rules in section 2 apply to Sparse-mode PIM ๐Ÿงš we're assuming you know normal PIM-SM behavior, as specified in [4] ๐Ÿ“š

the thing is, to get correct PIM-SM behavior within the domain, the PIM-SM domain MUST be convex so that Bootstrap messages reach all routers in the domain ๐Ÿซถ like, the shortest-path route from any internal router to any other internal router has to lie entirely within the PIM domain ๐Ÿ—บ๏ธ

unless some form of Domain-Wide-Reports (DWRs) [10] gets added to PIM-SM in the future, all PIM-SM components act as wildcard receivers for externally-reached sources ๐Ÿ˜ญ and if DWRs are available for the domain, then a PIM-SM component only acts as a wildcard receiver for externally-reached sources if there are internally-reached domains that don't support some form of DWRs ๐Ÿ’–

a PIM-SM component acts as a wildcard receiver for internally-reached sources if and only if any other component is a wildcard receiver for externally-reached sources ๐ŸŒˆ it does this by periodically sending (,,RP) Joins to all RPs for non-local groups (for example, 239.x.x.x is considered locally-scoped, and PIM-SM components do not send (,,RP) Joins to RPs supporting only that portion of the address space) ๐Ÿ“ the period is set according to standard PIM-SM rules for periodic Join/Prune messages โญ

to properly instantiate Rule 1, whenever PIM creates a PIM (S,G) entry for an externally-reached source, and the next hop towards S is reached via an interface owned by another component, the iif should always point towards S and not towards the RP for G ๐ŸŽ€ on top of that, the Border-bit is set in all PIM Register messages for this entry ๐Ÿ’…

finally, the PIM-SM component acts as a DR for externally-reached receivers in terms of being able to switch to the shortest-path tree for internally-reached sources ๐Ÿฆ‹

4.4.1. Generating Alerts

a (,) Join alert gets sent to the iif owner of the (,) entry (e.g., the Interop dispatcher) when the first component becomes a wildcard receiver for external sources ๐ŸŒธ this can happen when a PIM-SM component starts up and decides to take on that role โœจ

a (,) Prune alert gets sent to the iif owner of the (,) entry (e.g., the Interop dispatcher) when all components are no longer wildcard receivers for external sources ๐Ÿ’” this can happen when a PIM-SM component that was acting in this role shuts down ๐Ÿซ 

an (S,G) Prune alert gets sent to the component owning the iif for a forwarding cache entry whenever the last oif is removed from the entry and the iif is owned by another component ๐Ÿงš in PIM-SM, that can happen when:

  • A PIM (S,G) Join/Prune message with S in the prune list is received on a point-to-point interface, or
  • A PIM (S,G) Assert from a preferred neighbor was received on the interface, or
  • A PIM Register-Stop message is received for (S,G), or
  • The interface's Oif-Timer for PIM's (S,G) route table entry expires.
  • The Entry-Timer for PIM's (S,G) route table entry expires.

when it's known that there are no longer any members of a group G in the PIM-SM domain that receive data for externally-reached sources from the local router, a (,G) Prune alert gets sent to the "iif owner" for (,G) according to the dispatcher ๐Ÿ“š in PIM-SM, that can happen when:

  • A PIM (*,G) Join/Prune message with G in the prune list is received on a point-to-point interface, or
  • A PIM (*,G) Assert from a preferred neighbor was received on the interface, or
  • IGMP notifies PIM-SM that directly-connected members no longer exist on the interface.
  • The Entry-Timer for PIM's (*,G) route table entry expires.

an (S,G) Join alert gets sent to the component owning the iif for a forwarding cache entry whenever the first logical oif is added to an entry and the iif is owned by another component ๐ŸŒˆ in PIM-SM, this can happen when any of these go down:

  • A PIM (S,G) Join/Prune message is received on the interface, or
  • The Register-Suppression-Timer for (S,G) expires, or
  • The Entry-Timer for an (S,G) negative-cache state route table entry expires.

when it's first known that there are members of a group G in the PIM-SM domain, a (,G) Join alert gets sent to the "iif owner" of (,G), according to the dispatcher ๐Ÿ“ in PIM-SM, this can happen when any of these go down:

  • A PIM (*,G) Join/Prune message is received on the interface, or
  • A PIM (,,RP) Join/Prune message is received on the interface, or
  • (*,G) negative cache state expires, or
  • IGMP notifies PIM that directly-connected group members now exist on the interface.

4.4.2. Processing Alerts

Okay bestie, here's how a PIM-SM component handles incoming alerts ๐Ÿ’…โœจ

When a PIM-SM component gets an (S,G) Creation alert, it runs a longest match search ((S,G), then (*,G), then (*,*,RP)) through its multicast routing table ๐Ÿ”. Every outgoing interface on that entry gets added to the forwarding cache entry. Unless the PIM-SM component owns the iif, the oiflist also gets tweaked so it can send PIM Registers with the Border-bit set to the matching RP ๐Ÿฆ‹.

When a PIM-SM component gets an (S,G) Prune alert and the forwarding cache entry's oiflist is empty, it goes through each PIM (S,G) state entry it covers and sends an (S,G) Join/Prune message with S in the prune list up to the upstream neighbor, following normal PIM-SM behavior ๐ŸŒธ.

When a PIM-SM component gets a (*,G) Prune alert, it sends a (*,G) Join/Prune message with G in the prune list to the upstream neighbor toward the RP for G, following normal PIM-SM behavior ๐Ÿซถ.

When a PIM-SM component gets an (S,G) Join alert, it sends an (S,G) Join/Prune message to the next-hop neighbor toward S and resets the (S,G) Entry-timer, following normal PIM-SM behavior โฐ.

When a PIM-SM component gets a (*,G) Join alert, it sends a (*,G) Join/Prune message to the next-hop neighbor toward the RP for G and resets the (*,G) Entry-timer, following normal PIM-SM behavior ๐Ÿ’–.

When a PIM-SM component gets a (*,*) Join alert, it sends (*,*,RP) Join/Prune messages toward each RP ๐Ÿ‘‘.

When a PIM-SM component gets a (*,*) Prune alert, it sends a (*,*,RP) Prune toward each RP ๐Ÿฅ€.


4.5. CBTv2

Now we're talking about how the rules in section 2 apply to CBTv2 ๐ŸŽ€. We're assuming you already know normal CBTv2 behavior from [5], so no cap, you're prepared. The big thing to remember is that, like MOSPF, CBTv2 lets you join and prune entire groups, but not individual sources inside a group ๐Ÿ™ˆ.

Interop between a single CBTv2 stub domain and a DVMRP backbone is covered in [8]. The short version: CBTv2 MBR components get statically configured so that whenever an external route exists between two or more MBRs, one is designated as the primary and the others act as non-forwarding backups (to stop duplicate packets) ๐Ÿงš. So a CBTv2 domain must not serve as transit between two domains if another route between them exists ๐Ÿšซ.

Here's how a CBTv2 implementation can extend that to interoperate with all the other multicast routing protocols ๐Ÿ’œ. A CBTv2 component acts as a wildcard receiver for internally-reached sources if and only if some other component is a wildcard receiver for externally-reached sources. It does this by sending JOIN-REQUESTs for all non-local group ranges to all known cores, as described in [8] โœจ.

Unless some form of Domain-Wide-Reports (DWRs) [10] get added to CBTv2 in the future, all CBTv2 components act as wildcard receivers for externally-reached sources ๐ŸŒˆ. If DWRs are available for the domain, then a CBTv2 component acts as a wildcard receiver for externally-reached sources only if there are internally-reached domains that don't support some form of DWRs ๐Ÿฆ‹.

4.5.1. Generating Alerts

A (*,*) Join alert gets sent to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when the first component becomes a wildcard receiver for external sources ๐Ÿš€. This can happen when a PIM-SM component starts up and decides to take on that role ๐ŸŒŸ.

A (*,*) Prune alert gets sent to the iif owner of the (*,*) entry (for example, the Interop dispatcher) when all components stop being wildcard receivers for external sources ๐Ÿ˜ญ. This can happen when a PIM-SM component that was acting in that role shuts down ๐Ÿ•ฏ๏ธ.

When the last oif is removed from the core tree for G, a (*,G) Prune alert gets sent to the "iif owner" for (*,G) according to the dispatcher. CBTv2 always sends all data to the core, so the only time this can happen after the entry is created is when the MBR is the core itself ๐Ÿ‘‘. In that case, the last oif gets removed from the entry when:

  • A QUIT-REQUEST is received on the logical interface, and there are no directly-connected members present on the interface, or
  • IGMP tells CBT that there are no longer directly-connected members present on the interface, and the interface is not a CBT child interface for group G.

When the first CBT outgoing interface gets added to an existing core tree, a (*,G) Join alert gets sent to the "iif owner" of (*,G) according to the dispatcher. Same deal as before: because CBTv2 always sends all data to the core, these can only occur (other than when the entry is created) when the MBR is the core ๐Ÿซถ. In that case, the first logical oif gets added to an entry when:

  • A JOIN-REQUEST for G is received on the interface, or
  • IGMP tells CBT that directly-connected group members now exist on the interface.

4.5.2. Processing Alerts

When a CBTv2 component gets an (S,G) Creation alert, and the router is functioning as the designated BR, any CBT interfaces that are on the tree for G get added to the forwarding cache entry's oif list, following normal CBTv2 behavior ๐ŸŽ€.

When a CBTv2 component gets an (S,G) Prune alert, the alert gets ignored, because CBTv2 cannot prune specific sources ๐Ÿ™…โ€โ™€๏ธ. So it keeps receiving packets from S, since it has to keep receiving packets from other sources in group G anyway ๐Ÿ’….

When a CBTv2 component gets a (*,G) Prune alert, the router is not the primary core for G, and the only CBT on-tree interface is the interface toward the core, it sends a QUIT-REQUEST to the next-hop neighbor toward the core, following normal CBTv2 behavior ๐Ÿ‘‹.

When a CBTv2 component gets either an (S,G) Join alert or a (*,G) Join alert, the router is not the primary core for G, and the router is not already on the core-tree for G, it sends a CBT (*,G) JOIN-REQUEST to the next-hop neighbor toward the core, following normal CBTv2 behavior ๐ŸŒธ.


Here we're looking at how the section 2 rules apply to a link that isn't inside any routing domain ๐Ÿงš. That means no routing protocol messages get exchanged, and the interface isn't owned by any multicast routing protocol component ๐Ÿฅน. We're assuming you know normal IGMP behavior from [7]. Also, IGMPv2 lets you join and prune entire groups, but not individual sources within groups ๐Ÿ™ˆ.

An IGMP-only "component" can only own a single interface, so an IGMP-only domain only ever consists of one link ๐Ÿ”—. An IGMP-only component can only act as a wildcard receiver for internally-reached sources if all internally-reached sources are directly-connected. So either the IGMP-only domain (link) has to be a stub domain, or there must be no other components that are wildcard receivers for externally-reached sources ๐ŸŒˆ.

4.6.1. Generating Alerts

When it's known that there are no longer any directly-connected members of a group G on the IGMP-only interface, a (*,G) Prune alert gets sent to the "iif owner" for (*,G) according to the dispatcher. In IGMP, this can happen when:

  • The group membership times out.

When it's first known that there are directly-connected members of a group G on the interface, a (*,G) Join alert gets sent to the "iif owner" of (*,G) according to the dispatcher. In IGMP, this can happen when any of the following occur:

  • A Membership Report is received for G.

4.6.2. Processing Alerts

When an IGMP-only component gets an (S,G) Creation alert, and there are directly-connected members of G present on its interface, it adds the interface to the entry's oif list ๐ŸŒท.

When an IGMP-only component gets an (S,G) Prune alert, the alert gets ignored, since IGMP can only prune entire groups at a time ๐Ÿ™ƒ.

When an IGMP-only component gets a (*,G) Prune alert, the router leaves the group G and sends an IGMP Leave message if it was the last reporter, following normal IGMPv2 behavior ๐Ÿ‘‹.

When an IGMP-only component gets a (*,*) Prune alert, it leaves promiscuous multicast mode ๐Ÿซ .

When an IGMP-only component gets either an (S,G) Join alert or a (*,G) Join alert, and the component was not previously a member of G on the IGMP-only interface (and the component is not a wildcard receiver for internally reached sources), it joins the group on the interface. That makes it send an unsolicited Membership Report, following normal IGMP behavior ๐Ÿ“ฃ.

When an IGMP-only component gets a (*,*) Join alert, it enters promiscuous multicast mode ๐Ÿ‘€.


5. Security Considerations

Heads up, this part is serious! ๐Ÿšจ All operations described here are internal to multicast border routers. The rules described here do not change the security issues underlying the individual multicast routing protocols ๐Ÿ”. However, letting different protocols interact means that security weaknesses in any one protocol may also apply to the others as a result ๐Ÿ’€.

6. References

[1]   Ajit S. Thyagarajan and Stephen E. Deering.  Hierarchical
      distance-vector multicast routing for the MBone.  In
      "Proceedings of the ACM SIGCOMM", pages 60--66, October 1995.

[2]   Pusateri, T., "Distance Vector Multicast Routing Protocol",
      Work in Progress.

[3]   Moy, J., "Multicast Extensions to OSPF", RFC 1584, March 1994.

[4]   Estrin, D., Farinacci, D., Helmy, A., Thaler, D., Deering, S.,
      Handley, M., Jacobson, V., Liu, C., Sharma, P. and L. Wei,
      "Protocol Independent Multicast-Sparse Mode (PIM-SM): Protocol
      Specification", RFC 2362, June 1998.

[5]   Ballardie, A., "Core Based Trees (CBT version 2) Multicast
      Routing", RFC 2189, September 1997.

[6]   Estrin, Farinacci, Helmy, Jacobson, and Wei, "Protocol
      Independent Multicast (PIM), Dense Mode Protocol
      Specification", Work in Progress.

[7]   Fenner, W., "Internet Group Management Protocol, Version 2",
      RFC 2236, November 1997.

[8]   Ballardie, A., "Core Based Tree (CBT) Multicast Border Router
      Specification", Work in Progress.

[9]   Thaler, D., Estrin, D. and D. Meyer, "Border Gateway Multicast
      Protocol (BGMP): Protocol Specification", Work in Progress.

[10]  Fenner, W., "Domain Wide Multicast Group Membership Reports",
      Work in Progress.

7. Author's Address

Dave Thaler
Microsoft
One Microsoft Way
Redmond, WA 98052

Phone: (425) 703-8835
EMail: dthaler@microsoft.com

okay bestie, this part is the legal stuff, but it's actually pretty chill ๐Ÿ’… ngl it's giving "you can share this, you can make stuff based on it, just don't pretend you wrote it" ๐Ÿซถ

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐Ÿ’œ

So the vibe is: you can copy this doc and hand it to your friends, and you can write your own commentary or explainers about it, or make tools that help people actually use it, and you can publish and distribute all of that, whole or in part, no restrictions of any kind ๐Ÿฆ‹ the one big rule is you have to keep the copyright notice and this paragraph on every copy and every derivative work. iykyk, it's the Internet Society's way of getting credit ๐ŸŒธ

But the original document itself? Hands off ๐Ÿ™ˆ It may not be modified in any way. You can't strip the copyright notice, and you can't scrub out the references to the Internet Society or other Internet organizations. The exceptions are: if you're doing it for developing Internet standards (then you follow the copyright procedures in the Internet Standards process), or if you're translating it into a language other than English. Both are allowed, but only in those specific cases ๐Ÿ‘‘

The permissions here are perpetual, and the Internet Society or its successors or assigns will not revoke them. So once it's granted, it's forever ๐Ÿ’–

Now the disclaimer, which is the serious part ๐Ÿ˜ญ This document and the information in it are provided on an "AS IS" basis. THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, including but not limited to any warranty that using the information here will not infringe any rights, and any implied warranties of merchantability or fitness for a particular purpose. Translation: they're not promising it works for your specific thing, so test before you ship ๐Ÿงš

Acknowledgement ๐ŸŒˆ

Funding for the RFC Editor function is currently provided by the Internet Society. So the people keeping these documents organized and published are being funded by the Internet Society right now โœจ

๐Ÿ“ฆ where this page comes from