【问题标题】:How bonding driver takes RX packets from enslave interfaces绑定驱动程序如何从从属接口获取 RX 数据包
【发布时间】:2013-02-27 15:16:38
【问题描述】:

我有一个关于如何绑定驱动程序从被奴役接口获取 RX 数据包的问题。我发现绑定使用dev_add_pack() 为 LACPDU 和 ARP 数据包设置处理程序,但我没有找到其他处理程序(用于其他数据包类型)。

你能帮我解决这个问题吗?

【问题讨论】:

  • +1,我希望能帮到你。
  • 好的,谢谢,看来我找到答案了,我想我会在这里添加它,但稍后会

标签: c linux-kernel network-programming linux-device-driver


【解决方案1】:

绑定驱动程序注册自己的 Rx 处理程序,当从接口被绑定到绑定主机时,在 bond_enslave() 中您可以看到:

res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
                                 new_slave);

所以在bond_handle_frame()中,它会劫持slave接口接收到的数据包,让bond master代替接收数据包:

static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
{
        struct sk_buff *skb = *pskb;
        struct slave *slave;
        struct bonding *bond;
        int (*recv_probe)(const struct sk_buff *, struct bonding *,
                          struct slave *);
        int ret = RX_HANDLER_ANOTHER;

        skb = skb_share_check(skb, GFP_ATOMIC);
        if (unlikely(!skb))
                return RX_HANDLER_CONSUMED;

        *pskb = skb;

        slave = bond_slave_get_rcu(skb->dev);
        bond = slave->bond;

        if (bond->params.arp_interval)
                slave->dev->last_rx = jiffies;

        recv_probe = ACCESS_ONCE(bond->recv_probe);
        if (recv_probe) {
                ret = recv_probe(skb, bond, slave);
                if (ret == RX_HANDLER_CONSUMED) {
                        consume_skb(skb);
                        return ret;
                }
        }

        if (bond_should_deliver_exact_match(skb, slave, bond)) {
                return RX_HANDLER_EXACT;
        }

        skb->dev = bond->dev;

        if (bond->params.mode == BOND_MODE_ALB &&
            bond->dev->priv_flags & IFF_BRIDGE_PORT &&
            skb->pkt_type == PACKET_HOST) {

                if (unlikely(skb_cow_head(skb,
                                          skb->data - skb_mac_header(skb)))) {
                        kfree_skb(skb);
                        return RX_HANDLER_CONSUMED;
                }
                memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
        }

        return ret;
}

【讨论】:

  • 谢谢,看来我检查的绑定版本太旧了,从 kernel.org 更新后,我找到了你上面写的代码
【解决方案2】:

我检查了绑定代码,发现当驱动程序在这些模式下工作时,驱动程序不会检查没有某些类型(LACPDU、ARP)的传入 RX 数据包。驱动程序使用 dev_add_pack() 函数为此数据包设置处理程序。

在实践中设置全局挂钩可以使用 nf_register_hook(),它提供了设置自己的网络过滤程序来拦截数据包的接口。 似乎 nf_register_hook() 比 dev_add_pack() 更强大,但我认为在工作 nf_register_hook() 时需要更加小心,因为它可能会在 hook 中出现错误条件的情况下丢弃大量数据包。

【讨论】:

    猜你喜欢
    • 2014-06-05
    • 2014-04-14
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 2016-03-27
    相关资源
    最近更新 更多