深度探索Linux内核之离开一个多播组(最简单的情况)

    应用程序通过命令字IP_DROP_MEMBERSHIP使一个socket离开一个多播组,IP_DROP_MEMBERSHIP是一个IP层的命令字,其调用使用的参数是结构体struct ip_mreq。该结构体的两个成员分别用于指定所要离开的多播组的组IP地址,和所要离开组的那个本地接口的IP地址。
    ip_setsockopt实现了该命令字,它通过调用ip_mc_leave_group使socket离开一个多播组。
    表示INET域socket的结构体struct inet_sock的成员mc_list是该socket所加入的所有多播组的一个链表,ip_mc_leave_group从该链表中去匹配所要离开的组(匹配条件是组地址相同,本地网络接口相同),找到一个结构体struct ip_mc_socklist节点。
    首先要从该节点中删去源列表,同时把该节点从socket中删除,因为我们现在所关注的IP_DROP_MEMBERSHIP所要离开的组是通过IP_ADD_MEMBERSHIP加入的,没有源过滤机制,只要把节点从socket中删除即可。
    然后,还需要从网络接口struct in_device中删掉这个组,以使网络硬件设备以后可以过滤掉发往这个组的数据报。首先从struct in_device的成员mc_list链表中去匹配一个struct ip_mc_list结构体节点(匹配条件是组地址相同即可)。
    如果节点的成员loaded不为0,表示硬件过滤机制正接收该组的数据报。则调用ip_mc_filter_del从网络设备接口的结构体struct net_device的成员mc_list链表中删去相应的节点struct dev_mc_list,并通过调用网络设备接口的成员函数set_multicast_list来更新设备的过滤机制。
    如果所要离开的组不是IGMP_ALL_HOSTS(224.0.0.1),则首先停止节点本身的定时器(用于IGMPv1和IGMPv2的主动报告),然后把要删除的节点从struct in_device的mc_list链表移到mc_tomb链表上,表示这是将要删除的一个组,在稍后发送状态改变报告时有用。
    最后启用定时器struct in_device->mr_ifc_timer(接口状态改变定时器),发送主动成员报告。测试环境中要离开的多播组中是224.0.1.1,发出的IGMPv3报告如下:
    数据                含义
    22                  第3版成员关系报告
    00                  8bit保留,必须为0
    f9 fc               校验和
    00 00             16bit保留,必须为0
    00 01             组记录的数量,为1
    下面为一条组记录:
    03                  组记录类型为CHANGE_TO_INCLUDE_MODE,改变到INCLUDE模式
    00                  辅助数据长度
    00 00             源地址的数量
    e0 00 01 01    组地址224.0.1.1
    即:组224.0.1.1的过滤模式从原来的EXCLUDE(过滤的源为空)变到现在的INCLUDE(包含的源为空),也就是离开了多播组224.0.1.1。

你可能感兴趣的:(深度探索Linux内核之离开一个多播组(最简单的情况))