Linux内核定义了这个API:
static inline void * __must_check
__skb_header_pointer(const struct sk_buff *skb, int offset,
int len, void *data, int hlen, void *buffer)
{
if (hlen - offset >= len)
return data + offset;
if (!skb ||
skb_copy_bits(skb, offset, buffer, len) < 0)
return NULL;
return buffer;
}
static inline void * __must_check
skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
{
return __skb_header_pointer(skb, offset, len, skb->data,
skb_headlen(skb), buffer);
}
在内核的某些部分,此API用于检索big-endian中的数据包字段,因为它是一个网络skb
。所以我理解这个API何时应用于数据包标头,我们知道这些数据包在big-endian中有一些字段,例如struct iphdr
其中16/32位字段显式声明为__be16/__be32
。
所以根据https://en.wikipedia.org/wiki/Endianness
Internet协议套件协议中的字段,如IPv4,IPv6,TCP和UDP,以big-endian顺序传输。
但是,始终保证{em> 存储在skb
中的数据包的16位或32位部分将按网络字节顺序排列吗?
换句话说,接下来的电话:
u32 *ptr, data;
ptr = skb_header_pointer(skb, offset, 4, &data);
可以更改为:
__be32 *ptr, data;
ptr = skb_header_pointer(skb, offset, 4, &data);
这是正确的假设吗?
更新我认为不是。只有协议(IP / TCP / UDP / ICMP / etc。)标头需要采用big-endian字节顺序,有效负载字节顺序由发送机器确定。