void br_multicast_init(struct net_bridge *br)
{
br->hash_elasticity = 4;
br->hash_max = 512;
br->multicast_router = 1;
br->multicast_last_member_count = 2;
br->multicast_startup_query_count = 2;
br->multicast_last_member_interval = HZ;
br->multicast_query_response_interval = 10 * HZ;
br->multicast_startup_query_interval = 125 * HZ / 4;
br->multicast_query_interval = 125 * HZ;
br->multicast_querier_interval = 255 * HZ;
br->multicast_membership_interval = 260 * HZ;
spin_lock_init(&br->multicast_lock);
setup_timer(&br->multicast_router_timer,
br_multicast_local_router_expired, 0);
setup_timer(&br->multicast_querier_timer,
br_multicast_local_router_expired, 0);
setup_timer(&br->multicast_query_timer, br_multicast_query_expired,//创立多播查询定时器
(unsigned long)br);
}
static void br_multicast_query_expired(unsigned long data)
{
struct net_bridge *br = (void *)data;
spin_lock(&br->multicast_lock);
if (br->multicast_startup_queries_sent <
br->multicast_startup_query_count)
br->multicast_startup_queries_sent++;
br_multicast_send_query(br, NULL, br->multicast_startup_queries_sent);//发送多播查询报文
spin_unlock(&br->multicast_lock);
}
static void br_multicast_send_query(struct net_bridge *br,
struct net_bridge_port *port, u32 sent)
{
unsigned long time;
struct br_ip br_group;
if (!netif_running(br->dev) || br->multicast_disabled ||
timer_pending(&br->multicast_querier_timer))//如果设备关闭,或者多播禁止或者timer真挂起则返回
return;
memset(&br_group.u, 0, sizeof(br_group.u));
br_group.proto = htons(ETH_P_IP);
__br_multicast_send_query(br, port, &br_group);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
br_group.proto = htons(ETH_P_IPV6);
__br_multicast_send_query(br, port, &br_group);
#endif
time = jiffies;
time += sent < br->multicast_startup_query_count ?
br->multicast_startup_query_interval :
br->multicast_query_interval;
mod_timer(port ? &port->multicast_query_timer :
&br->multicast_query_timer, time);
}
static void __br_multicast_send_query(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *ip)
{
struct sk_buff *skb;
skb = br_multicast_alloc_query(br, ip);
if (!skb)
return;
if (port) {
__skb_push(skb, sizeof(struct ethhdr));
skb->dev = port->dev;
NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit);
} else
netif_rx(skb);
}
static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
struct br_ip *addr)
{
switch (addr->proto) {
case htons(ETH_P_IP):
return br_ip4_multicast_alloc_query(br, addr->u.ip4);//ipv4 IGMP查询报文
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case htons(ETH_P_IPV6):
return br_ip6_multicast_alloc_query(br, &addr->u.ip6);//ipv6 MLD查询报文
#endif
}
return NULL;
}
流程比较简单,要关闭这个功能可以通过echo "0"> /sys/class/net/br0/bridge/multicast_snooping
命令关闭
阅读(3372) | 评论(0) | 转发(1) |