sk_buff結構分析
sk_buff是我們遇到的第二個重要的結構,在內核中經常被縮寫成skb.在linux 2.6.21它被定義成:
struct sk_buff {
//指向下一個skb
struct sk_buff *next;
//上一個skb
struct sk_buff *prev;
struct sk_buf0f_head *list;
//對應的sock。這也是個重要的結構,在傳輸層的時候我們再來分析
struct sock *sk;
//接收或者發送時間戳
struct timeval stamp;
//接收或者發送時對應的net_device
struct net_device *dev;
//接收的net_device
struct net_device *input_dev;
//數據包對應的真實net_device.關於虛擬設備可以在之後的網橋模式分析中討論
struct net_device *real_dev;
//ip層的相關信息
union {
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct ipv6hdr *ipv6h;
unsigned char *raw;
} h;
//協議層的相關信息
union {
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
unsigned char *raw;
} nh;
//鏈路層的相關信息
union {
unsigned char *raw;
} mac;
//在路由子系統中再來分析這一結構
struct dst_entry *dst;
struct sec_path *sp;
/*
* 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[40];
//各層的數據長度
unsigned int len,
data_len,
mac_len,
csum;
unsigned char local_df,
cloned,
pkt_type,
ip_summed;
__u32 priority;
unsigned short protocol,
security;
void (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
unsigned long nfmark;
__u32 nfcache;
__u32 nfctinfo;
struct nf_conntrack *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
union {
__u32 ifield;
} private;
#endif
#ifdef CONFIG_NET_SCHED
__u32 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u32 tc_verd; /* traffic control verdict */
__u32 tc_classid; /* traffic control classid */
#endif
#endif
/* These elements must be at the end, see alloc_skb() for details. */
unsigned int truesize;
//引用計數
atomic_t users;
//存儲空間的起始地址
unsigned char *head,
//網絡數據的起始起址
*data,
//存放網絡數據的結束地址
*tail,
//存儲空間的結束地址
*end;
}
對應我們上面的網卡驅動分析。接收到的數據是存放在data至tail之間的區域。
Skb通常還有常用的幾個函數,一一列舉分析如下:
struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
分配存儲空間為sixe的skb,內存分配級別為gfp_mask.注意這裡的存儲空間的含義,即為skb->data至skb->tail的區域
struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
克隆出的skb指向同一個結構,同時會增加skb的引用計數
struct sk_buff *skb_copy(const struct sk_buff *skb, int priority)
復制一個全新的skb
void kfree_skb(struct sk_buff *skb)
當skb的引用計數為1的時候,釋放此skb
unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
使skb的存儲空間擴大len.即使tail指針下移
unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
push,即推出一段數據,使data指針下層。
void skb_reserve(struct sk_buff *skb, unsigned int len)
該操作使data指針跟tail指針同時下移,即擴大存儲區域之前的空間
int skb_headroom(const struct sk_buff *skb)
返回data之前可用的空間數量
int skb_tailroom(const struct sk_buff *skb)
返回緩存區中可用的空間大小