什么是处理在Linux中的sk_buff包的所有有效载荷的正确方法(What's the c

2019-08-03 06:08发布

目前,我试图调试在最上层以太网上运行的ATM封装层。 基本上,ATM信元被存储在顺序以太网报头之后。 不过我怀疑司机幼稚的方法来sk_buffs被打破了。

司机盲目假设是skb->数据可以通过迭代但看着为virtio_net.c内核代码:page_to_skb我看到以下行为:

memcpy(hdr, p, hdr_len);
len -= hdr_len;
p += offset;
copy = len;

if (copy > skb_tailroom(skb))
        copy = skb_tailroom(skb);

memcpy(skb_put(skb, copy), p, copy);

再往上:

while (len) {
        set_skb_frag(skb, page, offset, &len);
    page = (struct page *)page->private;
    offset = 0;
}

这似乎表明缓冲液是零散仅所述第一部分从是skb->数据直接访问。

我应该是用得到的基础数据。 理想我想memcpy'ing块到重构缓冲器我维持之前偷看在任意的偏移到以太网数据包的几个字节。 我应该是使用要做到这一点?

Answer 1:

插座缓冲器的执行是由一个线性数据缓冲器和一个或多个页缓冲器。

分页数据的在插座缓冲器中的存在是由表示skb->data_len构件是非零的。

bool skb_is_nonlinear(const struct sk_buff *skb)中所定义/include/linux/skbuff.h用于测试此。

非分页数据中的是skb->数据量可被计算为是skb-> LEN - 是skb-> DATA_LEN。 unsigned int skb_headlen(const struct sk_buff *skb)中所定义/include/linux/skbuff.h用于测试此。

skb->data指针仅指向非分页的数据,这是你所描述的司机可能依靠。

void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)中被定义/include/linux/skbuff.h 。 它采用socket缓冲区,字节偏移和字节长度你想和如果数据是在页面缓冲器中的一个仅使用本地数据缓存。

它返回从一个指针到无论是在直线数据缓冲器中的数据skb->data ,如果您的偏移量和长度是不正确的或指针到本地数据缓存器提供,或NULL。

对于非协议报头大数据块或者你要使用

int skb_copy_bits(const struct sk_buff *skb, int offset,void *to, int len);

从给定的插座缓冲区拷贝,字节偏移和字节长度给定的内核缓冲区。

要么

int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, struct iovec *to, int size);

到从给定的插座缓冲区拷贝,字节偏移和字节长度在用户空间中给定iovec的结构。

使用的例子可以被视为在netfilter的代码和其他以太网驱动程序。

了解更多信息

  • 套接字缓冲区介绍由David S.米勒
  • 套接字缓冲区数据布局由David S.米勒
  • 套接字缓冲区教程罗伯托Innocente,OSAdewale


文章来源: What's the correct way to process all the payload of a sk_buff packet in Linux