2、非線性區(qū)域
在1、中,可以看到每張sk_buff的圖: 在end指針緊挨著一個非線性區(qū)域 ;
在struct sk_buff中沒有指向skb_shared_info結(jié)構(gòu)的指針,利用end指針,,可以用skb_shinfo宏來訪問:
#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB)))
其中skb_end_pointer函數(shù)如下,返回end指針
static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
{
return skb- >end;
}
具體地,struct skb_shared_info如下:
struct skb_shared_info {
__u8 __unused;
__u8 meta_len;
//數(shù)組frags包含的元素個數(shù)
__u8 nr_frags;
__u8 tx_flags;
unsigned short gso_size;
/* Warning: this field is not always filled in (UFO)! */
unsigned short gso_segs;
struct sk_buff *frag_list;
struct skb_shared_hwtstamps hwtstamps;
unsigned int gso_type;
u32 tskey;
/*
* Warning : all fields before dataref are cleared in __alloc_skb()
*/
//結(jié)構(gòu)skb_shared_info 的引用計數(shù)器
atomic_t dataref;
/* Intermediate layers must ensure that destructor_arg
* remains valid until skb destructor */
void * destructor_arg;
/* must be last field, see pskb_expand_head() */
skb_frag_t frags[MAX_SKB_FRAGS];
};
其中skb_frag_t如下:
typedef struct skb_frag_struct skb_frag_t;
struct skb_frag_struct {
struct {
//指向文件系統(tǒng)緩存頁的指針
struct page *p;
} page;
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
//數(shù)據(jù)起始地址在文件系統(tǒng)緩存頁中的偏移
__u32 page_offset;
//數(shù)據(jù)在文件系統(tǒng)緩存頁中使用的長度
__u32 size;
#else
__u16 page_offset;
__u16 size;
#endif
};
nr_frags,frags,frag_list與IP分片存儲有關(guān)。
frag_list的用法:
- 用于在接收分組后鏈接多個分片,組成一個完整的IP數(shù)據(jù)報
- 在UDP數(shù)據(jù)報輸出中,將待分片的SKB鏈接到第一個SKB中,然后在輸出過程中能夠快速的分片
- 用于存放FRAGLIST類型的聚合分散I/O數(shù)據(jù)包
判斷是否存在非線性緩沖區(qū):
- 先說明struct sk_buff中關(guān)于長度的兩個字段
- len字段:無分片的報文,數(shù)據(jù)報文的大小
- data_len字段:存在分散報文,data_len表示分片的部分大小
如下所示,沒有開啟分片的報文len = x,data_len = 0:
如下所示在Linux內(nèi)核中,使用skb_is_nonlinear函數(shù)判斷是否存在分片,即通過判斷data_len的大小是否為0:
static inline bool skb_is_nonlinear(const struct sk_buff *skb)
{
return skb- >data_len;
}
- 在沒有開啟分片的報文中,數(shù)據(jù)包長度在struct sk_buff中為len字段的大小,即data到tail的長度,nf_frags為0,frag_list為NULL。
普通聚合分散I/O的報文:
采用聚合分散I/O的報文, frag_list為 NULL,nf_frags不等于0 ,說明這不是一個普通的分片,而是聚合分散I/O的報文。
如下所示:
nr_frags為2,而frag_list為NULL,說明這不是普通的分片,而是聚合分散I/O分片,數(shù)量為2,這兩個分片指向同一物理分頁,各自在分頁中的偏移和長度分別是0/S1和S1/S2。
FRAGLIST類型的分散聚合I/O的報文:
采用FRAGLIST類型的分散聚合I/O報文, ** frag_list不為NULL,nf_frags等于0 ,** 數(shù)據(jù)長度len為x+S1,data_len為S1,
以上從struct sk_buff的四大指針以及操作、非線性區(qū)域?qū)μ捉幼志彺?socket buffer)進(jìn)行分析,更多sk_buff的分析、實操等將在以后的文章中梳理。
-
嵌入式
+關(guān)注
關(guān)注
5086文章
19141瀏覽量
305955 -
Linux
+關(guān)注
關(guān)注
87文章
11314瀏覽量
209778 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3031瀏覽量
74119
發(fā)布評論請先 登錄
相關(guān)推薦
評論