Configuring Multicast routing with PIM Sparse-Mode (Part 1)

In this post I'm going to walk through how we can configure basic multicast routing using PIM Sparse-Mode. I'm going to walk though how the multicast traffic flows from the source to the receiver, what's the role of the Rendezvous Point (RP), how are the shared-tree and the source-tree (Shortest Path Tree, SPT) built, and how does PIM work in general. First let's take a look at the topology:

Multicast Topology

Basic Multicast configuration using PIM Sparse-Mode

For the core routers I use the CSR1000v image, and regular IOSv for the source and the receiver. As IGP I use OSPF, the full reachability is already established between all of the devices. To enable multicast routing we need to do the following on all of the devices in the core:

CSR1_RP(config)#ip multicast-routing distributed 
CSR1_RP(config)#int range g1 - 2
CSR1_RP(config-if-range)#ip pim sparse-mode 
CSR1_RP(config)#ip pim rp-address 10.1.1.1
CSR1_RP(config)#
*Jul 18 09:11:40.105: %LINEPROTO-5-UPDOWN: Line protocol on Interface Tunnel0, changed state to up
*Jul 18 09:11:40.252: %LINEPROTO-5-UPDOWN: Line protocol on Interface Tunnel1, changed state to up

We enable multicast routing globally with the ip multicast-routing distributed, and we enable PIM sparse-mode on all of the interfaces in the core. Also on the First Hop Router (FHR = CSR4) we also enable PIM SM on the G2 interface facing the multicast source and on the Last Hop Router (LHR = CSR5) we enable PIM SM on the receiver-facing interface (G2). We won't establish PIM neighborship with the source, but with ip pim sparse-modeon the interface we're listening for IGMP messages which is used by the receiver to signal the multicast group he wants to receive. For sparse-mode we also need at least one RP in the core, we can configure it statically like I did above with the ip pim rp-address 10.1.1.1command, or we can configure it dynamically using BSR or Auto-RP. If we choose the static configuration (which is obviously not scalable if we have a lot of devices) we need to issue this command on every router, including the RP itself which is CSR1 in this example. If we take a look at the RP, two tunnel interfaces are automatically created, they are used to tunnel multicast traffic from the FHR towards the RP before the multicast traffic can flow natively.

For verification we can use the following command, like OSPF or any other IGP, PIM should establish a neighbor relationship with all of the neighboring devices which also run PIM:

CSR1_RP(config)#do show ip pim neighbor
PIM Neighbor Table
Mode: B - Bidir Capable, DR - Designated Router, N - Default DR Priority,
      P - Proxy Capable, S - State Refresh Capable, G - GenID Capable,
      L - DR Load-balancing Capable
Neighbor          Interface                Uptime/Expires    Ver   DR
Address                                                            Prio/Mode
10.0.134.4        GigabitEthernet1         00:01:16/00:01:27 v2    1 / DR S P G
10.0.134.3        GigabitEthernet1         00:01:51/00:01:27 v2    1 / S P G
10.0.12.2         GigabitEthernet2         00:02:12/00:01:29 v2    1 / DR S P G

Client joins a multicast group

Now on R6 let's join the multicast group of 239.1.1.1:

R6_RECEIVER(config)#int g0/0
R6_RECEIVER(config-if)#ip igmp join-group 239.1.1.1

Remember, R6 doesn't run PIM, receivers send IGMP messages to tell the FHR that they want to receive multicast traffic. Here is the IGMP Membership Report (aka. IGMP Join) R6 sent towards the LHR:

IGMP Membership Report
IGMP Membership Report sent from the Receiver towards the LHR

We use IGMPv2 by default on IOS, for Source Specific Multicast (SSM) we need IGMPv3. Here with IGMPv2 we only specify the group we're interested in, we don't care who the source is. IGMP Join messages are sent to the destination group address which receiver wants to join to (239.1.1.1). Besides that the LHR also periodically sends IGMP Membership Query messages to the local broadcast domain with a destination address of 224.0.0.1. It's important to note that IGMP messages never leave the receiver's local segment, they are not forwarded in the core. Instead the LHR creates a (*,G) entry in his mroute table and sends a PIM Join towards the RP to build the shared tree.

Building the (*,G) shared tree

In response to the IGMP Join from the client the LHR sends a PIM Join towards the RP:

PIM (*,G) Join
PIM Join from CSR5 sent towards the RP

PIM messages are sent to the well-known link-local address of 224.0.0.13. Here CSR5 builds the shared, or (*,G) tree (sometimes called RP tree) towards the RP. Look at the RP bit in the PIM Join message: this indicates that we're building the (*,G) tree, we don't know at this point who the source is (hence the star). Also every PIM router along the way towards the RP adds this (*,G) state to his mroute table:

CSR1_RP(config)#do show ip mroute | section 239
(*, 239.1.1.1), 00:05:19/00:03:04, RP 10.1.1.1, flags: S
  Incoming interface: Null, RPF nbr 0.0.0.0
  Outgoing interface list:
    GigabitEthernet1, Forward/Sparse, 00:01:34/00:03:04

CSR1 (who is the RP) is the root of the shared tree, it adds the interface G1 to the OIL (Outgoing interface list) which the PIM Join was received on. Similarly, CSR2 adds G1 to his OIL, and CSR5 adds G2 to his OIL. The incoming interface is Null on CSR1, because CSR1 is the root of the tree itself (he is the RP), on CSR2 the Incoming Interface would be G2, which is pointing towards the RP. So this is how the shared tree looks like at this point:

PIM shared tree
PIM shared tree

