如何从 skb 中提取整个数据包,包括以太网 header、ip 和 tcp 以及设备 driver 的轮询方法中的有效负载

How to extract entire packet from skb including ethernet header, ip, and tcp plus pay load in poll method of device driver

在 r8169 driver 来自 realtek 的

    rx_buf = page_address(tp->Rx_databuff[entry]);
    dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
    prefetch(rx_buf);
    skb_copy_to_linear_data(skb, rx_buf, pkt_size);<----//Do I get packet at this????
    skb->tail += pkt_size;
    skb->len = pkt_size;
    dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
    //csum...
    skb->protocol = eth_type_trans(skb, dev);
    napi_gro_receive(&tp->napi, skb);

这是从 driver 的轮询调用的 rtl_rx 函数内部。我想知道在上面的代码中,我怎样才能在之后的哪一行从 skb 中提取整个数据包。

我假设在这一行

             skb_copy_to_linear_data(skb, rx_buf, pkt_size);

我应该有一个数据包,但想知道我可以创建一个 kmalloc 对象的正确方法

         void   *packet=   kmalloc(....sizeof(struct ethhdr)+sizeof(struct iphdr)+sizeof(tcphdr))

并从 void *packet

中读取以太网 ip 和 tcp headers

如何实现

或者我应该简单地做 skb_netword_header、skb_tcp_header 等...在 skb 在上面的行中填充后从 skb 中提取 headers 和有效载荷,

或者我可以简单地转换为

              rx_buf = page_address(tp->Rx_databuff[entry]);
              struct ether_header ethhdr_of_packet=(struct eher_header *) rx_buf;

应该有用吗?

突出显示的行(带有skb_copy_to_linear_data()的行)确实从 driver-internal Rx环中的缓冲区复制了整个数据包数据rx_buf) skb的data buffer.

static inline void skb_copy_to_linear_data(struct sk_buff *skb,
                       const void *from,
                       const unsigned int len)
{
    memcpy(skb->data, from, len);
}

rx_buf 指针转换为以太网 header 应该也可以。但是,像这样访问数据包 header 的目的在您的问题中相当模糊。您是要打印(“转储”)数据包还是打算将数据包数据复制到完全不同的缓冲区以供其他地方使用?