2012-11-27 21 views
5

現在、Ethernet上で実行される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'ingチャンクを再構成バッファに入れる前に、イーサネットパケットに任意のオフセットでいくつかのバイトを覗き見したいと思います。これを行うにはどうすればよいですか?

答えて

7

ソケットバッファの実装は、リニアデータバッファと1つ以上のページバッファで構成されています。

ソケットバッファ内のページデータの存在は、skb->data_lenメンバが非ゼロで示されます。

bool skb_is_nonlinear(const struct sk_buff *skb)は、/include/linux/skbuff.hで定義されています。

skb-> dataのページングされていないデータの量は、skb-> len-skb-> data_lenと計算できます。 で定義された 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で定義されています。ソケットバッファ、バイトオフセット、バイト長を とし、データがページバッファの1つにある場合にのみ使用されるローカルデータバッファを取ります。

リニアデータバッファ内のデータへのポインタをskb->dataから、またはローカルデータバッファへのポインタ から、オフセットと長さが正しくない場合はNULLを返します。あなたがいずれかの特定のカーネルバッファに与えられたソケットバッファ、バイトオフセットとバイト長からコピーする

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

を使用するプロトコルヘッダよりも大きなデータの部分については

。ユーザ空間でIOVEC所与の構造に与えられたソケットバッファ、バイトオフセットとバイト長からコピーするため

又は

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

使用例は、netfilterコードおよび他のイーサネットドライバで確認できます。詳細について

関連する問題