NAME
ibv_post_recv - Receive Queue (RQ) に work request (WR) のリストを登録する。
SYNOPSIS
#include <infiniband/verbs.h> int ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr);
DESCRIPTION
ibv_post_recv()
は queue pair qp の receive queue (RQ) に対して、wr から片方向リンクでつながっている一連の Receive Work Request (WR) のリストを登録する。
もしリストの先頭から WR を登録し、最初に失敗した箇所で停止し、bad_wr に登録に失敗した WR の struct ibv_recv_wr
構造体へのポインタをコピーする。
例えば、最初の Receive WR の登録に失敗した場合、*bad_wr = wr
がコピーされる。
メンバ名 | 型 | 説明 |
---|---|---|
wr_id | uint64_t | ユーザーが自由に設定できる WR ID。この値は ibv_poll_cq で取り出す完了の中に埋め込まれる。 |
next | struct ibv_recv_wr * | 1 度の ibv_post_recv() で複数の Receive WR を登録したい場合、next を使って片方向リストを作る。最後の Receive 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 を意味する。 |
QP ケーパビリティは ibv_create_qp()、ibv_modify_qp() で設定可能で、ibv_query_qp() で現在値を取得できる。
1 つの Receive 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 の値をコピーすればよい。 |
Receive WR がデータを受信する時は、scatter/gather 配列の先頭から順番に利用され、余った領域は使用されないで終わる。 受信したメッセージ長が Receive WR の受信領域長よりも大きい場合は、UD QP ではメッセージが破棄され、RC/UC QP ではエラーとなる。 同様に受信したメッセージ長が HCA のメッセージの最大長を越えた場合はエラーとなる(メッセージの最大長は ibv_query_port() によって取得できる max_msg_sz で確認できる)。 詳細は 「InfiniBand のエラーハンドリングのモデルを理解する」 2.2 Local Length Error (IBV_LOC_LEN_ERR)を参照のこと。
UD QP の場合、受信領域の先頭 40 バイトには必ず Global Routing Header (GRH) 用の領域が確保される。 これは GRH が設定されたメッセージを受信すると GRH が格納され、GRH がない場合は 40 バイトの不定値値が入る。
Receive WR で指定する受信領域のサイズを 0 にしたい場合は、struct ibv_recv_wr
構造体の num_sge の値を 0 に設定すること。
struct ibv_sge
構造体の length に 0 を指定した場合、HCA によっては 0x8000,0000 バイトを指定したとみなされる。
Recieve WR で受信領域となる memory region は、ibv_reg_mr() で生成する時に引数 access に IBV_ACCESS_LOCAL_WRITE のビットを立てておく必要がある。
RETURN VALUE
ibv_post_recv()
は成功した場合、0 を返す。
失敗した場合は、エラーの原因を示す値(errno と同じ)を返す。
ERRORS
ibv_post_recv()
はエラー時には復帰値に errno と同じ値が入る。
ENOMEM | QP ケーパビリティの max_recv_wr を越えて Receive WR を登録しようとした。 |
InfiniBand Architecture Specification Volume 1 Release 1.2.1 C10-97.2.1 には、QP が Reset ステートの時に Receive WR を RQ に登録する場合、immediate error を返す仕様になっている。
つまり ibv_post_recv()
は非 0 値を返す必要がある。
しかし一部の HCA では、Reset ステートでも ibv_post_recv()
を実行しても成功を返す場合がある。
この場合、その後 QP を RTR ステートまで遷移させた時に正しく受信できることは保証されないと思われる。
NOTES
- qp が SRQ を使っている場合には、
ibv_post_recv()
ではなく ibv_post_srq_recv() を使うこと。 - Receive WR で登録した受信領域は、ibv_poll_cq() で Work Completion で取り出すまで安全に再利用することはできない。
ibv_post_recv()
は wr から片方向リンクでつながるデータ構造を内部でコピーするので、ibv_post_recv()
の復帰後は領域を開放してもよい。ibv_post_recv()
は s/g が指定した領域の重なりをチェックしない。 プログラム側で重ならないように指定する必要がある。- wr が next を作って循環するリンクを作った場合、異常終了すると思われる。
- Receive WR で登録する scatter/gather 組で指定する memory region は、qp の protection domain と一致させる必要がある。
SEE ALSO
InfiniBand Verbs API Reference、ibv_create_qp(3)、ibv_post_send(3)、ibv_post_src_recv(3)、ibv_post_cq(3)
AUTHORS
原文 Dotan Barak <dotanba@gmail.com>
原文にない加筆がある。