Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1911518
  • 博文数量: 376
  • 博客积分: 2147
  • 博客等级: 大尉
  • 技术积分: 3642
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 10:47
文章分类

全部博文(376)

文章存档

2019年(3)

2017年(28)

2016年(15)

2015年(17)

2014年(182)

2013年(16)

2012年(115)

我的朋友

分类: 嵌入式

2013-08-05 10:51:17

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
命令关闭

阅读(3346) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~