2、非線性區(qū)域
在1、中,可以看到每張sk_buff的圖: 在end指針緊挨著一個(gè)非線性區(qū)域 ;
在struct sk_buff中沒(méi)有指向skb_shared_info結(jié)構(gòu)的指針,利用end指針,,可以用skb_shinfo宏來(lái)訪問(wèn):
#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包含的元素個(gè)數(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 的引用計(jì)數(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)緩存頁(yè)的指針
struct page *p;
} page;
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
//數(shù)據(jù)起始地址在文件系統(tǒng)緩存頁(yè)中的偏移
__u32 page_offset;
//數(shù)據(jù)在文件系統(tǒng)緩存頁(yè)中使用的長(zhǎng)度
__u32 size;
#else
__u16 page_offset;
__u16 size;
#endif
};
nr_frags,frags,frag_list與IP分片存儲(chǔ)有關(guān)。
frag_list的用法:
- 用于在接收分組后鏈接多個(gè)分片,組成一個(gè)完整的IP數(shù)據(jù)報(bào)
- 在UDP數(shù)據(jù)報(bào)輸出中,將待分片的SKB鏈接到第一個(gè)SKB中,然后在輸出過(guò)程中能夠快速的分片
- 用于存放FRAGLIST類型的聚合分散I/O數(shù)據(jù)包
判斷是否存在非線性緩沖區(qū):
- 先說(shuō)明struct sk_buff中關(guān)于長(zhǎng)度的兩個(gè)字段
- len字段:無(wú)分片的報(bào)文,數(shù)據(jù)報(bào)文的大小
- data_len字段:存在分散報(bào)文,data_len表示分片的部分大小
如下所示,沒(méi)有開(kāi)啟分片的報(bào)文len = x,data_len = 0:
如下所示在Linux內(nèi)核中,使用skb_is_nonlinear函數(shù)判斷是否存在分片,即通過(guò)判斷data_len的大小是否為0:
static inline bool skb_is_nonlinear(const struct sk_buff *skb)
{
return skb- >data_len;
}
- 在沒(méi)有開(kāi)啟分片的報(bào)文中,數(shù)據(jù)包長(zhǎng)度在struct sk_buff中為len字段的大小,即data到tail的長(zhǎng)度,nf_frags為0,frag_list為NULL。
普通聚合分散I/O的報(bào)文:
采用聚合分散I/O的報(bào)文, frag_list為 NULL,nf_frags不等于0 ,說(shuō)明這不是一個(gè)普通的分片,而是聚合分散I/O的報(bào)文。
如下所示:
nr_frags為2,而frag_list為NULL,說(shuō)明這不是普通的分片,而是聚合分散I/O分片,數(shù)量為2,這兩個(gè)分片指向同一物理分頁(yè),各自在分頁(yè)中的偏移和長(zhǎng)度分別是0/S1和S1/S2。
FRAGLIST類型的分散聚合I/O的報(bào)文:
采用FRAGLIST類型的分散聚合I/O報(bào)文, ** frag_list不為NULL,nf_frags等于0 ,** 數(shù)據(jù)長(zhǎng)度len為x+S1,data_len為S1,
以上從struct sk_buff的四大指針以及操作、非線性區(qū)域?qū)μ捉幼志彺?socket buffer)進(jìn)行分析,更多sk_buff的分析、實(shí)操等將在以后的文章中梳理。
-
嵌入式
+關(guān)注
關(guān)注
5082文章
19104瀏覽量
304823 -
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209332 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3019瀏覽量
74005
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論