在內核分析網路分組時,底層協議的數據將傳輸到跟高的層。而發送數據的時候順序是相反的。每一層都是通過加(首部+凈荷)傳向跟底層,直至最終發送。 這些操作決定了網路的的性能。 就如下圖所示 linux因此設計了一個結構體 如下代碼 套接字換從區在各個層交換數據,就不用複製數據了。 從以上欄位和註釋可以看 ...
在內核分析網路分組時,底層協議的數據將傳輸到跟高的層。而發送數據的時候順序是相反的。每一層都是通過加(首部+凈荷)傳向跟底層,直至最終發送。
這些操作決定了網路的的性能。
就如下圖所示
linux因此設計了一個結構體
如下代碼
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
* @prev: Previous buffer in list
* @list: List we are on
* @sk: Socket we are owned by
* @stamp: Time we arrived
* @dev: Device we arrived on/are leaving by
* @real_dev: The real device we are using
* @h: Transport layer header
* @nh: Network layer header
* @mac: Link layer header
* @dst: FIXME: Describe this field
* @cb: Control buffer. Free for use by every layer. Put private vars here
* @len: Length of actual data
* @data_len: Data length
* @csum: Checksum
* @__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
* @priority: Packet queueing priority
* @users: User count - see {datagram,tcp}.c
* @protocol: Packet protocol from driver
* @security: Security level of packet
* @truesize: Buffer size
* @head: Head of buffer
* @data: Data head pointer
* @tail: Tail pointer
* @end: End pointer
* @destructor: Destruct function
* @nfmark: Can be used for communication between hooks
* @nfcache: Cache info
* @nfct: Associated connection, if any
* @nf_debug: Netfilter debugging
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
* @private: Data which is private to the HIPPI implementation
* @tc_index: Traffic control index
*/
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
struct sk_buff_head *list;
struct sock *sk;
struct timeval stamp;
struct net_device *dev;
struct net_device *real_dev;
union {
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
unsigned char *raw;
} h;
union {
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
unsigned char *raw;
} nh;
union {
struct ethhdr *ethernet;
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[48];
unsigned int len,
data_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;
struct nf_ct_info *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 */
#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;
};
套接字換從區在各個層交換數據,就不用複製數據了。
從以上欄位和註釋可以看到,head和end欄位指向了buf的起始位置和終止位置。然後使用header指針指像各種協議填值。然後data就是實際數據。tail記錄了數據的偏移值。
相信大家都能看懂註釋,具體的解釋就不用介紹了.,
在一個新的分組產生的時候,TCP層首先在用戶空間中分配記憶體來容納該分組數據。分配的空間大於數據的實際需要長度。因此較低的層可以增加首部,在往下一層走的時候,只需要對欄位添值即可。
對接收分組的一樣,分組數據複製到內核分配的一個記憶體區中。併在分析的過程中一直處於記憶體區中。
skbuf還提供了一個雙向鏈表對這個數據分組進行了管理。
如下代碼
struct sk_buff_head {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
__u32 qlen;
spinlock_t lock;
};
__u32 qlen; 緩衝區中等待隊列的長度。就是分組的成員數量。
lock 表示了cpu的互斥。
今天分析到此,跟多源碼閱讀去看skbuff.h的文件。