http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E5%8D%81%E4%BA%8C%E7%AB%A0%20%E7%BD%91%E7%BB%9C/12.2.3.htm
12.4.3 sk_buff数据结构的核心内容
sk_buff 数据结构中包含了一些指针和长度信息,从而可让协议层以标准的函数或方法对应用程序的数据进行处理,其定义于include/linux/skbuff.h中:
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next; /* Next buffer in list*/
struct sk_buff *prev; /* Previous buffer in list*/
struct sk_buff_head * list; /* List we areon */
structsock *sk; /* Socket we are owned by */
struct timeval stamp; /*Time we arrived */
struct net_device *dev; /* Device we arrived on/are leaving by */
/* Transport layer header */
union
{
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct spxhdr *spxh;
unsigned char *raw;
} h;
/* Network layer header */
union
{
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
struct ipxhdr *ipxh;
unsigned char *raw;
} nh;
/*Link layer header */
union
{
struct ethhdr *ethernet;
unsigned char *raw;
} mac;
struct dst_entry*dst;
/*
* This is the control buffer. It is free to use for every
* layer. Please put your private variablesthere. If you
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoeverhas the skb queued ATM.
*/
char cb[48];
unsigned int len; /* Length of actual data*/
unsignedint data_len;
unsigned int csum; /* Checksum */
unsigned char __unused, /* Deadfield, may be reused */
cloned, /* head may be cloned (check refcnt to be sure). */
pkt_type, /* Packet class */
ip_summed; /*Driver fed us an IP checksum */
__u32 priority; /* Packet queueing priority */
atomic_t users; /*User count - see datagram.c,tcp.c */
unsigned short protocol; /* Packet protocol fromdriver. */
unsigned short security; /* Security level of packet*/
unsigned int truesize; /* Buffer size */
unsigned char *head; /*Head of buffer */
unsigned char *data; /* Data head pointer
unsignedchar *tail; /* Tail pointer
unsignedchar *end; /* End pointer */
void (*destructor)(struct sk_buff *); /* Destruct function */
…
}
该结构的示意图如图12.13所示:
图12.13 sk_buff 结构
每个 sk_buff 均包含一个数据块、四个数据指针以及两个长度字段。利用四个数据指针,各协议层可操纵和管理套接字缓冲区的数据,这四个指针的用途是:
head:指向内存中数据区的起始地址。sk_buff和相关数据块在分配之后,该指针的值是固定的。
data: 指向协议数据的当前起始地址。该指针的值随当前拥有 sk_buff 的协议层的变化而变化。
tail:指向协议数据的当前结尾地址。和 data指针一样,该指针的值也随当前拥有 sk_buff 的协议层的变化而变化。
end:指向内存中数据区的结尾。和 head指针一样,sk_buff 被分配之后,该指针的值也固定不变。
sk_buff 有两个非常重要长度字段,len和 truesize,分别描述当前协议数据包的长度和数据缓冲区的实际长度。