At this point the source hasn't started sending multicast yet. Still, routers periodically send PIM Joins for the (*,239.1.1.1) every 60 seconds to maintain the state in the mroute table and also to indicate for the RP that we have clients wanting to receive multicast traffic destined to that particular group address.

Turning off SPT Switchover on CSR5

Before the source starts sending multicast, I turn off the SPT Switchover on CSR5:

CSR5(config)#ip pim spt-threshold ?
  0         Always switch to source-tree
  infinity  Never switch to source-tree

CSR5(config)#ip pim spt-threshold infinity

What this option does is it prevents CSR5 from joining the (S,G) source tree (sometimes called SPT tree). By default when the multicast stream destined to 239.1.1.1 gets to CSR5, CSR5 learns the source of the multicast stream and sends a (S,G) PIM Join towards the source and build the so called source tree. Once the SPT tree is built multicast traffic will flow through the shortest path to the receiver, in this example: CSR4 -> CSR3 -> CSR5, and it won't be flowing through the RP. So here we have two options, with the infinity option we simply turn off the SPT switchover, while the 0 options enables the switchover once the source of the multicast stream is learned.

Source starts sending multicast - PIM Register

Now let's start sending multicast traffic from R7. We simply send ICMP echoes to the multicast group address. By doing this we also get a response back from the receiver. Usually multicast traffic is unidirectional and we use UDP for transport protocol, but sending ping with ICMP is a great way to verify that multicast works:

R7_SOURCE#ping 239.1.1.1 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 239.1.1.1, timeout is 2 seconds:

Reply to request 0 from 10.0.56.6, 77 ms
Reply to request 1 from 10.0.56.6, 13 ms
Reply to request 2 from 10.0.56.6, 4 ms
Reply to request 3 from 10.0.56.6, 5 ms
Reply to request 4 from 10.0.56.6, 12 ms

We can verify that we have one receiver, R6 (10.0.56.6) and the multicast stream successfully got to R6. Once CSR4, the FHR gets the multicast traffic he encapsulates it into a unicast packet and sends to the RP's address, that is what's called a PIM Register packet:

PIM Registration
PIM Registration: multicast packet encapsulated in unicast and send to the RP as a unicast packet

Remember that at this point there's no tree built yet between the FHR and the RP (we only have a shared tree between the receivers and the RP), the FHR only knows the IP address of the RP, so it sends the first few packets as unicast to the RP. Once the RP learns the address of the source, it sends a PIM (S,G) Join, and builds the (S,G) source tree from the RP towards the source. Once the (S,G) source tree is build, multicast traffic can flow natively, and the RP sends a PIM Register Stop message to the FHR (CSR4):

PIM Register Stop
RP sends a PIM Register Stop to the FHR

Now let's take a look at the mroute table of CSR1:

CSR1_RP(config)#do show ip mroute | section 239
(*, 239.1.1.1), 00:13:16/00:03:02, RP 10.1.1.1, flags: S
  Incoming interface: Null, RPF nbr 0.0.0.0
  Outgoing interface list:
    GigabitEthernet1, Forward/Sparse, 00:09:31/00:03:02
(10.0.47.7, 239.1.1.1), 00:03:07/00:02:14, flags: PTX
  Incoming interface: GigabitEthernet1, RPF nbr 10.0.134.4
  Outgoing interface list: Null

Notice that besides the (*,G), we also have a corresponding (S,G) entry. The OIL of the (S,G) entry is empty, while the OIL of the (*,G) entry still has the G1 interface. So from the perspective of CSR1: we use the source (S,G) tree from the FHR to the RP, and from the RP to the LHR we still use the (*,G) shared tree. At this point CSR5 doesn't have the (S,G) entry in his mroute table, since we turned off the SPT switchover earlier. We can easily determine that multicast flows though a sub-optimal path (CSR4 -> CSR1 -> CSR2 -> CSR5). The best path according to OSPF would be through CSR3 (every link has a cost of 1).

Turning on SPT Switchover on CSR5, and building the SPT tree towards the source

So to be able to build the SPT tree from CSR5 let's turn back on the SPT switchover:

CSR5(config)#ip pim spt-threshold 0

The moment I issue this command CSR5 sends a (S,G) PIM Join towards the source:

PIM (S,G) Join
PIM (S,G) Join sent from CSR5

Notice that the RP bit is not set this time, and also CSR5 specifies the source (10.0.47.7) which indicates that this is a (S,G) PIM Join and CSR5 wants to build the source tree. So the source tree from the source to the receiver looks like this at this point:

Source tree
PIM source tree

As the name says: the SPT tree is the shortest path tree from the receiver's perspective to the source according to the IGP we use. So we really only need the RP to find the source, once the source is found we can directly build the tree towards the source.

Now CSR5 also has a corresponding (S,G) entry in his mroute table:

CSR5(config)#do show ip mroute | section 239
(*, 239.1.1.1), 00:21:00/stopped, RP 10.1.1.1, flags: SJC
  Incoming interface: GigabitEthernet1, RPF nbr 10.0.235.3
  Outgoing interface list:
    GigabitEthernet2, Forward/Sparse, 00:17:15/00:02:33
(10.0.47.7, 239.1.1.1), 00:04:04/00:02:45, flags: JT
  Incoming interface: GigabitEthernet1, RPF nbr 10.0.235.3
  Outgoing interface list:
    GigabitEthernet2, Forward/Sparse, 00:04:04/00:02:33

Notice that the (*,G) is still maintained: the client has only specified the multicast group address, it doesn't care about the source thus this is sometimes called any source multicast. If R7 stops broadcasting CSR5 can easily switch to another source because client didn't requested the multicast from a specific source. If the client specifies the source, CSR5 doesn't really need the RP, we can directly build the (S,G) tree since we know the source.