sk_buff
Rev.6を表示中。最新版はこちら。
1. 概要
sk_buffはパケットデータを格納するバッファ。各パケットは、それぞれsk_buffに格納されLinuxのネットワークレイヤで扱われる。
2. 基本的なデータ構造
sk_buffの構造を図2.1に示す。まずバッファの管理構造体としてstruct sk_buffがある。そして、実際にパケットデータを格納する領域が別にあり、sk_buffのhead,data,tail,endでデータの位置を管理する。また、データ格納エリアの後ろにはstruct skb_shared_infoが付いており、ここにはcloneで複製されたsk_buff間で共有するデータが格納される。
図2.1 sk_buffの構造(空のケース)
sk_buffにデータが格納されていると図2.2のようになる。sk_buffの各フィールドの意味は表2.1参照。
フィールド |
説明 |
---|---|
head |
データ格納用バッファの先頭を示す |
data |
バッファに格納されているデータの先頭 |
tail |
データの終端 |
end |
データ格納用バッファの終端 このアドレスは、skb_shared_infoの開始アドレスでもある。 |
3. その他のデータ構造
3.1 frags配列
skb_shared_info内のfrags配列がある。この配列を使用することで、パケットデータを非連続な領域に分断して保持することができる。fragsを使用した状態のsk_buffを図3.1に示す。
ただし、このようにfragsパケットデータを分断して持つ形式はネットワークカード(とそのドライバ)がScatter/gather I/O(*1)に対応していないと使えない。Scatter/gather I/Oに対応しているとデバイスにNETIF_F_SGフラグが設定されているので、送信デバイスにこのフラグが立っている場合のみ、このような形式を使う。
frags配列の要素はskb_frag_structとなっており(ポインタではなくそのもの)、これは、分断されたデータがどこにあるかを管理する。 skb_frag_structはデータが置かれている物理ページのstruct pageを指している。そして、page_offset,sizeが物理ページ内のデータ格納位置を示している。
(*1) 物理的に非連続になっている複数のバッファのデータから1つのパケットを構築(Gather)して送信したり、逆に受信パケットを分断された複数のバッファに格納(Scatter)できる ネットワークカード。この機能により、ジャンボフレームを扱う場合に、パケットサイズ分の物理的に連続なページを確保する必要がなくなる。
Scatter/Gather I/Oに対応しているドライバでは、送信時にfrags[]をチェックして、分断されたバッファのデータをまとめて送信するようにH/Wを制御する。
3.2 frag_list
skb_shared_info内のfrag_listにはIPフラグメントされたパケットのsk_buffがチェーンされる(図3.2)。図3.2ではデータ(A)がフラグメントされた先頭パケットのデータ、データ(C)が2番目のパケットのデータとなる。
frag_listの構築はIPv4では、ip_append_data()で行っている。
図3.2 frag_list