2012-11-27 19 views
5

我正在嘗試調試在以太網上運行的ATM封裝層。基本上ATM信元按照順序存儲在以太網報頭之後。不過,我懷疑司機對sk_buffs的天真做法已經破裂。在Linux中處理sk_buff數據包的所有有效負載的正確方法是什麼

司機盲目假設是skb->數據可以通過但看着爲virtio_net.c內核代碼迭代:page_to_skb我看到以下行爲:進一步

memcpy(hdr, p, hdr_len); 
len -= hdr_len; 
p += offset; 
copy = len; 

if (copy > skb_tailroom(skb)) 
     copy = skb_tailroom(skb); 

memcpy(skb_put(skb, copy), p, copy); 

然後在:

while (len) { 
     set_skb_frag(skb, page, offset, &len); 
    page = (struct page *)page->private; 
    offset = 0; 
} 

這看起來似乎表明緩衝區是碎片化的,只有第一部分可以從skb-> data直接訪問。

我應該用什麼來獲取底層數據。理想情況下,我希望在將memcpy分塊成爲我維護的重組緩衝區之前,將任意偏移量的幾個字節掃描到以太網數據包中。我應該用什麼來做到這一點?

回答

7

套接字緩衝區的實現由一個線性數據緩衝區和一個或多個頁面緩衝區組成。

分頁數據的在插座緩衝液中的存在是由skb->data_len部件是非零指示。

/include/linux/skbuff.h定義

bool skb_is_nonlinear(const struct sk_buff *skb)用於測試此。

非分頁數據中的是skb-量>數據可被計算爲是skb-> LEN - 是skb-> DATA_LEN。使用/include/linux/skbuff.h中定義的 unsigned int skb_headlen(const struct sk_buff *skb)來測試這個。

skb->data指針僅指向非分頁的數據,這是你所描述的司機可能依靠。

void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)/include/linux/skbuff.h定義。它需要套接字緩衝區,字節偏移量和字節長度,以及本地數據緩衝區,該緩衝區僅在數據位於頁面緩衝區之一時使用。

它返回一個指向任一中相應的線性數據緩衝器從skb->data數據或指針到本地數據緩衝器供給 或NULL如果您的偏移量和長度是不正確的。

對於除協議頭部較大的數據片或者你想使用

int skb_copy_bits(const struct sk_buff *skb, int offset,void *to, int len);

從給定套接字緩衝區,字節偏移和字節長度給定的內核緩衝區複製。

int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, struct iovec *to, int size);

到從給定的插座緩衝區拷貝,字節偏移和字節長度在用戶空間中給定iovec的結構。用法

例子可以被視爲在netfilter的代碼和其他以太網驅動程序。

如需進一步信息

相關問題