先简单介绍IGMPv3,一个网络协议总的说来无非多是"一问,一答",当然也有主动的去"报告
",IGMPv3也不例外.
1.看过IGMPv2以及v1的人会奇怪为什么要v3,v3能带来些什么?
1>.IGMPv2/v1是典型的接受任意源多播(Any-Source Multicast)[ASM],即它只是关注多播
组,而不关注是谁发送的,这样会有一些问题,比如说,假如一个局域网存在一个多播视频服
务器,其它Host在上面点播视频;假如出现一个伪装者,也向这个多播组发送干扰数据,但Ho
st无法辨别,这样可能引起视频的接受断断续续,影响服务的提供,显然这不是很理想;而IG
MPv3的提出,就是为了解决这个问题,它提出了源特定多播(Source-Specific Multicast)[
SSM],不仅关注多播组,也关注发送多播组的源.
2>.包的类型
IGMPv3主要有两种包:
Type Number (hex) Message Name
----------------- ------------
0x11 Membership Query
0x22 Version 3 Membership Report
基于兼容的原因,还有IGMPv2/v1的几种包:
0x12 Version 1 Membership Report [RFC-1112]
0x16 Version 2 Membership Report [RFC-2236]
0x17 Version 2 Leave Group [RFC-2236]
关于协议部分更详尽的细节,参考RFC3376(IGMPv3),RFC2236(IGMPv2),RFC1112(IGMPv1)
2.Linux Kernel的IGMPv3以及多播路由的实现
仔细看了这部分的代码,主要的文件比较少,分别为:
igmp.c 内核实现的对IGMP的实现,可以兼容v2/c.
ipmr.c 看文件名自然就可以猜测是多播路由的实现.
其中,值得参考的文档是Sprint Labs的两份文档,一份是实现架构,一份是测试计划,不过从
我读Code来看,这两份文档只具备参考意义,因为kernel的实现并不是按照其实现架构文档
来实现的,看igmp.c/ipmr.c的文件注释可以知道多播部分的实现是其它人来实现的,并不遵
循该设计文档(也许该实验室是准备实现的,但最终由于某些其它原因由其它人来实现,并且
没有采取其设计文档),不过设计思想值得参考,实际的实现比那份设计文档要简洁一些.
下面看看一些具体的数据结构,由于部分成员我也没看懂做什么用处,如果你知道,请告诉
我:)
net_device{}
--------
| |<------------------
|~~~~~~~~| in_device{} |
|--------| --------- |
| ip_ptr |--->| dev |----
|--------| |---------|<------------------
| | |~~~~~~~~~| ip_mc_list{} |
|~~~~~~~~| |---------| --------- |
-------- | mc_list |--->|interface|----
|---------| |---------|
|~~~~~~~~~| |multiaddr|
--------- |---------|
|~~~~~~~~~|
---------
通过上图可以看到3个结构之间的部分关系,我简单说说这三个结构:
net_device:针对每个网络设备的一个抽象,比如你用ifconfig看到的eth0,就对应了一个
该结构实例.
in_device:针对IPv4的网络部分的描诉,因为Linux支持不仅仅是TCP/IP协议族,还用ATM等
等,其底层设备是不同的,而对与网络设备的通用部分,用net_device{}描述,而针对不同协
议私有部分,则使用不同结构,支持IPv4的设备,就使用该结构.
ip_mc_list:描述的自然是IP设备的多播相关信息,我只花出了一个multiaddr,举例说来,
我们说"eth0加入了多播组224.0.0.1",multiaddr就记录了该设备加入的一个多播组:224.
0.0.1
因此,结合上图,可以基本知道一个网络设备,如何记录它加入的多播组.
下面来看igmp的处理流程:
--------
|ip_rcv()|[IP层的总入口]
--------
|
V
------------------
|ip_local_deliver()|[本地分发,即目的地为本地]
------------------
|
V
----------
|igmp_rcv()|[分发到IGMP的处理入口]
----------
|
V
------------------------
| [处理查询] |[处理报告]
V V
------------------ -------------------
|igmp_heard_query()| |igmp_heard_report()|
------------------ -------------------
[开始计时器]| ++++++++++++++ |[停止计时器]
----> +ip_mc_list{}+<----
++++++++++++++
|
V
------------------
|igmp_send_report()|
------------------
在上面的文档里简要介绍了kernel对IGMP包的处理,其实下面才是重点,kernel怎么处理多
播包呢?即多播包怎么路由呢?
这又涉及到UNIX常用的一个哲学"数据路径要分离于控制路径(最常见的说法是策略与机制
,上面的说法是我自己理解后表述的,因为我老把这两者弄反,呵呵:))",这实际上是两个分
离的问题:
1).多播包在内核中怎么样被处理?
2).该使用什么方法在应用程序中向内核添加路由?
说道这里,我再次强调一下,注意区分在网路中的常见角色"Host"和"Router",时刻记得它
们本质的区别是重要的:),它们最重要的区别在于是否能够转发包.
好了,我们来依次解决上面的两个问题:
我们不去考虑MAC层对多播的处理,只是理解就可以了,记得网络设备在MAC层可以实现一个
不完全的过滤就可以了,相关知识,参考<TCP/IP详解>卷一,下面我们从IP层开始考虑(认为
网卡支持多播,不过现在不支持多播的网 卡很少了,呵呵)
