操作tailroom中用戶數據塊區域:skb_put用于修改指向數據區末尾的指針tail:
void *skb_put(struct sk_buff *skb, unsigned int len)
{
void *tmp = skb_tail_pointer(skb);
SKB_LINEAR_ASSERT(skb);
skb- >tail += len;
skb- >len += len;
if (unlikely(skb- >tail > skb- >end))
skb_over_panic(skb, len, __builtin_return_address(0));
return tmp;
}
可以看到 tail指針的移動是擴大數據區域 ,即數據區向下擴大len字節,并更新數據區長度len。
增加headroom區域的協議頭: skb_push函數用于移動data指針,增加頭部協議, 與skb_reserve()類似,也并沒有真正向數據緩存區中添加數據,而只是移動數據緩存區的頭指針data。數據由其他函數復制到數據緩存區中。 函數如下:
void *skb_push(struct sk_buff *skb, unsigned int len)
{
skb- >data -= len;
skb- >len += len;
if (unlikely(skb- >data< skb- >head))
skb_under_panic(skb, len, __builtin_return_address(0));
return skb- >data;
}
如下兩張圖分別是由傳輸層、網絡層,數據包向下傳遞時data指針移動,進行頭部協議的封裝。
- TCP層添加TCP首部。
- SKB傳遞到IP層,IP層為數據包添加IP首部。
- SKB傳遞到鏈路層,鏈路層為數據包添加鏈路層首部。
可以看到在數據包封裝的過程中,每一層移動data指針進行數據報頭的封裝。
數據報文解封裝,解除協議頭: skb_pull通過將data指針向下移動,進行數據報文的解封裝,函數如下所示:
static inline void *__skb_pull(struct sk_buff *skb, unsigned int len)
{
skb- >len -= len;
BUG_ON(skb- >len < skb- >data_len);
return skb- >data += len;
}
如下圖所示,在收包流程上,向上層協議,如下網絡層向傳輸層傳送的時候,調用skb_pull進行數據包的解封裝。
以上就是struct sk_buff的四大指針的相關操作,通過分析可得:
- head指向緩沖區的首地址,作為上邊界
- end指向緩沖區的尾地址,作為下邊界
- data指針在數據包頭部封裝和解封裝的過程中移動,指向各層的協議頭,skb_push函數將data的指向,向低地址移動(向上),完成協議頭空間的占據,skb_pull函數將data的指向,向高地址移動(向下),完成協議頭的解封裝。
- tail指針在增加應用層用戶緩沖數據時移動,skb_put函數將該指針向高地址移動(向上),完成用戶數據空間的占據。
-
嵌入式
+關注
關注
5082文章
19104瀏覽量
304823 -
Linux
+關注
關注
87文章
11292瀏覽量
209332 -
內存
+關注
關注
8文章
3019瀏覽量
74005 -
指針
+關注
關注
1文章
480瀏覽量
70551
發布評論請先 登錄
相關推薦
評論