如何在内核驱动程序中获取 sk_buff_head?

How to get sk_buff_head in kernel driver?

我最近在写一个网络驱动,在transmit函数中想修改socket buffer queue。因此我需要获得 sk_buff_head 的锁,但是从套接​​字缓冲区到头部的 link 几年前就被删除了。

如何从 ndo_start_xmit(struct sk_buff *skb, net_device *dev) 访问 sk_buff_head

我正在使用当前的 linux 内核 4.15.3。

背景

我修改了一个虚拟网络设备的现有驱动程序以实现依赖于帧顺序的分片,因此第二个分片必须在第一个分片之后直接发送。它适用于第 2 层帧。

因此我在 start_xmit 函数中进行了连接,简化后如下所示:

static spinlock_t xmit_lock;
start_xmit(struct sk_buff *skb, struct net_device *dev)
{

    [...]

    if(skb->len > TRESHHOLD) {
        second_skb = do_fragmentation(skb);
    }

    [...]

    spin_lock_bh(&xmit_lock);

    if(second_skb) {
         second_skb->next = skb->next;
         second_skb->prev = skb;
         skb->next = second_skb;
    }

    ret = dev_queue_xmit(skb);

    spin_lock_bh(&xmit_lock);
}

所以我想达到两个 skbs 都是按照这个顺序发送的,不应该有一个帧在其间发送通过这个驱动程序。这在使用带有 UDP 的 ping 泛洪模式 oder iperf 时有效,但有时它会使用 TCP 连接搞乱 iperf。然后,也有一些顺序乱了的情况。

为了解决这个问题,我想我需要 skb 的 "real" 队列锁,所以我需要 sk_buff_head

要正确执行此操作,您需要在私有数据结构中设置本地锁:

例如

struct my_protocol {
    spinlock_t lock;
}

在 dev->open(通常在分配例程中完成)使用 alloc_netdev() 进行设置,然后您可以使用 netdev_priv 访问该结构并持有您的锁。