mrouted程序计算多播路由表,以及在网络之前转发多播数据报的内核函数。
下图是mrouted的几个版本及它们和BSD版本的对应关系。mrouted版本包含用户级守护程序和内核级多播程序。
本文讨论包含在Net/3中多播软件2.0版,但被认为已经过时了。
因为还没有广泛安装商用多播路由器,所以常用多播隧道连接标准IP单播互联网上的两个多播路由器,构造多播网络。Net/3
支持多播隧道,并采用宽松源站记录路由选项构造多播隧道。一种更好的隧道技术是把IP多播数据报封装在一个单播数据报里,
但Net/3不支持。
1.多播输出处理
在ip_moptions结构中ip_output被传给一个明确的结构,或者ip_output在路由表中查找目的地组,并使用在路由路口中返回
的接口。
如果在选择了输出接口后,ip_output回送该数据报,就把它放在所选输出接口等待输入处理,当ipintr处理它时,把它当作是
要转发的数据报,如下图所示:
上图中,虚线箭头代表原始输出的数据报,ip_mloopback创建的备份由带箭头的细线表示,并作为输入被传给运输层协议。
当ip_mforward决定通过系统上的另一个接口转发该数据报时,就产生了第三个备份。最粗的箭头代表第三个备份,在多播
隧道上发送。
如果数据报不是回送的,则ip_output把它直接传给ip_mforward,ip_mforward复制并处理该数据报,就像它是从ip_output
选定的接口上收到的一样。如下图所示:
2.mrouted守护程序
用户级进程mrouted守护进程允许和管理多播路由选择。mrouted实现IGMP协议的路由部分,并于其他多播路由器通信,
实现网络间的多播路由选择。路由算法在mrouted上实现,但内核维护多播路由选择表,并转发数据报。
本文主要讨论支持mrouted的内核数据结构和函数,不讨论mrouted本身。我们讨论用于数据报选择路由的截断逆向路径
广播TRPB(truncated reverse path broadcast)算法以及用于在多播路由器之间传递信息的距离向量多播选路协议
DVMRP。
mrouted守护程序通过在一个IGMP插口上设置选项与内核通信,这些选项如下图所示:
插口选项被setsockopt系统调用传给rip_ctloutput函数,rip_ctloutput调用ip_mrouter_cmd函数,该函数通过一个switch
分别调用上表中第三列的函数。
3.虚拟接口
当作为多播路由器运行时,Net/3接收到达的多播数据报,复制它们,并在一个或多个接口上转发备份。通过这种方式,数据报
被转发给互联网上的其他多播路由器。
输出的接口可以是一个物理接口,也可以使一个多播隧道。多播隧道的两端都与一个多播路由器上的某个物理接口相关。多播
隧道使两个多播路由器,即使被不能转发多播数据报的路由器分隔,也能够交换多播数据报。下图是一个多播隧道连接的两个
多播路由器。
网络A上的源主机HS正在向组G多播数据报,组G的唯一成员在网络B上,并通过一个多播隧道连接到网络A。路由器A接收
多播,查询它的多播路由选择表,并通过多播隧道转发该数据报。下图显示了IP LSRR选项如何实现多播隧道。
第一行,HS在网络A上发送的多播数据报,路由器A全部接收,因为多播路由器接收本地连接网络上的所有数据报。
第二行,是在隧道上离开A时的数据报,LSRR的选项第一个地址是隧道的源地址,第二个是目的地多播地址。数据报
的目的地址是Te。
第三行,是被路由器B上的ip_dooptions处理之后的数据报。
第四行,是调用ip_mforward之后的数据报。在哪里,LSRR选项被识别,并从数据报首部中移走。得到的数据就像原始
多播数据报,由ip_mforward处理它,把它作为多播数据报在网络B上转发,并被HG收到。
使用LSRR构造多播隧道已经过时。新的程序通过在IP多播数据报的首部前面加上另一个IP首部来构造隧道,新IP首部协议
设置为4,表示分组内容是另一个IP分组。
3.1.虚拟接口表
无论物理接口还是隧道接口,内核都为其在虚拟接口表中维护一个入口,其中包含了只有多播使用的信息。每个虚拟接口
都用一个vif结构表示,如下图所示。全局变量viftable是一个这种结构的数组。数组的下标保存在无符号短整数vifi_t变量中。
v_flags定义的唯一标志位是VIFF_TUNNEL,被置位时,该接口是一个到远程多播路由器的隧道。没有置位时,接口是在本地
系统上的一个物理地址。
v_threahold是一个多播ttl阈值。
v_lcl_addr是与这个虚拟接口相关的本地接口的IP地址。
v_rmt_addr是一个IP多播隧道远端的单播IP地址。
v_lcl_addr和v_rmt_addr为非零,但是不会两者都为非零。
v_ifp,对于物理接口,该变量非空,并指向本地接口的ifnet结构,对隧道,v_ifp是空的。
v_lcl_grps指向一个IP多播地址数组,这个数组记录了在连到的接口上的成员组列表。对隧道而言,v_lcl——grps总是空的。
数组的大小保存在v_lcl_grps_max中,被使用的入口数保存在v_lcl_grps_n中。数组随着成员关系表的增大而增大。
v_cached_group和v_cached_result实现一个入口高速缓存,其中记录的都是最近一次查找得到的组。
下图时一个viftable结构:
setsockopt通过DVMRP_ADD_VIF和DVMRP_DEL_VIF对viftable进行操作。
4.IGMP
mrouted实现了IGMP协议的路由部分,mrouted必须为每个物理接口记录哪个多播组有成员连接到网络上,mrouted每120
秒多播一个IGMP_HOST_MEMBERSHIP_QUERY数据报,并把结果汇编到与每个网络相关的成员关系数组中。
mrouted根据收集到的信息构造多播路由选择表,多播组表也提供信息,用来抑制向没有目的组成员的多播互联网区进行多播。
置位物理接口维护这样的成员关系数组。对其他多播路由器来说,隧道是点到点接口,所以无需组成员关系信息。
mrouted用DVMRP_ADD_LGRP和DVMRP_DEL_LGRP命令维护v_lcl_grps指向的IP多播组数组。
当收到一个IGMP_HOST_MEMBERSHIP_REPORT时,调用下图所示的函数。
5.多播选路
上图中,方框代表路由器,椭圆代表连接到路由器的多播网络,最简单的路由选择方法是,从互联网拓扑中选出一个子网,
形成一个生成树。如果每个路由器都沿着生成树转发多播,则各路由器最终会收到数据报。下图显示了示例网络的一个生成
树。其中网络A的主机S是多播数据报的源。
这个生成树是根据从各网络回到网络A上的源站的最短逆向路径构成的。如果用同一生成树转发来自网络C的数据报,为了
在网络B上收到,数据报经过的转发路径将大于需要的长度。RFC1075提出的算法为每个潜在的源站计算了一个单独的生
成树,以避免这种情况。因为构造生成树是为了给源站的数据报提供最短逆向路径,而每个网络都接收所有多播数据报,
所以这个过程称为逆向路径广播(reverse path broadcast),即RPB。
RPB没有任何多播组成员信息,使许多数据报被不必要地转发到没有目的组成员的网络上,如果,除了计算生成树外,该
路由选择算法还能记录哪些网络是叶子,注意到每个网络上的组成员关系,那么连到叶子网络的路由器就可以避免把数据
转发到没有目的组成员的网络上去。这称为截断逆向路径广播(TRPB)。
下图显示了TRPB算法的应用,多播来自网络C上的源站,并在网络B上有一个目的组成员。
路由器C接收多播,并通过连接到路由器ABE的接口将其转发, 尽管把它发给AE都是浪费的。因为网络ADE是叶子网络,并
且没有目的组成员,所以它们没有阴影。在路由器处截断生成树,也不把数据报转发到这些网络上去。路由器B把数据报转发
到网络B上,因为B上有一个目的成员。
对多播路由选择算法的最后一个改进叫做逆向路径多播(reverse path multicasting,RPM)。RPM的目的是修剪各生成
树,避免在没有目的组成员的分支上发送数据报。在上图中,RPM可以避免路由器C向A和E发送数据报,因为在这两个分支
上没有目的多播组的成员。如下图所示:
为了生成树对应的路由表,多播路由器和邻近的多播路由器通信,发现多播互联网拓扑和多播组成员的位置,在Net/3中,用
DVMRP进行这种通信。DVMRP作为IGMP数据报传送,发给224.0.0.4组,该组是给DVMRP通信保留的。
5.1.多播选路表
现在我们描述Net/3中实现的多播路由选择。内核的多播路由选择表示作为一个有64个入口的散列表实现的(MRTHASHIZ)。
该表保存在全局数组mrttable中,每个入口指向一个mrt结构的链表。如下图所示:
mrt_origin和mrt_originmask标识表中的一个入口,mrt_parent是虚拟接口的下标,该虚拟接口上预期有来自起点的所有
多播数据报。
mrt_children是一个位图,标识外出的接口。mrt_leaves也是一个位图,里面标识多播路由选择树中也是叶子的外出接口,当
多条路由散列到同一个数组入口时,最后一个成员mrt_next实现该入口的一个链表。
下图是多播选路表的整体结构,各mrt结构都放在一个散列链上。
mrouted守护程序通过DVMRP_ADD_MRT和DVMRP_DEL_MRT命令在内核的多播选路表中增加和删除mrt表项。
6.多播转发:ip_mforward函数
内核实现了整个多播转发,mrouted运行时,ipintr把到达数据报传给ip_mforward。ip_output可以把本地主机产生的多播
数据报传给ip_mforward,由ip_mforward为这些数据报选路到除ip_output选定的接口以外的其他接口上去。
与单播不同,每当多播数据报被转发到某个接口上时,就为该数据报产生一个备份。下图显示了一个到达某个物理接口的
多播数据报。
数据报到达的接口是目的多播组的一个成员,所以数据报被传给传输层协议等待输入处理。该数据报也被传给了ip_mforward,
在这里它被复制和转发到一个物理接口和一个隧道,这两个必须都不和接收接口相同。
下图显示了一个到达某隧道的多播数据报。
图中,用带虚线的箭头表示与该隧道的本地端有关的物理接口,数据报就在这一接口上到达,数据报被传给ip_mforward,
因为分组到达一个隧道,所以ip_mforword返回一个非零值,这导致ipintr不再把该分组传给运输层协议。
ip_mforward从分组中取出隧道选项,查询多播选路表,并且,还把分组转发到另一个隧道以及到达的物理接口上去,用
带细线的箭头表示。这是可行的,因为多播选路表是根据虚拟接口,而不是物理接口。
我们假定物理接口是目的多播组的成员,所以ip_output把该数据报传给ip_mloopback,ip_mloopback把它送到队列中
等待ipintr的处理(粗线箭头),然后,分组又被传给ip_mforward,并被这个函数丢弃。ip_mforword返回0,所以ipintr
接收该数据报,并进行输入处理。
多播转发函数的大概处理如下:
1.判断到达本地物理接口还是隧道,通过检查IP头部的LSRR选项。
2.如果隧道选项正确,在调整IP头部,删除隧道选项。
3.如果ip_ttl是0或者1,那么数据报已经到了生存期的最后,不再转发它。如果目的组小于或者等于几个224.0.0.x组,则不允许
数据报离开本地网络,也不转发它。
4.如果无法根据数据报中的源地址找到一条路由,则函数返回,没有路由,多播路由器无法确定把数据报转发到哪个接口上去。
5.如果数据报到达某个物理接口,但系统本来预想它应该到达某个隧道或者其他物理接口,则函数返回。.如果数据报到达某个
隧道,但系统本来预想它应该到达某个物理接口或者其他隧道,则函数也返回。
6.把数据从指定接口发送出去。对于每个虚拟接口,如果以下条件满足,则在该接口上发送数据报。
- 数据报的TTL大于接口的多播阈值
- 接口是该路由的子接口
- 接口没有和其他叶子网络相连
对于隧道接口,发送调用tunnel_send函数,对于物理接口,发送调用phyint_send函数。
tunnel_send函数直接调用ip_output函数发送,phyint_send函数需要重新构建ip隧道选项,调用ip_output函数发送。
7.清理:ip_mrouter_done函数
当mrouted结束时,它发布DVMRP_DONE命令,ip_mrouter_done函数处理这个命令。
这个函数对每个物理多播接口,释放本地组表,发布SIOCDELMULTI命令,阻止接收多播数据报。清零整个viftable数组,
并把numvifs设置为0。
释放多播选路表mrttable中的所有活动入口。