前面分析了igmp snooping的实现,最近由于工作比较忙,还有就是个人比较懒的缘故一直没有分析igmpproxy的实现,今天开始分析igmpproxy的实现。

       我们首先还是从数据结构开始分析之路。

 

1. ip_mc_list

struct ip_mc_list {

       structin_device      *interface;//三层接口

       __be32                  multiaddr;//组播地址

       structip_sf_list      *sources;//组播路由表对应的源地址过滤相关的地址链表

       structip_sf_list      *tomb;

       unsignedint           sfmode;//过滤模式

       unsignedlong        sfcount[2];

       structip_mc_list     *next;//指向下一个组播路由entry

       structtimer_list      timer;//用于发送igmp report报文的定时器

       int                 users;//引用计数

       atomic_t         refcnt;

       spinlock_t              lock;

       char               tm_running;

       char               reporter;

       char               unsolicit_count;//用于发送igmp report使用,目前是允许发送3次igmp report报文

       char               loaded;

       unsignedchar         gsquery;  /* check source marks? */

       unsignedchar         crcount;

};

 

该数据结构用于标示一个组播路由,当应用层通过set_sockopt的IP_ADD_MEMBERSHIP命令,将一个组播路由添加到一个网络设备对应的三层数据结构的mc_list中(in_dev->mc_list)

 

 

 

2.  mfc_cache

struct mfc_cache{

struct mfc_cache *next;                /*指向 下一个组播路由缓存     */

#ifdefCONFIG_NET_NS

struct net *mfc_net;

#endif

__be32 mfc_mcastgrp;                 /* 组播组ip */

__be32 mfc_origin;                     /* 组播源ip*/

vifi_t mfc_parent;                /*该组播路由对应的vif,通过该值能够找到该组播路由缓存对应的网络设备*/

int mfc_flags;                      /*Flags on line             */

 

union {

        struct {

               unsigned long expires;//组播路由缓存失效超时时间

               struct sk_buff_head unresolved;    /*未创建组播路由缓存的缓冲队列*/

        } unres;

        struct {

               unsigned long last_assert;

               int minvif;

               int maxvif;

               unsigned long bytes;

               unsigned long pkt;

               unsigned long wrong_if;

               unsigned char ttls[MAXVIFS];     /* TTL thresholds          */

        } res;

} mfc_un;

};

 

组播路由缓存,组播路由缓存保存在net->ipv4.mfc_cache_array的数组链表中,该数组中的每一个成员都可以看成一个链表。而数组成员的确定是根据源ip地址与组播组地址经过hash计算得出。

        当我们首先根据一个下行接口接收的igmp report报文创建了一个组播路由时,此时还没有创建组播路由缓存,当组播流数据到达多播路由器的上行接口时,会最终由函数ip_mr_input进行处理。在这个函数里如果没有查找到组播路由缓存,则会调用ipmr_cache_unresolved 向应用层igmp proxy的相关的应该程序发送igmp 数据包,让应用层igmpproxy相关的应用向内核中添加路由缓存,并将数据包缓存在mfc_cache. mfc_un.unres.unresolved中。

        对于查找到组播路由缓存的组播流数据,则从相应的网络接口中把数据发送出去(即多播路由的下行接口)

 

 

3.虚拟网络设备

structvif_device {

struct net_device    *dev;                    /*对应的真实网络设备 */

unsigned long bytes_in,bytes_out;

unsigned long pkt_in,pkt_out;             /* Statistics                  */

unsigned long rate_limit;             /* Traffic shaping (NI) */

unsigned char  threshold;              /* TTL threshold           */

unsigned short flags;                    /* Control flags            */

__be32           local,remote;          /* Addresses(remote for tunnels)*/

int          link;               /* Physical interface index     */

};

 

虚拟网络设备主要是对应多播路由的上行、下行设备,我们需要为上行、下行设备都创建一个虚拟网络设备。

        关于虚拟网络设备的作用,有专家曾经说过主要是为了兼容ip隧道的。

 

 

一、igmp proxy实现分析

前面我们说过igmpproxy的工作原理:

对于IGMPPROXY,主要是拦截lan側pc发送的igmp报文,其在wan側作为客户端响应上行路由的查询操作,而在lan側则作为服务端定期发送查询报文。

当lan側加入的组播组在IGMPPROXY设备上没有相应的组播路由时,才会给上层发送组播加入报文,当lan側加入的组播组在IGMPPROXY设备上已经存在时,则无需再将加入报文转发出去。这样不仅能够达到有效抑制二层组播泛滥的问题,且能更有效的获取和控制用户信息,降低网络负载。

 

理解了igmpproxy的工作原理后,再基于上面一中所说的数据结构,对于一个多播路由器来说,肯定存在2个以及2个以上的网络设备接口:

一个用于上行口:

a) 主要是向上层发送igmpreport/igmp leave 或者响应上层的igmpquery

b) 接收上层多播路由下发的组播流数据,并根据组播路由缓存决定是否将组播流数据发送给下行端口

c) 向下行接口发送igmpquery数据包,维护上层组播路由表与组播路由缓存表

该接口一般是一个wan接口(static、dhcp、pppoe模式)

一个用于下行口:

用于接收lan侧设备发送的igmpreport、igmpleave报文,并交由上层应用层的程序进行后续处理,并实现转发组播流的功能。一般是br0桥接口

 

实现igmpproxy的步骤大致如下:

1、 创建2个虚拟接口,一个作为upstream 接口,一个作为downstream接口

2、 上行接口设备与下行接口设备都需要维护一个组播路由表,其中上行接口设备维护的组播路由主要是为了将wan侧接收的组播流流向下行接口。而下行接口设备维护的组播路由表主要是维护lan侧设备的加入请求,当接收到一个lan侧igmpleave报文后,需要检查是否是该组播组的最后一个成员,若是则需要发送igmpquery报文,进行查询操作

3、 写一个创建组播路由或者删除组播路由的接口函数供应用层调用,以便实现组播路由的添加或删除

4、 当创建一个组播路由时,并不代表需要创建组播路由缓存,只有接收到组播流后,内核才会发送igmp报文给应用层igmpproxy应用程序,让应用程序创建组播路由缓存。

5、 组播路由与组播路由缓存的存在需要有一个垃圾回收机制。

基本上也就上面5大方面。

下一节会接着分析igmp类型数据包的接收和组播流数据包的接收处理。

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