Multicast with PIM-SM
This lab shows a multicast routing example using PIM in Sparse Mode, with pimd. For the source specific variant, which needs neither a Rendezvous Point nor a Bootstrap Router, see Multicast with PIM-SSM.
Overview¶
Network diagram¶
Here is the logical and physical view:
flowchart TD
VM1["VM1 (multicast source)<br/>vtnet0: 10.0.12.1"]
VM2["VM2 (PIM router, Candidate-RP)<br/>vtnet0: 10.0.12.2<br/>vtnet1: 10.0.23.2"]
VM3["VM3 (PIM router, Candidate-BSR)<br/>vtnet1: 10.0.23.3<br/>vtnet2: 10.0.34.3"]
VM4["VM4 (multicast receiver)<br/>vtnet2: 10.0.34.4"]
VM1 ---|"10.0.12.0/24<br/>source LAN"| VM2
VM2 ---|"10.0.23.0/24<br/>PIM adjacency"| VM3
VM3 ---|"10.0.34.0/24<br/>receiver LAN"| VM4
VM2 is the Rendezvous Point (RP) for the whole 224.0.0.0/4 range and VM3 is
the Bootstrap Router (BSR) that floods the RP set. VM1 and VM4 are plain hosts:
VM1 sends the multicast flow, VM4 joins the group with IGMP.
Setting up the lab¶
Downloading BSD Router Project images¶
Download the BSDRP serial image (to avoid needing an X display) from SourceForge.
Download lab scripts¶
More information on the BSDRP lab scripts is available in How to build a BSDRP router lab.
Start the lab with 4 routers. The -r pimsm flag makes the lab script build
per-VM cloud-init disks that apply the configuration below automatically on
first boot (through the labconfig script shipped in the image):
tools/BSDRP-lab-bhyve.sh -i BSDRP-2.3-full-amd64.img.xz -n 4 -r pimsm
Without -r pimsm the 4 VMs boot unconfigured and you can enter the
configuration of each router by hand, as described below.
Router configuration¶
VM1 (multicast source)¶
A plain host, no PIM:
sysrc hostname=VM1 \
gateway_enable=no \
ipv6_gateway_enable=no \
ifconfig_vtnet0="inet 10.0.12.1/24" \
defaultrouter=10.0.12.2
service hostname restart
service netif restart
service routing restart
config save
VM2 (Candidate Rendezvous Point)¶
VM2 is a PIM router that announces itself (10.0.23.2) as Candidate-RP with an advertisement period of 10 seconds and high priority: it will become the rendezvous point.
sysrc hostname=VM2 \
gateway_enable=yes \
ipv6_gateway_enable=yes \
ifconfig_vtnet0="inet 10.0.12.2/24" \
ifconfig_vtnet1="inet 10.0.23.2/24" \
defaultrouter=10.0.23.3 \
pimd_enable=yes
cat > /usr/local/etc/pimd.conf <<EOF
rp-candidate 10.0.23.2 time 10 priority 1
#rp-address 10.0.23.2
EOF
service hostname restart
service netif restart
service routing restart
service pimd start
config save
VM3 (Candidate Bootstrap Router)¶
VM3 announces itself (10.0.23.3) as a Candidate-BSR with high priority.
sysrc hostname=VM3 \
gateway_enable=yes \
ipv6_gateway_enable=yes \
ifconfig_vtnet1="inet 10.0.23.3/24" \
ifconfig_vtnet2="inet 10.0.34.3/24" \
defaultrouter=10.0.23.2 \
pimd_enable=yes
cat > /usr/local/etc/pimd.conf <<EOF
bsr-candidate 10.0.23.3 priority 1
#rp-address 10.0.23.2
EOF
service hostname restart
service netif restart
service routing restart
service pimd start
config save
VM4 (multicast receiver)¶
Another plain host, no PIM:
sysrc hostname=VM4 \
gateway_enable=no \
ipv6_gateway_enable=no \
ifconfig_vtnet2="inet 10.0.34.4/24" \
defaultrouter=10.0.34.3
service hostname restart
service netif restart
service routing restart
config save
Checking NIC drivers and bhyve compatibility with multicast¶
Before moving to the advanced routing setup, test simple multicast between two directly connected hosts. Some NICs (such as vtnet) or hypervisor network setups do not handle even basic multicast correctly.
On VM1, start a multicast generator (an iperf client emitting multicast):
[root@VM1]~# iperf -c 239.1.1.1 -u -T 32 -t 300 -i 1
------------------------------------------------------------
Client connecting to 239.1.1.1, UDP port 5001
Sending 1470 byte datagrams, IPG target: 0.00 us (kalman adjust)
UDP buffer size: 9.00 KByte (default)
------------------------------------------------------------
[ 1] local 10.0.12.1 port 46504 connected with 239.1.1.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-1.00 sec 129 KBytes 1.06 Mbits/sec
[ 1] 1.00-2.00 sec 128 KBytes 1.05 Mbits/sec
[ 1] 2.00-3.00 sec 128 KBytes 1.05 Mbits/sec
(...)
On the directly connected VM2, check whether it sees multicast packets in non-promiscuous mode:
[root@VM2]~# tcpdump -pni vtnet0 -c 2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on vtnet0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23:29:32.800991 IP 10.0.12.1.46504 > 239.1.1.1.5001: UDP, length 1470
23:29:32.812784 IP 10.0.12.1.46504 > 239.1.1.1.5001: UDP, length 1470
2 packets captured
9 packets received by filter
0 packets dropped by kernel
VM2 receives multicast packets from 10.0.12.1 to multicast group 239.1.1.1. Now start a multicast listener on VM2 (an iperf server); it should receive the multicast flow:
[root@VM2]~# iperf -s -u -B 239.1.1.1%vtnet0 -i 1
------------------------------------------------------------
Server listening on UDP port 5001
Joining multicast (*,G)=*,239.1.1.1 w/iface vtnet0
Server set to single client traffic mode (per multicast receive)
UDP buffer size: 41.1 KByte (default)
------------------------------------------------------------
[ 1] local 239.1.1.1 port 5001 connected with 10.0.12.1 port 46504
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 1] 0.00-1.00 sec 129 KBytes 1.06 Mbits/sec 0.028 ms 15995/16085 (99%)
[ 1] 1.00-2.00 sec 128 KBytes 1.05 Mbits/sec 0.049 ms 0/89 (0%)
[ 1] 2.00-3.00 sec 128 KBytes 1.05 Mbits/sec 0.044 ms 0/89 (0%)
(...)
The multicast receiver is correctly receiving at 1 Mb/s (the loss reported on the first line just counts the datagrams sent before the listener started).
Always bind the listener to an interface
If the source interface is not given (iperf -s -u -B 239.1.1.1 -i 1),
iperf joins the group on the wrong interface and the server stays in
"waiting" mode forever.
Checking pimd behavior¶
The examples below were captured with pimd 3.1.0 on BSDRP 2.3. The -p flag of
pimctl disables the terminal control characters used to highlight table
headings, which keeps the output copy-pasteable:
[root@VM2]~# pimctl -p version
pimd version 3.1.0
PIM neighbors¶
Do the PIM routers see each other?
[root@VM2]~# pimctl -p show
_______________________________________________________________________________
PIM Interface Table
=================================================================================================
Interface State Address Priority Hello Nbr DR Address DR Priority
=================================================================================================
vtnet0 Up 10.0.12.2 1 30 0 10.0.12.2 1
vtnet1 Up 10.0.23.2 1 30 1 10.0.23.3 1
_______________________________________________________________________________
PIM Neighbor Table
==================================================================================
Interface Address Priority Mode Uptime/Expires
==================================================================================
vtnet1 10.0.23.3 1 DR 0h11m31s/0h1m40s
_______________________________________________________________________________
Multicast Routing Table
===============================================================================
Source Group RP Address Flags
===============================================================================
Number of Groups : 0
Number of Cache MIRRORs : 0
_______________________________________________________________________________
PIM Candidate Rendez-Vous Point Table
===============================================================================
Group Address RP Address Prio Holdtime Expires
===============================================================================
232.0.0.0/8 169.254.0.1 1 Forever Never
224.0.0.0/4 10.0.23.2 1 150 0h2m10s
Current BSR address: 10.0.23.3
_______________________________________________________________________________
PIM Rendez-Vous Point Set Table
===============================================================================
Group Address RP Address Prio Holdtime Type
===============================================================================
232.0.0.0/8 169.254.0.1 1 Forever Static
224.0.0.0/4 10.0.23.2 1 130 Dynamic
VM2 sees VM3 as a PIM neighbor (and as the Designated Router of the 10.0.23.0/24 link). It also learned, through the BSR 10.0.23.3, that it (10.0.23.2) is itself the RP for 224.0.0.0/4.
VM3 has the symmetric view:
[root@VM3]~# pimctl -p show neighbor
_______________________________________________________________________________
PIM Neighbor Table
==================================================================================
Interface Address Priority Mode Uptime/Expires
==================================================================================
vtnet1 10.0.23.2 1 0h11m32s/0h1m40s
Does the PIM daemon register to the PIM multicast group?¶
A PIM router must register to the 224.0.0.13 multicast group. Check that all PIM routers list this group on their enabled interfaces:
[root@VM2]~# ifmcstat -f inet
vtnet0:
inet 10.0.12.2
igmpv3 rv 2 qi 125 qri 100 uri 3
group 224.0.0.22 mode exclude
group 224.0.0.2 mode exclude
group 224.0.0.13 mode exclude
group 224.0.0.1 mode exclude
vtnet1:
inet 10.0.23.2
igmpv3 rv 2 qi 125 qri 100 uri 3
group 224.0.0.22 mode exclude
group 224.0.0.2 mode exclude
group 224.0.0.13 mode exclude
group 224.0.0.1 mode exclude
lo0:
inet 127.0.0.1
igmpv3 rv 2 qi 125 qri 10 uri 3
group 224.0.0.1 mode exclude
The multicast group 224.0.0.13 is correctly subscribed on the PIM-enabled interfaces.
Testing¶
1. Start a multicast receiver (iperf server) on VM4¶
Start the receiver first: the IGMP report it sends makes VM3 build the shared tree toward the RP before any traffic exists.
[root@VM4]~# iperf -s -u -B 239.1.1.1%vtnet2 -i 1
------------------------------------------------------------
Server listening on UDP port 5001
Joining multicast (*,G)=*,239.1.1.1 w/iface vtnet2
Server set to single client traffic mode (per multicast receive)
UDP buffer size: 41.1 KByte (default)
------------------------------------------------------------
2. Check that VM3 notices the subscriber¶
VM3 records the IGMP membership of 10.0.34.4 and creates the (*,G) entry pointing to the RP, even though no source is active yet:
[root@VM3]~# pimctl -p show igmp groups
_______________________________________________________________________________
IGMP Group Membership Table
===============================================================================
Interface Group Source Last Reported Timeout
===============================================================================
vtnet2 239.1.1.1 ANY 10.0.34.4 385
[root@VM3]~# pimctl -p show mrt
_______________________________________________________________________________
Multicast Routing Table
===============================================================================
Source Group RP Address Flags
===============================================================================
ANY 239.1.1.1 10.0.23.2 WC RP
Number of Groups : 1
Number of Cache MIRRORs : 0
3. Start the multicast generator (iperf client) on VM1¶
[root@VM1]~# iperf -c 239.1.1.1 -u -T 32 -t 300 -i 1
------------------------------------------------------------
Client connecting to 239.1.1.1, UDP port 5001
Sending 1470 byte datagrams, IPG target: 0.00 us (kalman adjust)
UDP buffer size: 9.00 KByte (default)
------------------------------------------------------------
[ 1] local 10.0.12.1 port 46504 connected with 239.1.1.1 port 5001
[ ID] Interval Transfer Bandwidth
[ 1] 0.00-1.00 sec 129 KBytes 1.06 Mbits/sec
[ 1] 1.00-2.00 sec 128 KBytes 1.05 Mbits/sec
[ 1] 2.00-3.00 sec 128 KBytes 1.05 Mbits/sec
4. Check that VM2 switched to the shortest-path tree¶
VM2, the RP and the Designated Router of the source LAN, registers the source and then switches the flow to the (S,G) shortest-path tree:
[root@VM2]~# pimctl -p show mrt
_______________________________________________________________________________
Multicast Routing Table
===============================================================================
Source Group RP Address Flags
===============================================================================
ANY 239.1.1.1 10.0.23.2 WC RP
10.0.12.1 239.1.1.1 10.0.23.2 SPT CACHE ASSERTED SG
Number of Groups : 1
Number of Cache MIRRORs : 1
The kernel multicast forwarding table confirms the traffic is forwarded from the source LAN (vif 1) to the VM3 link (vif 2):
[root@VM2]~# netstat -g
IPv4 Virtual Interface Table
Vif Thresh Local-Address Remote-Address Pkts-In Pkts-Out
0 1 10.0.12.2 0 0
1 1 10.0.12.2 1117 0
2 1 10.0.23.2 0 1117
IPv4 Multicast Forwarding Table
Origin Group Packets In-Vif Out-Vifs:Ttls
10.0.12.1 239.1.1.1 1117 1 2:1
IPv6 Multicast Interface Table is empty
IPv6 Multicast Forwarding Table is empty
5. Check that VM3 forwards the flow to the receiver¶
[root@VM3]~# pimctl -p show mrt
_______________________________________________________________________________
Multicast Routing Table
===============================================================================
Source Group RP Address Flags
===============================================================================
ANY 239.1.1.1 10.0.23.2 WC RP CACHE ASSERTED
Number of Groups : 1
Number of Cache MIRRORs : 1
[root@VM3]~# netstat -g
IPv4 Virtual Interface Table
Vif Thresh Local-Address Remote-Address Pkts-In Pkts-Out
0 1 10.0.23.3 0 0
1 1 10.0.23.3 2042 0
2 1 10.0.34.3 0 2042
IPv4 Multicast Forwarding Table
Origin Group Packets In-Vif Out-Vifs:Ttls
10.0.12.1 239.1.1.1 2042 1 2:1
IPv6 Multicast Interface Table is empty
IPv6 Multicast Forwarding Table is empty
VM3 correctly learns that the source is reached through vif 1 (toward VM2) and that the subscriber is on vif 2 (toward VM4).
6. Check the receiver¶
Back on VM4, the iperf server receives the full 1 Mb/s flow without loss:
[ 1] local 239.1.1.1 port 5001 connected with 10.0.12.1 port 46504
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 1] 0.00-1.00 sec 129 KBytes 1.06 Mbits/sec 0.075 ms 0/90 (0%)
[ 1] 1.00-2.00 sec 128 KBytes 1.05 Mbits/sec 0.089 ms 0/89 (0%)
[ 1] 2.00-3.00 sec 128 KBytes 1.05 Mbits/sec 0.024 ms 0/89 (0%)
[ 1] 3.00-4.00 sec 128 KBytes 1.05 Mbits/sec 0.032 ms 0/89 (0%)
The multicast flow crosses the two PIM-SM routers end to end.