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 are
on */
struct
sock *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 variables
there. If you
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever
has the skb queued ATM.
*/
char cb[48];
unsigned int len;
/* Length of actual data*/
unsigned
int data_len;
unsigned int csum;
/* Checksum */
unsigned char __unused, /* Dead
field, 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 from
driver. */
unsigned short security; /* Security level of packet
*/
unsigned int truesize;
/* Buffer size */
unsigned char
*head; /*
Head of buffer */
unsigned char
*data;
/* Data head pointer
unsigned
char *tail;
/* Tail pointer
unsigned
char *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,分别描述当前协议数据包的长度和数据缓冲区的实际长度。