NETMAP(4) | FreeBSD Kernel Interfaces Manual | NETMAP(4) |
名称
netmap — 速いパケット I/O のためのフレームワーク書式
device netmap解説
netmap は、(1GHz 未満で 14.88 の Mpps に達する) ネットワークデバイスへの速くて安全なアクセスのためのフレームワークです。 netmap は、 ioctl() と select()/poll() を通して情報を有効にすることを任されている、カーネルと通信するためにメモリマップバッファ (memory mapped buffer) とメタデータ (バッファのインデックスと長さ) を使用します。 netmap は、マルチキュー (multiqueue) デバイスとマルチコア (multicore) システムで並列性を有効に使うことができます。netmap は、デバイスドライバの明示的なサポートを要求します。サポートされたデバイスのリストについて、このマニュアルページの終りを参照してください。
操作
netmap クライアントは、最初に open("/dev/netmap") をオープンして、次に、ファイル記述子をネットワークデバイスにバインドするために ioctl(...,NIOCREGIF,...) を発行しなければなりません。デバイスが netmap モードに置かれるとき、そのデータのパスは、ホストスタックから切断されます。ファイル記述子を所有するプロセスは、前もって割り付けられたバッファとメタデータを含んでいる mmap されたメモリ領域を通して、デバイスで、またはホストスタックでパケットを交換することができます。
ブロック化されていない I/O は、着信パケットまたは利用可能な送信バッファに関して通知される select()/poll() にファイル記述子を渡すことができる、特別の ioctl() で行われます。
データ構造
netmap モードのすべてのデバイスのためのすべてのデータ構造は、 /dev/netmap をオープンするカーネルとすべてのプロセスによって共有されるメモリ領域にあります (注: 可視性は、将来の実装で制限されるかもしれません)。共有されたデータ構造の間のすべての参照は、相対的です (オフセットまたはインデックス)。いくつかのマクロは、それらを実際のポインタに変換することを支援します。共有されたメモリのデータ構造は、次の通りです:
- struct netmap_if (インタフェース毎に 1 つ)
-
インタフェースによってサポートされるリングの数、それらのサイズ、とインタフェースに関連する
netmap_rings のオフセットを示します。共有されたメモリ領域の
struct netmap_if のオフセットは、
NIOCREGIF (下記参照) によって返された構造体の
nr_offset フィールドによって示されます。
struct netmap_if { char ni_name[IFNAMSIZ]; /* インタフェースの名前. */ const u_int ni_num_queues; /* hw リングペアの数 */ const ssize_t ring_ofs[]; /* tx と rx のリングのオフセット */ };
- struct netmap_ring (リング毎に 1 つ)
-
現在の読み込みまたは書き込みスロットのインデックス (cur)、受信または送信に利用可能なスロットの数、とバッファを記述する
slots の配列を含んでいます。 (0..N-1 と番号が付けられた) カードによってサポートされた N ハードウェアリングペアの各々のための 1 つのリングペア、およびホストスタック (から/へ) のパケットのための (N と番号が付けられた) 1 つのリングペアがあります。
struct netmap_ring { const ssize_t buf_ofs; const uint32_t num_slots; /* リングのスロットの数. */ uint32_t avail; /* 使用可能なスロットの数 */ uint32_t cur; /* ユーザ側の '現在の' インデックス */ uint32_t reserved; /* 現在時点では書き込まれていません */ const uint16_t nr_buf_size; uint16_t flags; struct netmap_slot slot[0]; /* スロットの配列. */ }
- struct netmap_slot (パケット毎に 1 つ)
-
次のパケットのためのメタデータを含んでいます: バッファインデックス (buf_idx)、バッファ長 (len) といくつかのフラグ。
struct netmap_slot { uint32_t buf_idx; /* バッファのインデックス */ uint16_t len; /* パケット長 */ uint16_t flags; /* 変更されたバッファ等. */ #define NS_BUF_CHANGED 0x0001 /* resync しなければならない, 変更 * されたバッファ */ #define NS_REPORT 0x0002 /* 結果を報告するために hw に伝える * 例えば, 割り込みの生成によって */ };
- パケットバッファ
- は、パケットデータを含んでいる、カーネルによって割り付けられた固定サイズ (約 2k) のバッファです。バッファアドレスは、マクロによって計算されます。
いくつかのマクロは、共有されたメモリ領域のオブジェクトへのアクセスをサポートします。特に次の通りです:
struct netmap_if *nifp; struct netmap_ring *txring = NETMAP_TXRING(nifp, i); struct netmap_ring *rxring = NETMAP_RXRING(nifp, i); int i = txring->slot[txring->cur].buf_idx; char *buf = NETMAP_BUF(txring, i);
IOCTL
netmap は、カーネルとユーザプロセスの間のリングの状態を同期させるために、さらに、インタフェースを問い合わせて、設定する、いくつかの ioctl() をサポートしています。前者は、引数を要求しませんが、一方、後者は、次のように定義された struct netmap_req を使用します:
struct nmreq { char nr_name[IFNAMSIZ]; uint32_t nr_version; /* API のバージョン */ #define NETMAP_API 3 /* 現在のバージョン */ uint32_t nr_offset; /* 共有される領域の nifp オフセット */ uint32_t nr_memsize; /* 共有される領域のサイズ */ uint32_t nr_tx_slots; /* tx リングのスロット */ uint32_t nr_rx_slots; /* rx リングのスロット */ uint16_t nr_tx_rings; /* tx リングの数 */ uint16_t nr_rx_rings; /* tx リングの数 */ uint16_t nr_ringid; /* 関心がある (複数の) リング */ #define NETMAP_HW_RING 0x4000 /* 1 つの hw リングを示す下位ビット */ #define NETMAP_SW_RING 0x2000 /* sw リングを処理する */ #define NETMAP_NO_TX_POLL 0x1000 /* ポーリングで余計な txsync なし */ #define NETMAP_RING_MASK 0xfff /* 実際のリング番号 */ uint16_t spare1; uint32_t spare2[4]; };
/dev/netmap によって取得されたデバイス記述子は、ネットワークデバイスによってサポートされた ioctl もまたサポートします。
下記の netmap に特有の ioctl(2) コマンドコードは、 < net/netmap.h> と次に定義されています:
- NIOCGINFO
-
nr_name で指定されたインタフェースに関するリターン情報。返り時に、nr_memsize は、共有される netmap メモリ領域 (これは、デバイス独立です) のサイズを示し、 nr_tx_slots と nr_rx_slots は、どのくらい多くのバッファが送信と受信リングにあるかを示し、 nr_tx_rings と nr_rx_rings は、ハードウェアによってサポートされる送信と受信リングの数を示します。
デバイスが netmap をサポートしないなら、ioctl は、EINVAL を返します。
- NIOCREGIF
-
nr_name で指定されたインタフェースをホストスタックからそれを切断している、 netmap モードにし、および/または、どのリングがこのファイル記述子によって制御されるか定義します。返り時に、NIOCGINFO と同じ情報を与え、 nr_ringid は、ファイル記述子によって制御されるリングの識別を示します。
nr_ringid に指定できる値は、次の通りです:
- 0
- デフォルトで、すべてのハードウェアリング
- NETMAP_SW_RING
- ホストスタックに接続する ``ホストリング''
- NETMAP_HW_RING + i
- i 番目のハードウェアリング
デフォルトで、 poll または select 呼び出しは、たとえ書き込みイベントが指定されなくても、送信リングであらゆる保留中 (pending) のパケットを押し出します。 nr_ringid に NETMAP_NO_TX_SYNC を論理 OR することによってこの機能を無効にすることができます。しかし、通常、利用者は、送信と受信リングのための個別のファイル記述子を使用しないなら、この機能を維持するべきです、なぜなら、そうでなければ、パケットは、NETMAP_TXSYNC が呼び出されるか、送信キューが満杯である場合のみ、押し出されます。
常に同じデバイス内で、リングペアにファイル記述子の関連性を変更するために NIOCREGIF を、複数回、使用することができます。
- NIOCUNREGIF
- インタフェースを通常モードにします。
- NIOCTXSYNC
- 送信する新しいパケットのハードウェアを伝え、送信のために利用可能なスロットの数を更新します。
- NIOCRXSYNC
- 消費されるパケットのハードウェアを伝え、新しく利用可能なパケットを要求します。
システムコール
netmap は、十分なイベントが起こるとき、プロセスを起こすために、 select と poll 使用します。使用例
次のコードは、トラフィックジェネレータを実装しています:
#include <net/netmap.h> #include <net/netmap_user.h> struct netmap_if *nifp; struct netmap_ring *ring; struct nmreq nmr; fd = open("/dev/netmap", O_RDWR); bzero(&nmr, sizeof(nmr)); strcpy(nmr.nr_name, "ix0"); nmr.nr_version = NETMAP_API; ioctl(fd, NIOCREG, &nmr); p = mmap(0, nmr.nr_memsize, fd); nifp = NETMAP_IF(p, nmr.offset); ring = NETMAP_TXRING(nifp, 0); fds.fd = fd; fds.events = POLLOUT; for (;;) { poll(list, 1, -1); for ( ; ring->avail > 0 ; ring->avail--) { i = ring->cur; buf = NETMAP_BUF(ring, ring->slot[i].buf_index); ... prepare packet in buf ... ring->slot[i].len = ... packet length ... ring->cur = NETMAP_RING_NEXT(ring, i); } }
関連項目
vale(4)http://info.iet.unipi.it/~luigi/netmap/
Luigi Rizzo, Revisiting network I/O APIs: the netmap framework, Communications of the ACM, 55 (3), pp.45-51, March 2012
Luigi Rizzo, netmap: a novel framework for fast packet I/O, Usenix ATC'12, June 2012, Boston
作者
netmap フレームワークは、 , , の助けを借りて によって 2011 年に Universita` di Pisa にて設計され実装されました。netmap は、FP7 Project CHANGE (257422) 内の欧州委員会によって資金援助されました。
September 23, 2013 | FreeBSD |