IP多路组播技术,英文为IP Multicast, 就是英文文档里经常说到的BUM报文里的大M。这是一门特别的技术,它从2层到3层协议mac地址到IP地址都自成一体。很多网工同行只在IE考试里学习了一下,后来就不怎么使用了,究其原因是该技术只在某些特定领域里使用。使用(往往是大量使用)组播技术的领域有广播行业或有IPTV业务的机构,据说央视就部署了很多组播设备。还有就是在金融行业,使用组播技术来达到同时向多个服务器下单的目的。
简单描述一下什么是组播,我们用微信来做个比喻:想象一下小A要同时向小B小C小D...小Z发一段语音,他会怎么做?一,他可以向每个人发一段同样的语音。二,他也可以拉一个群把人都放进去,然后给群里发一段语音。后者的做法就是组播技术的原理,把消息发到一个群里也就是组播地址(multicast group IP), 所有群成员都可以收到消息,这样大大减少了信息源的工作不需要给每个群成员单独发消息。
组播技术的学习分两部分,组播技术2层用的是IGMP协议,在3层用的是PIM协议,尤其PIM是学习难点。下文会简要的讲解一下这两个协议 ,关于PIM今天我们只讲PIM-SM。以下是本文的提纲。
- 基本原理
- 组播二层协议IGMP
- 组播三层协议三层PIM
- PIM-SM的工作流程
- 一个简单的实验
- 排错清单
基本原理
组播的目的就是要让一个终端能同时向多个终端发送数据报文。这些接收的终端都需要加入到一个IP组地址(multicast group IP)中,才能收到信息源发送的报文。IANA规定224.0.0.0/4 这个D类网段为组播的IP地址段,这个网域包含从224.0.0.0 到 239.255.255.255 的所有地址,对应二进制地址中以1110开头的所有地址。
在这些组播地址中还有预留给某些协议的专用地址。
224.0.0.0/24 | 子网内控制报文 |
224.0.1.0/24 | 不同网段的控制报文 |
224.0.0.1 | 网段内所有的主机 |
224.0.0.2 | 网段内所有的路由器 |
224.0.0.5 | 所有OSPF路由器 |
224.0.0.6 | OSPF中的指定路由器 (Designated Routers) |
224.0.0.9 | 所有RIPv2路由器 |
224.0.0.22 | IGMPv3协议 |
224.0.0.13 | 所有PIM路由器 |
224.0.1.1 | NTP设备 |
因为群组IP地址是一个共享地址所以对应的mac地址也是共享地址,所有群成员(也就是加入群组里的接收端)都要让自己侦听这个地址。
组播MAC地址的前24位总是固定的以01:00:5E开头, 并且组播MAC地址中的第25位总为0,所剩下的23位就要用于匹配对应的组播IP地址。而前文说了组播的IP地址的前4位是不变的,这样算下来组播MAC地址中可变的23位要就用来匹配组播IP中可变的28位,这就造成了组播MAC地址到组播IP地址的影射中有5位是不能一对一对应的 -- 不同的IP地址使用同一个MAC地址。因此在选择组播IP地址时应避免同时使用239.0.x.y 和239.128.x.y这两个区间的地址 [1]。(239.128.0.0 和239.0.0.0映射到同一个MAC地址,239.128.0.1则与 239.0.0.1使用同一个MAC地址如此类推。)
组播二层协议IGMP
终端是不会使用组播的MAC地址作为发送报文的源地址的,所以交换机是不能通过mac learning学到组播的MAC地址,因而在这种情况下交换机只能把发给组播地址的报文向整个VLAN泛洪,这也是交换机一般的默认设置。对于要用作组播的网络,把所有组播报文进行全网泛洪自然是不理想的,使用IGMP协议(RFC4541)即可以让交换机选择性地只把组播报文发送到加入到该组播地址组的端口。IGMP协议主要包含两个部分(1)IGMP Snooping和(2)IGMP Querier。
IGMP Snooping能把组播MAC地址添加到交换机的MAC地址表中,这依赖于终端组员发送IGMP join报文来加入IGMP地址组,IGMP会把该地址加入到对应的地址表上,用命令show mac address-table multicast可查看当前交换机上有的组播MAC地址。 发送到一个组播地址的报文会被复制并发送到所有加入到该地址组的端口。用命令show ip igmp snooping groups可以查询那些端口加入到IGMP Snooping的地址组中。
SW1#sh ip igmp snooping groups
Vlan Group Type Version Port-List
--------------------------------------------------------------------------------
900 239.20.20.20 Dynamic - Et1, Cpu
IGMP Snooping需要终端发送IGMP join的报文,在Linux中可以用这个命令sudo ip addr add <multicast group address>/32 dev eth1 autojoin来加入一个组播地址。例如加入239.20.20.20, 用sudo ip addr add 239.20.20.20/32 dev eth1 autojoin。
但是有些终端是不具备发送IGMP report的功能,这个情况下可以配置静态关联。
SW1(config)#interface et5
SW1(config-if-Et4)#ip igmp static-group 239.150.150.160
用命令show ip igmp member查看所有加入到igmp组播的成员,包括用静态关联加入的也会显示。
#sh ip igmp membership
Interface----------------Group Address----IncludeSrc----------ExcludeSrc----------
Ethernet5 239.150.150.160 0.0.0.0
Vlan300 224.0.1.129 0.0.0.0
IGMP Querier会周期性地广播发出queries报文到VLAN中,在该网段的终端通过回复querier来表达要加入的组地址。在一个网段中如果有组播路由器,IGMP Querier的角色就由指定的(Designated)组播路由器来担当,如果一个网段中有多个组播路由器,则通过选举找出一个指定的路由器来担当这个角色(一般看那一个的IP地址较小)。这里组播路由器一般是指配置了PIM的路由器。在没有组播路由器的情况下,交换机可以配置IGMP Snooping Querier来代替实现相同的功能。
找出在组播中的指定路由器(Designated Router), 用命令show ip pim interfaces。
SW1#show ip pim interfaces
Address Interface Mode Neighbor Hello DR DR Address PktsQed PktsDropped
Count Intvl Pri
70.0.0.1 Ethernet3 sparse 1 30 1 70.0.0.2 0 0
90.0.0.1 Vlan900 sparse 0 30 1 90.0.0.1 0 0
在这个连接里[2]可以看到IGMP的抓包。
组播三层协议PIM
PIM是组播技术中使用的路由协议,让组播报文能通过路由到达多个终端,这让组播技术真正变得有价值。注意具备路由能力的交换机,当其配置了PIM的情况下,IGMP也会被自动开启。
PIM有多个模式,其中PIM-SM模式应用最广,本文中只讲解PIM-SM。在这里提一下的是PIM-DM这个模式,PIM-DM与PIM-SM的区别是PIM-DM不需要RP(下文会说什么是RP),PIM-DM假设所有网段都加入到一个组播地址中,组播报文会被泛洪到所有路由器,不需要组播报文的终端需要发送prune消息来停止接收组播报文。另外还有一种PIM的模式为PIM-SSM,这种模式下只有一个特定的组播源,不需要使用RP。因为PIM-SM在组播源上没有限制,所以也经常被叫作any source multicast, 意思就是任意组播源的组播协议。
要去理解PIM-SM,首先要搞清楚的就是它的术语。向一个组播地址发送报文的服务器就为源端(source), 而使在该组播地址里的组员即为接收端。往源端方向的流为上游(upstream), 往接收端方向为下游(downstream)。下图给出了在PIM-SM拓扑中几个重要角色 -- FHR,RP,LHR--所处的位置,我做了一些简化,假设FHR和LHR是具备路由功能的交换机,在现实中一般有多个FHR和LHR。下面来讲解这些角色的功能。
- Mroute (Multicast Route): 组播路由表,与之对应的单播路由表就是我们平时常用的路由表。组播路由是为流量驱动的,在有流量的情况下才会生成路由项,没有流量路由表就为空。在组播路由表中没有BGP,OSPF这些用来传递路由的协议。
- FHR (First Hop Router): 如上图,配置了PIM的连接组播源的第一跳路由器。
- LHR (Last Hop Router):如上图,配置了PIM的连接接收端的第一跳的路由器。
- DR (Designated Router): 一般FHR和LHR会被配置为DR,这种情况下作为DR的FHR负责发送PIM register报文;作为DR的LHR负责发送PIM join报文。
- RP (Rendezvous Point): RP是PIM-SM的一个具有特殊角色的路由器,在FHR和LHR上配置的RP必须一致。RP是共享树(RPT)的根。
- SPT (Shortest Path Tree): 从源端到接收端的最短路径树,根据单播路由表用RPF(Reserver Path Forwarding)算出来的。
- RPT(Rendezvous Point Tree): RP树经常被称之为共享树(share tree),从RP到接收端的路径。
- (S, G): 用于标记SPT,在组播路由表中用来表示SPT去往接收端的下一跳,S表示source, G表示Group。
- (*,G): 用于标记RPT,在组播路由表中用来表示RPT去往接收端的下一跳,*表示任何地址,G表示Group。
为了防止组播路由中出现环路,在组播中应用了RPF检测这个规则。不论是从(S,G)路径或是从(*,G)路径发送的组播报文都必须通过RPF检测才能够往下发送[3]。RPF检测就是在单播路由表上查询出报文源地址对应的路径所对应的出口,即为RPF接口,如果组播报文进入到组播路由器时的入口与RPF接口不一致,该报文会被丢弃。
PIM-SM的工作流程
上面讲了术语,估计不太好理解,下面讲一下PIM-SM的工作流程,整个框架呈现出来以后就会好理解一点,其中理解这个流程的关键点是搞清报文发送的方向。
- FHR-DR向RP注册组播源。当组播源向一个组地址发送报文时,FHR会把这第一个报文封装成PIM register报文,并把报文发送给RP去注册这个组播源。
- RP给组播源完成注册。当RP收到PIM register的报文后,假设在有RPT共享树的情况下,RP会解封这个PIM register报文,并向接收端下发这个报文。同时RP会向FHR发送PIM join报文,在组播路由表中生成(S,G)路由,即去往组播源的路由,途径的路由器都会生成对应的(S,G),SPT树就建立了。(C)一旦SPT树建立,RP会向FHR发PIM register stop报文。
- 组播源通过RPT路径向接收端发报文。当第二步完成后,源端就可以向接收端发送报文,但这个时候发送的报文都要经过RP,所以可能不是发送报文的最优路径。 注意这一步的前提条件是RP的组播路由表中有(*,G),也就是RPT共享树已生成,这时Outgoing Interface List(OIL)上也会对应的接口,报文会从这些接口下发。在没有(*,G)的情况下,RP会向FHR发PIM register stop报文,并不会向下传输组播报文。
- RPT路径转到(switchover)SPT路径。当LHR接收到报文后,LHR就知道了组播源地址,LHR会向源端方向(即上游)发送PIM join报文,在组播路由表中生成(S,G),途径的路由器也会生成(S,G),建立SPT树。
- LHR-DR剪除RPT树。当LHR到FHR完成SPT树的建立,也就是说途径的路由器都有(S,G),那么LHR会发送PIM prune报文给RP,告知RP不用再发组播报文,否则会收到重复的报文。在PIM的RFC7761中[5],这一步被表示为(S,G,RPT), LHR发(S,G,RPT)报文来通知RP不要再转发发来自该组播源的报文。
注意在上文第三步中说了RP在组播路由中有(*,G)时才向下发报文。(*,G)的生成由LHR驱动,LHR在有IGMP组员的情况下会向RP发PIM join,RP和中间路由器会对应地生成(*,G)。需要说明的一点是FHR是不用发PIM join报文的,只有LHR发PIM join报文。这里我们假设LHR是其子网段中的DR,如果LHR不是DR,LHR则只负责在接到IGMP report后建立IGMP组员表,由DR发送PIM join。从PIM-SM上游到下游,如果没有源端发报文,或没有接收端发IGMP join报文,PIM-SM将不会有组播路由项也不会传输报文,所以PIM-SM被称之为流量驱动型的协议。
一个简单的实验
前文讲解了什么是PIM当中的FHR,RP,LHR,在实际拓扑中这些PIM协议中的角色通常会分布在不同的路由器上,但我们也可以在同一个路由器上部署所有这些角色,换言之,这个路由器即是FHR同时也是RP和LHR。
在这个实验中我们只需要两台设备,一台作PIM路由器,一台作打流机生成组播流量。这里的PIM会被设置成同时担当FHR,RP和LHR;打流器我们使用Arista的vEOS中自带的软件ethxmit,在我前面的博客里介绍了如何在EVE-NG环境上导入vEOS,这是链接。下面是这个实验的配置。
router pim sparse-mode
ipv4
rp address 5.5.5.5 <==== 使用loopback5作RP
interface Loopback5
ip address 5.5.5.5/32
interface Ethernet1 <==== et1 作为PIM组播源的入口, 连接到vEOS打流器上
no switchport
ip address 10.1.1.2/30
pim ipv4 sparse-mode
interface Vlan300
ip address 192.168.1.1/24
ip igmp version 2
ip igmp static-group 224.0.1.129 <==== 在vlan 300上配置igmp的静态关联,加入组地址224.0.1.129
pim ipv4 sparse-mode
在vEOS上用命令行bash进入Linux模式,用以下命令生成组播流量,用et1为接口向组播224.0.1.129发流量。
# sudo ethxmit --ip-dst=224.0.1.129 --ip-src=10.1.1.1 --udp-dport=65000 --udp-sport=65000 et1
查看PIM-SM的数据流是否建立,主要就是看(S,G)是否生成。
# sh ip mroute | beg 224.0.1.129
224.0.1.129
0.0.0.0, 0:00:14, RP 5.5.5.5, flags: W
Incoming interface: Register
Outgoing interface list:
Vlan300
10.1.1.1, 0:00:03, flags: SLN <==== 这就是(S,G),S=10.1.1.1, G=224.0.1.129
Incoming interface: Ethernet1
RPF route: [U] 10.1.1.0/30 [0/1]
Outgoing interface list:
Vlan300
排错清单
在排查组播路由时常见的问题有如下,
- 因MTU不足造成组播源到RP上的注册失败。上文的所述,当组播源开始发送报文时,FHR会封装第一个报文发送到RP,封装的报文会比原报文大,所以MTU不足会造成注册失败。
- FHR,LHR或任一组播路由器没有去往RP的路径,这里指单播(unicast)的路径。
- TTL问题。有一些组播源在发送的报文上设定TTL为1,如需经过多个中间的路由器,报文即无法到达接收端[3]。另一点是IGMP report报文的TTL也为1。
- LHR中没有IGMP组员导致报文不能下发。LHR没有IGMP组员就不会给RP发PIM join, RP就不会向其转发组播报文。造成这个的原因可能有多种,组员不具备发送IGMP report的功能,或者发送IGMP report的间隔太长。
- Switchover没有发送。上文说了switchover的过程,简单来说就是报文的转发从RPT树的路径换到使用SPT树的路径,相应地组播路由表中的(*,G)会变成(S,G)。记住即使RP在最短路径上,这个状态的切换依然要发生,组播表中最终应该显示的是(S,G)。如果不想让switchover发生,需要把SPT threshold这个参数上设为infinity。
在排错组播问题常用的命令有:
show ip igmp snooping group | 查看IGMP组地址和组员 |
show ip pim interfaces | 查看配置了PIM的接口, 查看谁是DR |
show ip pim rp | 查看RP |
show ip mroute <group ip> show ip mroute <group ip> details | 查看组播路由表 |
show ip pim neighbor | 查看PIM邻居和其对应接口 |
show ip rpf <source ip> | 查组播源地址对应的RPF接口 |
clear ip mroute * | 清空当前的组播路由表 |
用show ip mroute来查看一个组播路由器是处与RPT树状态还是SPT树状态。
以下是组播路由器处于SPT树状态的输出,10.0.0.10是组播源地址,239.10.10.10是组地址,即为(S,G):
# show ip mroute
239.10.10.10
10.0.0.10, 0:00:51, flags: SL
Incoming interface: Ethernet1
RPF route: [U] 10.0.0.0/24 [0/1]
Outgoing interface list:
Ethernet3
以下是组播路由器处于RPT树状态的输出,组播源地址为0.0.0.0,表示为任何地址对应(*,G)中的’*‘, 239.10.10.10是组地址,所以为(*,G):
#show ip mroute
239.20.20.20
0.0.0.0, 0:00:28, RP 2.2.2.2, flags: W
Incoming interface: Register
Outgoing interface list:
Ethernet4
参考文献
[1] Clusters from Scratch:https://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/1.1/html/Clusters_from_Scratch/_notes_on_multicast_address_assignment.html
[2] IGMP Packets: https://packetlife.net/captures/protocol/igmp/
[3] Multicast with TTL of 1: https://forums.juniper.net/t5/Routing/Multicast-with-TTL-of-1-how-to-route-across-subnets-PIM-not/td-p/289032
[4] Cisco IP Multicast Troubleshooting Guide: https://www.cisco.com/c/en/us/support/docs/ip/ip-multicast/16450-mcastguide0.htm
[5] Protocol Independent Multicast - Sparse Mode, RFC7761, https://tools.ietf.org/html/rfc7761