NAME
ibv_post_send - Send Queue (SQ) に work request (WR) のリストを登録する。
SYNOPSIS
#include <infiniband/verbs.h> int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr, struct ibv_send_wr **bad_wr);
DESCRIPTION
ibv_post_send()
は queue pair qp の send queue (RQ) に対して、wr から片方向リンクでつながっている一連の Send Work Request (WR) のリストを登録する。
もしリストの先頭から WR を登録し、最初に失敗した箇所で停止し、bad_wr に登録に失敗した WR の struct ibv_send_wr
構造体へのポインタをコピーする。
例えば、最初の Send WR の登録に失敗した場合、*bad_wr = wr
がコピーされる。
メンバ名 | 型 | 説明 | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
wr_id | uint64_t | ユーザーが自由に設定できる WR ID。この値は ibv_poll_cq で取り出す完了の中に埋め込まれる。 | ||||||||||||||||||||||||||||||||||||||||||
next | struct ibv_send_wr * | 1 度の ibv_post_send() で複数の Send WR を登録したい場合、next を使って片方向リストを作る。最後の Send WR には NULL を設定する。 | ||||||||||||||||||||||||||||||||||||||||||
sg_list | struct ibv_sge * | ローカルバッファを示す scatter/gather 組を struct ibv_sge 構造体の配列へのポインタで指定する。num_sge が 0 なら NULL でよい。 | ||||||||||||||||||||||||||||||||||||||||||
num_sge | int | sg_list が指す struct ibv_sge 構造体の配列の要素数。0 以上で QP ケーパビリティの max_recv_sge 未満の値を指定すること。0 はローカルバッファのサイズが 0 を意味する。 | ||||||||||||||||||||||||||||||||||||||||||
opcode | enum ibv_wr_opcoe |
オペレーション種類を指定する。
QP のサービスタイプによって指定可能なオペレーションは制限される。
詳細は「InfiniBand プログラムに必要な基本的な概念」 7.オペレーションの種類を参考。 | ||||||||||||||||||||||||||||||||||||||||||
send_flags | int | Send WR のプロパティを設定する。以下のマクロの論理和を指定する。
| ||||||||||||||||||||||||||||||||||||||||||
imm_data | uint32_t | Immediate data。SEND with Immediate オペレーションと RDMA WRITE with Immediate オペレーションで使用する。ネットワークバイトオーダーで指定。 | ||||||||||||||||||||||||||||||||||||||||||
wr | wr は共用体で RC/UC サービスの SEND オペレーション以外で使用する。 | |||||||||||||||||||||||||||||||||||||||||||
rdma | wr.rdma は RDMA WRITE オペレーション、RDMA WRITE with Immediate オペレーション、RDMA READ オペレーションを使用する際に指定する。 | |||||||||||||||||||||||||||||||||||||||||||
remote_addr | uint64_t | リモートメモリバッファの開始アドレス。 | ||||||||||||||||||||||||||||||||||||||||||
rkey | uint32_t | リモートの memory region の R_Key。 | ||||||||||||||||||||||||||||||||||||||||||
atomic | wr.atomic は Compare and Swap オペレーションと Fetch and Add オペレーションを使用する際に指定する。 | |||||||||||||||||||||||||||||||||||||||||||
remote_addr | uint64_t | リモートメモリバッファの開始アドレス。8 バイト境界に揃える必要がある。 | ||||||||||||||||||||||||||||||||||||||||||
compare_add | uint64_t | メモリ内容の比較に使う「現在値」。Compare and Swaop オペレーションでのみ指定。 | ||||||||||||||||||||||||||||||||||||||||||
swap | uint64_t | 比較が成功した時にメモリ内容を書き換える「変更値」。Compare and Swaop オペレーションでのみ指定。 | ||||||||||||||||||||||||||||||||||||||||||
rkey | uint32_t | メモリ内容に追加する「増分」。Fetch and Add オペレーションでのみ指定。 | ||||||||||||||||||||||||||||||||||||||||||
ud | wr.ud は UD サービスにおいて SEND オペレーションを使用する際に指定する。 | |||||||||||||||||||||||||||||||||||||||||||
ah | struct ibv_ah * | 送信先を示す address handle(AH)。ibv_create_ah() で作成したものを指定。 | ||||||||||||||||||||||||||||||||||||||||||
remote_qpn | uint32_t | 送信先の QP 番号。 | ||||||||||||||||||||||||||||||||||||||||||
remote_qkey | uint32_t | Q_Key となる 32 ビット値を設定する。
詳細は「InfiniBand プログラムに必要な基本的な概念」 12.2 UD サービスのための保護機構を参照のこと。 |
QP ケーパビリティは ibv_create_qp()、ibv_modify_qp() で設定可能で、ibv_query_qp() で現在値を取得できる。
1 つの Sen WR のローカルバッファは複数の scatter/gather 組で構成できるが、各 scatter/gather は同一の memory region 内に収まる必要がある。 「InfiniBand プログラムに必要な基本的な概念」 6.5 Work Request と Work Completion のデータ構造を参照のこと。
メンバ名 | 型 | 説明 |
---|---|---|
addr | uint64_t | 1 s/g 組の開始アドレス。 |
length | uint32_t | 1 s/g 組の長さ。 |
lkey | uint32_t | addr と length が所属する memory region の L_Key を指定する。ibv_reg_mr() の戻り値となった struct ibv_mr 構造体の lkey の値をコピーすればよい。 |
Send WR で指定するローカルバッファのサイズは scatter/gather 配列の合計である。 UD QP では、この合計サイズがポートの Active MTU を越えた場合はエラーとなる(ポートの Active MTU は ibv_query_port() によって取得できる active_mtu で確認できる)。 同様に RC/UC QP では、この合計サイズが HCA のメッセージの最大長を越えた場合はエラーとなる(メッセージの最大長は ibv_query_port() によって取得できる max_msg_sz で確認できる)。 詳細は 「InfiniBand のエラーハンドリングのモデルを理解する」 2.2 Local Length Error (IBV_LOC_LEN_ERR)を参照のこと。
Send WR で指定するローカルバッファのサイズを 0 にしたい場合は、struct ibv_recv_wr
構造体の num_sge の値を 0 に設定すること。
struct ibv_sge
構造体の length に 0 を指定した場合、HCA によっては 0x8000,0000 バイトを指定したとみなされる。
Send WR はローカルバッファをどのように使用するかは、Table 3 に従うこと。
オペレーション | 転送の方向 | ローカルバッファ | リモートバッファ | 転送サイズ |
---|---|---|---|---|
SEND オペレーション(with Immediate も含む) | ローカルバッファのデータをリモートへ | 必要なアクセス権限は 0(なし) | Receive WR を使用。Receive WR に必要なアクセス権限は IBV_ACCESS_LOCAL_WRITE。 | ローカルバッファの合計サイズ |
RDMA WRITE wih Immediate オペレーション |
|
|||
RDMA WRITE オペレーション | wr.rdma.rkey が示す memory region に IBV_ACCESS_LOCAL_WRITE と IBV_ACCESS_REMOTE_WRITE が必要。 | |||
READ オペレーション | リモートからのデータをローカルバッファへ | IBV_ACCESS_LOCAL_WRITE | wr.rdma.rkey が示す memory region に IBV_ACCESS_REMOTE_READ が必要。 | |
Compare and Swap オペレーション Fetch and Add オペレーション |
wr.rdma.rkey が示す memory region に IBV_ACCESS_LOCAL_WRITE と IBV_ACCESS_REMOTE_ATOMIC が必要。 | 8 バイト固定 |
RETURN VALUE
ibv_post_recv()
は成功した場合、0 を返す。
失敗した場合は、エラーの原因を示す値(errno と同じ)を返す。
ERRORS
ibv_post_send()
はエラー時には復帰値に errno と同じ値が入る。
ENOMEM | QP ケーパビリティの max_send_wr を越えて Send WR を登録しようとした。 |
InfiniBand Architecture Specification Volume 1 Release 1.2.1 C10-96 には、QP が Reset、Init、RTR ステートの時に Send WR を SQ に登録する場合、immediate error を返す仕様になっている。
つまり ibv_post_send()
は非 0 値を返す必要がある。
しかし一部の HCA では、Reset、Init、RTR ステートでも ibv_post_send()
を実行しても成功を返す場合がある。
この場合、その後 QP を RTS ステートまで遷移させた時に正しく送信できることは保証されないと思われる。
NOTES
- Send WR で登録したローカルバッファは、ibv_poll_cq() で Work Completion で取り出すまで安全に再利用することはできない。
ibv_post_send()
は wr から片方向リンクでつながるデータ構造を内部でコピーするので、ibv_post_send()
の復帰後は領域を開放してもよい。ibv_post_send()
は s/g が指定した領域の重なりをチェックしない。 プログラム側で重ならないように指定する必要がある。- wr が next を作って循環するリンクを作った場合、異常終了すると思われる。
- Send WR で登録する scatter/gather 組で指定する memory region は、qp の protection domain と一致させる必要がある。
SEE ALSO
InfiniBand Verbs API Reference、ibv_create_qp(3)、ibv_create_ah(3)、ibv_post_recv(3)、ibv_post_src_recv(3)、ibv_post_cq(3)
AUTHORS
原文 Dotan Barak <dotanba@gmail.com>
原文にない加筆がある。