Linux IGMP PROXY 学习笔记 之 一 igmp proxy相关的数据结构及igmp proxy的大致实现要点
前面分析了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类型数据包的接收和组播流数据包的接收处理。
更多推荐
所有评论(0)