MBUF(9) | FreeBSD Kernel Developer's Manual | MBUF(9) |
名称
mbuf — カーネル IPC サブシステムにおけるメモリ管理書式
#include < sys/param.h>#include < sys/systm.h>
#include < sys/mbuf.h>
mbuf 割り付けマクロ
MGET( struct mbuf *mbuf, int how, short type);MGETHDR( struct mbuf *mbuf, int how, short type);
MCLGET( struct mbuf *mbuf, int how);
MEXTADD( struct mbuf *mbuf, caddr_t buf, u_int size, void (*free)(void *opt_arg1, void *opt_arg2), void *opt_arg1, void *opt_arg2, short flags, int type);
MEXTFREE( struct mbuf *mbuf);
MFREE( struct mbuf *mbuf, struct mbuf *successor);
mbuf ユーティリティマクロ
mtod( struct mbuf *mbuf, type);M_ALIGN( struct mbuf *mbuf, u_int len);
MH_ALIGN( struct mbuf *mbuf, u_int len);
int
M_LEADINGSPACE( struct mbuf *mbuf);
int
M_TRAILINGSPACE( struct mbuf *mbuf);
M_MOVE_PKTHDR( struct mbuf *to, struct mbuf *from);
M_PREPEND( struct mbuf *mbuf, int len, int how);
MCHTYPE( struct mbuf *mbuf, u_int type);
int
M_WRITABLE( struct mbuf *mbuf);
mbuf 割り付け関数
struct mbuf *m_get( int how, int type);
struct mbuf *
m_getm( struct mbuf *orig, int len, int how, int type);
struct mbuf *
m_getcl( int how, short type, int flags);
struct mbuf *
m_getclr( int how, int type);
struct mbuf *
m_gethdr( int how, int type);
struct mbuf *
m_free( struct mbuf *mbuf);
void
m_freem( struct mbuf *mbuf);
mbuf ユーティリティ関数
voidm_adj( struct mbuf *mbuf, int len);
void
m_align( struct mbuf *mbuf, int len);
int
m_append( struct mbuf *mbuf, int len, c_caddr_t cp);
struct mbuf *
m_prepend( struct mbuf *mbuf, int len, int how);
struct mbuf *
m_copyup( struct mbuf *mbuf, int len, int dstoff);
struct mbuf *
m_pullup( struct mbuf *mbuf, int len);
struct mbuf *
m_pulldown( struct mbuf *mbuf, int offset, int len, int *offsetp);
struct mbuf *
m_copym( struct mbuf *mbuf, int offset, int len, int how);
struct mbuf *
m_copypacket( struct mbuf *mbuf, int how);
struct mbuf *
m_dup( struct mbuf *mbuf, int how);
void
m_copydata( const struct mbuf *mbuf, int offset, int len, caddr_t buf);
void
m_copyback( struct mbuf *mbuf, int offset, int len, caddr_t buf);
struct mbuf *
m_devget( char *buf, int len, int offset, struct ifnet *ifp, void (*copy)(char *from, caddr_t to, u_int len));
void
m_cat( struct mbuf *m, struct mbuf *n);
u_int
m_fixhdr( struct mbuf *mbuf);
void
m_dup_pkthdr( struct mbuf *to, struct mbuf *from);
void
m_move_pkthdr( struct mbuf *to, struct mbuf *from);
u_int
m_length( struct mbuf *mbuf, struct mbuf **last);
struct mbuf *
m_split( struct mbuf *mbuf, int len, int how);
int
m_apply( struct mbuf *mbuf, int off, int len, int (*f)(void *arg, void *data, u_int len), void *arg);
struct mbuf *
m_getptr( struct mbuf *mbuf, int loc, int *off);
struct mbuf *
m_defrag( struct mbuf *m0, int how);
struct mbuf *
m_unshare( struct mbuf *m0, int how);
解説
mbuf は、カーネル IPC サブシステムにおけるメモリ管理の基本ユニットです。ネットワークパケットとソケットバッファは、 mbuf に格納されます。ネットワークパケットは、少ないオーバヘッドでネットワークヘッダを加えるか整えることができる mbuf chain (リンクリスト) にアレンジされた複数の mbuf に掛かることができます。開発者は、将来の変更に伴う非互換性を避けるために、重大な理由なしで mbuf 内部で頭を悩ますべきではありませんが、 mbuf の一般的な構造体を理解していることは役に立ちます。
mbuf は、可変サイズのヘッダとデータのための小さな内部のバッファから成ります。 mbuf の合計サイズ MSIZE は、 < sys/param.h> で定義された定数です。 mbuf ヘッダは、次を含みます:
- m_next
- ( struct mbuf *) mbuf chain の次の mbuf へのポインタ。
- m_nextpkt
- ( struct mbuf *) キュー内の次の mbuf chain へのポインタ。
- m_data
- ( caddr_t) この mbuf にアタッチされたデータへのポインタ。
- m_len
- ( int) データの長さ。
- m_type
- ( short) データのタイプ。
- m_flags
- ( int) mbuf フラグ。
mbuf フラグビットは、次のように定義されます:
/* mbuf フラグ */ #define M_EXT 0x0001 /* 関連する外部記憶がある */ #define M_PKTHDR 0x0002 /* レコードの始まり */ #define M_EOR 0x0004 /* レコードの終わり */ #define M_RDONLY 0x0008 /* 読み込み専用とマークされた関連データ */ #define M_PROTO1 0x0010 /* プロトコル特有 */ #define M_PROTO2 0x0020 /* プロトコル特有 */ #define M_PROTO3 0x0040 /* プロトコル特有 */ #define M_PROTO4 0x0080 /* プロトコル特有 */ #define M_PROTO5 0x0100 /* プロトコル特有 */ #define M_PROTO6 0x4000 /* プロトコル特有 (M_BCAST 競合を避ける) */ #define M_FREELIST 0x8000 /* mbuf はフリーリストにある */ /* mbuf pkthdr フラグ (また, m_flags に格納される) */ #define M_BCAST 0x0200 /* リンクレベルブロードキャストとして 送信/受信 */ #define M_MCAST 0x0400 /* リンクレベルマルチキャストとして 送信/受信 */ #define M_FRAG 0x0800 /* パケットは、より大きいパケットの フラグメント */ #define M_FIRSTFRAG 0x1000 /* パケットは最初のフラグメント */ #define M_LASTFRAG 0x2000 /* パケットは最後のフラグメント */
利用可能な mbuf タイプは、次のように定義されています:
/* mbuf タイプ */ #define MT_DATA 1 /* 動的な (データ) 割り付け */ #define MT_HEADER MT_DATA /* パケットヘッダ */ #define MT_SONAME 8 /* ソケット名 */ #define MT_CONTROL 14 /* 特別なデータプロトコルメッセージ */ #define MT_OOBDATA 15 /* 迅速なデータ */
利用可能な外部のバッファタイプは、次のように定義されています:
/* external buffer types */ #define EXT_CLUSTER 1 /* mbuf クラスタ */ #define EXT_SFBUF 2 /* sendfile(2) の sf_bufs */ #define EXT_JUMBOP 3 /* ジャンボクラスタ 4096 バイト */ #define EXT_JUMBO9 4 /* ジャンボクラスタ 9216 バイト */ #define EXT_JUMBO16 5 /* ジャンボクラスタ 16184 バイト */ #define EXT_PACKET 6 /* パケットゾーンからの mbuf+クラスタ */ #define EXT_MBUF 7 /* 外部 mbuf 参照 (M_IOVEC) */ #define EXT_NET_DRV 100 /* カスタム ext_buf はネットの ドライバによって提供された */ #define EXT_MOD_TYPE 200 /* カスタムモジュールの ext_buf タイプ */ #define EXT_DISPOSABLE 300 /* このバッファを常に w/page flipping に throw できる */ #define EXT_EXTREF 400 /* は、外部的に、維持される ref_cnt ポインタ */
M_PKTHDR フラグが設定されるなら、 struct pkthdr m_pkthdr は、 mbuf ヘッダに追加されます。それは、パケットが受信されたインタフェース ( struct ifnet *rcvif) へのポインタと合計パケット長 ( int len) を含んでいます。また、オプションで、それは、パケットタグ ( struct m_tag) のアタッチされたリストを含みます。詳細については、 mbuf_tags(9) を参照してください。ハードウェアへチェックサム計算をアンロードする際に使用されるフィールドはまた、 m_pkthdr に保存されます。詳細については、 ハードウェアで補助されたチェックサム計算 を参照してください。
十分小さいなら、データは、 mbuf の内部のデータバッファの中に格納されます。データが十分大きいなら、別の mbuf は、 mbuf chain に追加されるか、または外部記憶が mbuf に関連しているかもしれません。データの MHLEN バイトは、 M_PKTHDR フラグの設定で mbuf に適合することができます、そうでなければ、 MLEN バイトに適合できます。
外部記憶が mbuf に関連しているなら、 m_ext ヘッダは、内部のデータバッファを失う費用で加えられます。それは、外部記憶へのポインタ、記憶域のサイズ、記憶域を解放するために使用される関数へのポインタ、関数に渡すことができるオプションの引数へのポインタ、と参照カウンタへのポインタを含みます。外部記憶を使用する mbuf は、 M_EXT フラグの設定があります。
システムは、必要な外部記憶バッファ MEXTADD を割り付けるためのマクロを供給します。
参照カウンタの割り付けと管理は、サブシステムのよって取り扱われます。
また、システムは、 mbuf cluster と呼ばれる外部記憶バッファのデフォルトタイプを供給します。 mbuf cluster は、 MCLGET マクロを使用して割り付けて、設定することができます。それぞれの mbuf cluster は、サイズが MCLBYTES です。ここで、MCLBYTES がマシン依存定数です。システムは、 mbuf cluster に入れる最も少ない量のデータである、諮問マクロ MINCLSIZE を定義します。それは、 MHLEN に 1 加えたものに等しくなります。同じデータを保持するために別々の mbuf cluster を割り付けるのと対照的に、サイズが可能であれば、データを mbuf のデータ領域に格納するのは、通常望ましいことです。
マクロと関数
多数の事前に定義されたマクロと共通のユーティリティを開発者に提供する関数があります。- mtod( mbuf, type)
- mbuf ポインタをデータポインタに変換します。マクロは、指定された type のポインタへのデータポインタのキャスト (cast) に展開します。 注: mbuf に連続したデータが十分あることを保証することは、賢明です。詳細については、 m_pullup() 参照。
- MGET( mbuf, how, type)
-
mbuf を割り付けて、内部のデータを含むように、それを初期化します。
mbuf は、成功すれば、割り付けられた
mbuf を指すか、または失敗すれば
NULL に設定されます。
how 引数は、
M_WAITOK または
M_NOWAIT に設定されます。それは、必要なら、呼び出し側がブロックすることを望んでいるかどうか指定します。
mbuf に関連する多くの他の関数とマクロは、それらが、ある時点で新しい
mbuf を割り付ける必要があるので、同じ引数を持っています。
歴史的に mbuf アロケータ ( 歴史 セクションを参照) は、割り付けフラグ M_WAIT と M_DONTWAIT を使用していました。これらの定数は、互換性のために保持されていますが、新しいコードでそれらを使用することは、お勧めできません。
- MGETHDR( mbuf, how, type)
- mbuf を割り付けて、パケットヘッダと内部のデータを含むように、それを初期化します。詳細については、 MGET() 参照。
- MEXTADD( mbuf, buf, size, free, opt_arg1, opt_arg2, flags, type)
- 外部的に管理されたデータを mbuf に関連付けます。 mbuf 中に含まれるあらゆる内部のデータは、捨てられ、 M_EXT フラグが設定されます。 buf と size 引数は、それぞれデータのアドレスと長さです。 free 引数は、mbuf が解放されるとき、データを解放するために呼び出される関数を指します。それは、 type が EXT_EXTREF である場合にだけ使用されます。 opt_arg1 と opt_arg2 引数は、 free (解放) するために変更されずに渡されます。 flags 引数は、追加の mbuf フラグを指定します。 M_EXT を指定する必要はありません。最終に、 type 引数は、 mbuf が解放されるとき、それがどのように処理されるかを制御する、外部データのタイプを指定します。ほとんどの場合、正しい値は、 EXT_EXTREF です。
- MCLGET( mbuf, how)
- mbuf cluster を mbuf に割り付けて、アタッチします。マクロが失敗するなら、 M_EXT フラグは、 mbuf に設定されないでしょう。
- M_ALIGN( mbuf, len)
- ポインタ mbuf->m_data をロングワードに整列された mbuf の内部のデータ領域の終わりに、サイズ len のオブジェクトを置くように設定します。 mbuf が MGET() または m_get() で新しく割り付けられる場合のみ、適切です。
- MH_ALIGN( mbuf, len)
- M_ALIGN() が行うのと同じ目的で役立ちますが、 MGETHDR() または m_gethdr() で新しく割り付けられた mbuf のためだけか、または m_dup_pkthdr() または m_move_pkthdr() によって初期化します。
- m_align( mbuf, len)
- M_ALIGN() と同じ用途を提供しますが、mbuf のどんなタイプも取り扱います。
- M_LEADINGSPACE( mbuf)
- mbuf のデータの始まりの前の利用可能なバイト数を返します。
- M_TRAILINGSPACE( mbuf)
- mbuf のデータの終わり以降の利用可能なバイト数を返します。
- M_PREPEND( mbuf, len, how)
- このマクロは、 mbuf chain で動作します。それは、(例えば、リンクレイヤヘッダの整備の後に残る) データの前の可能な空き空間を利用することができるように m_prepend() のための最適化されたラッパです。新しい mbuf chain のポインタまたは NULL は、呼び出しの後に mbuf にあります。
- M_MOVE_PKTHDR( to, from)
- このマクロを使用することは、 m_move_pkthdr( to, from) を呼び出すことと同等です。
- M_WRITABLE( mbuf)
- このマクロは、 mbuf が M_RDONLY であるとマークされないなら、そして mbuf が外部記憶を含んでいないなら、または、そうするなら、記憶域の参照カウントが 1 より大きくないなら、真と評価します。 M_RDONLY フラグは、 mbuf->m_flags に設定することができます。これは、外部記憶のセットアップの間に、 flags 引数として M_RDONLY ビットを MEXTADD() マクロに渡すことによって達成することができるか、または個々の mbuf に直接設定することができます。
- MCHTYPE( mbuf, type)
- mbuf のタイプを type に変更します。これは、比較的高価な操作であり、避けられるべきです。
関数は、次の通りです:
- m_get( how, type)
- ノン-クリティカルパスのための MGET() の関数バージョン。
- m_getm( orig, len, how, type)
- 必要なら、 mbuf と mbuf cluster に値する len バイトを割り付けて、そして、 mbuf chain を mbuf chain orig (それが NULL でないなら) に割り付けられた結果を追加します。割り付けがいずれかの点で失敗するなら、割り付けられたものなら何でも解放して、 NULL を返します。 orig が NULL でないなら、それは、解放されません。 len バイトを既存の mbuf または mbuf chain (例えば、前もって割り付けられたリングに位置しているかもしれないもの) に追加するか、または単に mbuf と mbuf cluster 割り付けをいちかばちか実行するために、 m_getm() を使用することは可能です。
- m_gethdr( how, type)
- ノン-クリティカルパスのための MGETHDR() の関数バージョン。
- m_getcl( how, type, flags)
- それにアタッチする mbuf cluster で mbuf を取って来ます。割り付けの 1 つが失敗するなら、全体の割り付けは失敗します。このルーチンは、割り付けの間のアンロック/再ロックすることを避けるように、 mbuf と mbuf cluster を一緒に両方取って来る好ましい方法です。失敗すれば NULL を返します。
- m_getclr( how, type)
- mbuf を割り付けて、データ領域を 0 クリアします。
- m_free( mbuf)
- mbuf を解放します。解放された mbuf の m_next を返します。
下記の関数は、 mbuf chains で動作します。
- m_freem( mbuf)
- 任意の外部記憶も含めて全体の mbuf chain を解放します。
- m_adj( mbuf, len)
- len が正の値なら、 mbuf chain の先頭から len バイトを取り除き、そうでなければ、末尾から取り除きます。
- m_append( mbuf, len, cp)
- データ cp の len バイトを mbuf chain に追加します。新しいデータが既存の空間に適合しないなら、mbuf chain を拡張します。
- m_prepend( mbuf, len, how)
- 新しい mbuf を割り付けて、適切に M_PKTHDR を取り扱う mbuf chain の先頭にそれを追加します。 注: M_PKTHDR フラグの設定によって、 len が MLEN または MHLEN 未満でなければならないので、任意の mbuf cluster を割り付けできません。
- m_copyup( mbuf, len, dstoff)
- m_pullup() と同様ですが、データの len バイトを新しい mbuf の dstoff バイトの位置にコピーします。 dstoff 引数は、データを整列し、リンクレイヤヘッダに空きを残します。成功すれば新しい mbuf chain を返し、失敗すれば mbuf chain を解放して NULL を返します。 注意: 関数が mbuf cluster を割り付けないので、 len + dstoff は、 MHLEN 未満でなければなりません。
- m_pullup( mbuf, len)
- mbuf chain の最初の len バイトは、連続しており、 mbuf のデータ領域に置かれ、したがって、それらは、 mtod( mbuf, type) でアクセス可能であるように調整します。いくらかの mbuf を再割り付けし、データの移動を必要とするかもしれないことを覚えていることは、重要であるので、古い mbuf チェーンの中でデータを参照するすべてのポインタが再計算しなければならないか、または無効にしなければなりません。成功すれば、新しい mbuf chain を返し、失敗すれば、 NULL を返します (この場合、 mbuf chain は、解放されます)。 注: len は、 MHLEN 以下でなければならないので、任意の mbuf cluster を割り付けることができません。
- m_pulldown( mbuf, offset, len, offsetp)
- mbuf chain の offset と offset + len の間の len バイトの調整は、 mbuf のデータ領域に連続して置かれているので、それらは、 mtod( mbuf, type) でアクセスしやすくなります。 len は、 mbuf cluster のサイズ以下でなければなりません。要求された領域を含むチェーンの中間の mbuf へのポインタを返します。返された mbuf に含まれるデータへの mbuf chain のデータ領域のオフセットは、 *offsetp に格納されます。 offp が NULL であるなら、領域は、 mtod( mbuf, type) を使用してアクセスされます。 offp が NULL でなければ、領域は、 mtod( mbuf, uint8_t, +, *offsetp) を使用してアクセスされます。始めと off の間の mbuf チェーンの領域は、変更されていません、したがって、 m_pulldown() を呼び出す前にこの領域中でデータへのポインタを保持することは安全です。
- m_copym( mbuf, offset, len, how)
- 始めの offset バイトから始まり、 len バイトが続く mbuf chain コピーを行います。 len が M_COPYALL であるなら、 mbuf chain の端までコピーします。 注: mbuf cluster がコピーされないので、コピーは、読み込み専用です、それらの参照カウントだけが増加されます。
- m_copypacket( mbuf, how)
- 存在しなければならないヘッダを含む全体のパケットをコピーします。これは、よくある例 m_copym( mbuf, 0, M_COPYALL, how) の最適化されたバージョンです。 注: mbuf cluster がコピーされないので、コピーは、読み込み専用です、それらの参照カウントだけが増加されます。
- m_dup( mbuf, how)
- 任意の mbuf cluster のコピーを含むまったく新しい mbuf chain にパケットヘッダ mbuf chain をコピーします。 mbuf chain の書き込み可能なコピーを必要とするとき、 m_copypacket() の代わりにこれを使用します。
- m_copydata( mbuf, offset, len, buf)
- 始めから off バイトで始まる mbuf chain から、 len バイトを含んで、データを、指示されたバッファ buf にコピーします。
- m_copyback( mbuf, offset, len, buf)
- バッファ buf から mbuf chain の始めから offset で始まる、指示された mbuf chain に len バイトを、必要なら、 mbuf chain を拡張して、コピーし戻します。 注: 任意の mbuf cluster を割り付けません、ただ、 mbuf を mbuf chain に追加します。現在の mbuf chain の終りを越えて offset を設定することは安全です: 0 クリアされた mbuf が空間を満たすために割り付けられます。
- m_length( mbuf, last)
- mbuf chain の長さと、オプションで最終の mbuf へのポインタを返します。
- m_dup_pkthdr( to, from, how)
- 関数の完了したときに、 mbuf to は、 from->m_pkthdr の同一の複製物と mbuf chain from で見つかる 1 パケット毎の属性を含みます。 mbuf from は、最初に設定されたフラグ M_PKTHDR がなければなりません、そして、 to は、入力時には空でなければなりません。
- m_move_pkthdr( to, from)
- m_pkthdr と mbuf chain from からのパケット毎の属性を mbuf to に移動します。 mbuf from は、最初に設定されたフラグ M_PKTHDR がなければなりません、そして、 to は、入力時には、空でなければなりません。関数の完了したときに、 from は、フラグ M_PKTHDR とクリアされたパケット毎の属性を持ちます。
- m_fixhdr( mbuf)
- パケットヘッダ長を mbuf chain の長さに設定します。
- m_devget( buf, len, offset, ifp, copy)
- buf によって指されたデバイスのローカルメモリからのデータを mbuf chain にコピーします。コピーは、指定されたコピールーチン copy か、または copy が NULL であるなら、 bcopy() を使用して行われます。
- m_cat( m, n)
- n を m に連結します。両方の mbuf chains は、同じタイプでなければなりません。関数が戻った後でも N は、有効です。 注: それは、 M_PKTHDR とフレンドを取り扱いません。
- m_split( mbuf, len, how)
- mbuf chain を 2 つの部分に分離して末尾を返します: 最初の len バイトのほかはすべて。失敗の場合には、それは、 NULL を返して、 mbuf chain を元の状態に復元することを試みます。
- m_apply( mbuf, off, len, f, arg)
-
オフセット
off で長さ
len バイトの
mbuf chain に関数を適用します。そうでなければ不要であるか、または望ましくない
m_pullup() への呼び出しを避けるために通常使用されます。
arg は、コールバック関数
f に渡される便利な引数です。
f() が呼び出されるたびに、 arg、現在の mbuf の data へのポインタ、と関数が適用されるべきであるこの mbuf のデータの長さ len が渡されます。
関数は、成功を示すために 0 を返すべきです。そうでなければ、エラーが示されるなら、 m_apply() は、エラーを返し、 mbuf chain を通して繰り返すのを停止します。
- m_getptr( mbuf, loc, off)
- ポインタを mbuf chain の始まりから loc バイトに位置するデータを含む mbuf へのポインタを返します。 mbuf への対応するオフセットは、 *off に格納されます。
- m_defrag( m0, how)
-
mbuf chain の断片化を解消して、mbuf とクラスタの最も短い可能なチェーンを返します。割り付けが失敗して、これを完了することができないなら、
NULL が返され、元のチェーンは、変更されません。成功すれば、元のチェーンは、解放され、新しいチェーンが返されます。呼び出し側の好みによって、
how は、
M_WAITOK または
M_NOWAIT のいずれかであるべきです。
特定の長い mbuf chains が TX 記述子リストに追加される前に、短縮されなければならないところで、この関数は、ネットワークドライバで特に役に立ちます。
- m_unshare( m0, how)
-
他のユーザに影響しないで内容を安全に変更することができる指定された mbuf チェーンのバージョンを作成します。割り付けが失敗して、この操作が完了することができないなら、
NULL が返されます。オリジナルの mbuf チェーンは、常に再要求され、任意の共有された mbuf クラスタの参照カウントは、減少されます。呼び出し側の選択によって、
how は、
M_WAITOK または
M_NOWAIT のいずれかであるべきです。このプロセスの副作用として、返された mbuf チェーンは、圧縮されます。
この関数は、データを暗号化するか、またはそうでなければ転送する前に変更されなければならないとき、ネットワークコードの転送パスで特に役に立ちます。
ハードウェアで補助されたチェックサム計算
このセクションは、現在、TCP/IP だけに適用されます。ホスト CPU リソースを保存するために、チェックサムを計算することは、可能であれば、ネットワークインタフェースハードウェアへオフロード (降ろ) されます。パケットの先導する mbuf の m_pkthdr メンバは、そのために使用される 2 つのフィールド、 int csum_flags と int csum_data を含みます。それらのフィールドの意味は、パケットが流れる方向と、パケットが断片化されるかどうかによって決まります。これからは、パケットの csum_flags または csum_data は、パケットを含む mbuf chain の先導する mbuf の m_pkthdr メンバの対応するフィールドを示します。出力のときに、発信インタフェースがパケットのために決定した後にチェックサムのオフロードが試みられます。チェックサムを計算するのを助けるインタフェースの能力のためにインタフェース特有のフィールド ifnet.if_data.ifi_hwassist ( ifnet(9) 参照) を調べます。パケットヘッダの csum_flags フィールドは、インタフェースがそれを実行するはずである動作を示すために設定されます。ネットワークインタフェースによってサポートされない動作は、インタフェースドライバまで下がってパケットを渡す前に、ソフトウェアで実行されます。そのような動作は、 csum_flags を通して決して要求されません。
インタフェースから特定の動作を要求するフラグは、次の通りです:
- CSUM_IP
- IP ヘッダチェックサムは、パケットの対応するフィールドで計算されて、格納されます。ハードウェアは、IP チェックサムフィールドのオフセットを決定するために IP ヘッダの形式を知っていると予想されます。
- CSUM_TCP
- TCP チェックサムが計算されます。 (下記参照。)
- CSUM_UDP
- UDP チェックサムが計算されます。 (下記参照。)
TCP または UDP チェックサムは、ハードウェアへオフロードされるはずで、フィールド csum_data は、IP ヘッダの終りに関連のあるチェックサムフィールドのバイトオフセットを含みます。この場合、チェックサムフィールドは、初めに、TCP と UDP 仕様で定義された疑似ヘッダのチェックサムへの TCP/IP モジュールによって設定されます。
入力のときに、インタフェースは、パケットに関連している csum_flags で次のフラグの 1 つ以上を設定することによってパケットで実行される動作を示します:
- CSUM_IP_CHECKED
- IP ヘッダチェックサムが計算されます。
- CSUM_IP_VALID
- IP ヘッダには、有効なチェックサムがあります。このフラグは、 CSUM_IP_CHECKED との組み合わのみに指定することができます。
- CSUM_DATA_VALID
- IP パケットのデータの一部のチェックサムは、計算されて、ネットワークバイト順でフィールド csum_data に格納されます。
- CSUM_PSEUDO_HDR
- TCP と UDP 仕様で定義された疑似ヘッダのために許された csum_data で見つけられた IP データチェックサムを示すために CSUM_DATA_VALID と共にだけ設定することができます。そうでなければ、疑似ヘッダのチェックサムは、ホスト CPU によって計算され、TCP か UDP の有効化の目的のために使用される最終的なチェックサムを得るために csum_data に加えなければなりません。
特定のネットワークインタフェースがただ、ホスト CPU の正確な値を返さないで TCP か UDP のチェックサムの有効化の成功か失敗を示すなら、ドライバは、 csum_flags に CSUM_DATA_VALID と CSUM_PSEUDO_HDR をマークし、 csum_data に有効なチェックサムを示す 16 進 0xFFFF
を設定することができます。それは、任意の有効なパケットで計算されたインターネットチェックサムが元のチェックサムフィールドが含まれている限り、 0xFFFF
になることに使用されるアルゴリズムの特性です。
ストレステスト
オプション MBUF_STRESS_TEST でコンパイルされたカーネルを実行するとき、次の sysctl(8) によって制御されたオプションは、 mbuf を当てにするネットワークドライバとカーネルの他の部品のテストのために様々な失敗/極端な場合を引き起こすために使用されます。- net.inet.ip.mbuf_frag_size
- ip_output() は、発信 mbuf chains を指定されたサイズの断片に断片化させます。この変数を 1 に設定することは、ネットワークドライバの長い mbuf chain を取り扱う能力をテストする素晴らしい方法です。
- kern.ipc.m_defragrandomfailures
- 関数 m_defrag() がランダムに失敗し、 NULL を返させます。 m_defrag() を使用する任意のコードの一部分は、この機能でテストされるべきです。
戻り値
上記参照。歴史
mbuf は、 BSD の早期のバージョンで登場しました。ネットワークパケットに使用されることのほかに、それらは、ルーティングテーブルエントリ、インタフェースアドレス、プロトコル制御ブロックなどのような、様々な動的構造体を格納するために使用されました。より最近の FreeBSD では、 mbuf の使用は、他のネットワーク関連のメモリを格納するために直接使用されている uma(9) ゾーンで、パケットを格納するために、ほぼ全体が制限されます。歴史的に、 mbuf アロケータは、割り込みコンテキストと特別のカーネルアドレス空間マップからの割り付けで実行できる専用のメモリアロケータです。 FreeBSD 5.3 以後は、 mbuf アロケータは、スラブ (slab) 割り付けの他の利益をもたらすのと同様に、 mbuf、クラスタと CPU 毎のキャッシュで mbuf + クラスタペアのキャッシングができる、 uma(9) まわりのラッパです。
November 13, 2012 | FreeBSD |