IGMP在本地网络上的主机和路由器之间传达组成员信息,路由器定时向所有主机组多播IGMP查询。主机多播IGMP报告报文
以响应查询。
从体系结构的观点来看,IGMP是位于IP上面的运输层协议。它有一个协议号(2),它的报文是由IP数据报承载的。与ICMP
一样,进程通常不直接访问IGMP,但进程可以通过IGMP插口发送和接受IGMP报文。这个特性使得能够把多播选路守护程序
作为用户级进程实现。
下图是Net/3中IGMP协议的整体结构:
到达的IGMP查询使igmp_input为每个in_multi结构初始化一个递减定时器,该定时器由igmp_fastimo更新,当每个定时器
超时时,igmp_fasttimo调用igmp_sendreport。
当我们创建一个新的in_multi结构时,ip_setmoptions调用igmp_joingroup。igmp_joingroup调用igmp_sendreport来发布
新的组成员信息,使组的定时器能够在短时间内安排第二次通告。igmp_sendreport完成对igmp报文的格式化,并把它传给
ip_output。
igmp报文只有8个字节长,结构如下:
igmp_type包含一个4bit的版本码和一个4bit的类型码,如下图所示:
igmp报文构造如下:
Net/3只使用版本1的报文,多播路由器发送1类报文向本地网络上所有主机请求成员关系报告。对1类IGMP报文的响应是
主机的一个2类报文,报告它们的多播成员信息。3类报文在路由器之间传输多播选路信息,主机不处理3类报文。
IGMP的protosw结构如下:
三种时间触发IGMP处理:
一个本地接口加入一个新的多播组。
某个IGMP定时器超时。
收到一个IGMP查询。
还有两种事件也触发本地IGMP处理,但结果不发送任何报文:
收到一个IGMP报告。
某个本地接口离开一个多播组。
当一个新的in_multi结构被创建时,in_addmulti调用igmp_joingroup。然后加入同一多播组的请求只增加in_multi结构的
引用次数,不调用igmp_joingroup。
函数的大概处理如下:
如果新的组时所有主机组,或成员关系请求时环回接口的,则不需要定时器,函数返回。因为每个多播主机都是所有组播组
的成员,不需要进行报告。没必要向环回接口发送组成员报告,因为本地主机是在回路网络上的唯一系统,它已经知道它的
成员状态了。
在其他情况下,新组的报告被立即发送(通过igmp_sendreport函数),并根据组的情况为组定时器选择一个随机值。
igmp_fastimo检查这个变量,避免不必要的处理。当新组的定时器超时时,就发布第2次成员关系报告。
igmp_fasttimo函数循环找到各个in_multi结构,对每个结构:
如果定时器为0,什么都不做。
如果定时器不是0,则将其递减。如果到达0,则发送一个IGMP组成员关系报告。
igmp_sendreport函数为一个多播组构造和发送IGMP报告报文。
通过创建一个mbuf,然后设定相应的值,最后构造一个ip_moptions结构,并将它与报文一起传给ip_output。
进程级的多播路由器必须监听成员关系报告,当系统被配置成多播路由器时,总是接收IGMP数据报。通过传输层程序把
报文传给IGMP的igmp_input和pr_input函数。
多播路由器接收所有的IGMP报文,但是多播主机只接收那些到达接收是目的多播组成员的IGMP报文(也即,那些接收
它们的接口是组成员的查询和成员管理报告)。
标准协议分用机制把接受的报文传给igmp_input。igmp_input的大概处理如下:
1.验证IGMP报文,包IGMP检验和等方式。
2.根据igmp_type内的代码处理报文,igmp_type包含一个版本码和一个类型码,根据这两个码分别进行处理。
3.把有效的IGMP报文传给rip_input,在rip_input里被提交给所有监听IGMP报文的进程。
RFC1075推荐多播路由器每120秒至少发布一次IGMP成员关系查询。把查询发给224.0.0.1组(所有主机组)。
对于该igmp_type的处理如下:
接收查询报文并不会立即引起IGMP成员报告。相反,igmp_input为与接收查询的接口相关的各个组定时器设置一个随机的值,
当某组的定时器超时,则igmp_fasttimo发送一个成员关系报告,与此同时,其他所有查询的主机也进行同一动作。一旦某个
主机上的某个特定组的随机定时器超时,就像该组多播一个报告。这个报告将取消其他主机上的定时器,保证只有一个报告在
网络上多播。路由器与其他组成员一样,接收该报告。这个情况的一个例外就是所有主机组,这个组不设定定时器,也不发送
报告。
对于该igmp_type的处理如下:
发送到环回接口上的报告被丢弃。
如果源地址的网络或者子网部分为0(如果主机正在启动,这是被允许的),则把源地址设成子网地址,那么进程级的多播路由
守护进程能够知道它是从哪个子网过来的。
当in_multi结构中的引用计数器跳到0时,in_delmulti调用igmp_leavegroup。该函数不采取任何动作。