admin管理员组

文章数量:1642441

一般情况下,网桥在泛洪时将数据包发送每一个子接口,每次发送前需要clone一份skb数据包。在遍历到最后一个子接口的时候,由于skb不再需要进行其它的处理了,可以不clone,直接使用原skb,处理完成后安全释放。

在br_flood函数中,通过prev变量保存前一个遍历的子接口,实现以上的功能。


static void br_flood(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb0, ...)
{
    struct net_bridge_port *p, *prev;

    list_for_each_entry_rcu(p, &br->port_list, list)
        prev = maybe_deliver(prev, p, skb, __packet_hook);

    if (!prev) goto out;
    __packet_hook(prev, skb);
}


数据包处理回调__packet_hook为函数__br_forward或者__br_deliver,前者为转发的报文处理函数,后者为本地报文发出时的处理函数。

在遍历网桥的port_list的时候,调用maybe_deliver处理,由其代码可知,在第一次调用时prev为空,此函数直接返回没做处理。所以当遍历结束时,prev其实指向着最后一个子接口。此后直接调用__packet_hook在其上发送数据包。


static int deliver_clone(const struct net_bridge_port *prev, struct sk_buff *skb, ...)
{
    skb = skb_clone(skb, GFP_ATOMIC);
    __packet_hook(prev, skb);
}
static struct net_bridge_port *maybe_deliver(struct net_bridge_port *prev, struct net_bridge_port *p, struct sk_buff *skb, ...)
{
    if (!prev) goto out;
    err = deliver_clone(prev, skb, __packet_hook);
    return p;
}


内核版本

Linux-4.0


本文标签: 网桥泛洪时skb