この文書は InfiniBand Verbs プログラムで必要になる InfiniBand のエラーハンドリングのモデルを解説する。
ただし InfiniBand Verbs でサポートしない Reliable Datagram(RD) サービスタイプは扱わず、Reliable Connection(RC)、Unreliable Connection(UC)、Unreliable Datagram(UD) の 3 つのサービスタイプのみを説明する。 eXtensible Reliable Connection(XRC) サービスタイプのエラーはまだ記載していない。 将来的に追記する。
以下は関連ページ。
更新履歴
(2014.04.17) 作成。
(2014.05.11) API にリンクを貼る
目次
- 1. はじめに
- 2. 完了エラー(Completion Error)
- 2.1 Success (IBV_WC_SUCCESS)
- 2.2 Local Length Error (IBV_LOC_LEN_ERR)
- 2.3 Local QP Operation Error (IBV_WC_LOC_QP_OP_ERR)
- 2.4 Local Protection Error (IBV_WC_LOC_PROT_ERR)
- 2.5 Work Request Flushed Error (IBV_WC_WR_FLUSH_ERR)
- 2.6 Local Access Error (IBV_WC_LOC_ACCESS_ERR)
- 2.7 Bad Response Error (IBV_WC_BAD_RESP_ERR)
- 2.8 Remote Invalid Request Error (IBV_WC_REM_INV_REQ_ERR)
- 2.9 Remote Access Error (IBV_WC_REM_ACCESS_ERR)
- 2.10 Remote Operation Error (IBV_WC_REM_OP_ERR)
- 2.11 Transport Retry Counter Exceed (IBV_WC_RETRY_EXC_ERR)
- 2.12 RNR Retry Counter Exceeded (IBV_WC_RNR_RETRY_EXC_ERR)
- 2.13 Aborted Error (IBV_WC_REM_ABORT_ERR)
- 2.14 Fatal Error (IBV_WC_FATAL_ERR)
- 2.15 Response Timeout Error (IBV_WC_RESP_TIMEOUT_ERR)
- 2.16 General Error (IBV_WC_GENERAL_ERR)
- 3. 非同期エラー(Asynchronous Error)
- 4. パターンごとの発生するエラー
- 5. その他のトピックス
- コメント
1. はじめに
InfiniBand のエラーは 3 種類の方法で報告される。 そのうち 2 種類は概念編とチュートリアル編で説明した 完了エラー(Completion Error) と非同期エラー(Asynchronous Error) である。
完了エラーは Completion Queue(CQ) に Work Completion として報告されるエラーであり、全て Queue Pair(QP) と紐付けられている。 完了エラーは ibv_poll_cq で取得する。
非同期エラーは様々な原因によって生じ、ibv_get_async_event で取得することができる。 非同期エラーはまずユーザーコンテキストが作り出した QP、CQ、Shared Receive Queue(SRQ) に関連した Affiliated Error と、HCA や Port に関連した Unaffiliated Error に大別される。 Affiliated error はエラーを生成する原因となったオブジェクトの所有ユーザーコンテキストにだけ報告されるが、unaffiliated error はシステム内にある全てのユーザーコンテキストにブロードキャストされる(そのため libibverbs-utils パッケージに含まれる ibv_asyncwatch は unaffiliated error だけを監視できる)。
非同期エラーと言ったが一部に非同期イベント(Asynchronous Event) も含まれる。 名前だけの違いなので両者を区別する必要は特にない。 この文書では非同期エラーで代表させる。
最後は Immediate Error と呼ばれる。 日本語にし辛いが 即答エラー か? これは InfiniBand Verbs API の関数戻り値がエラーとなって復帰する場合である。 この文書ではあまり触れない。

InfiniBand のエラーハンドリングを考える場合、以下の点を踏まえておく必要がある。
- InfiniBand は完了エラーで報告できる場合は完了エラーを優先し、できない場合は非同期エラーで報告する。
- InfiniBand の仕様には、HCA の実装の仕方によりエラーの報告方法が変わる幅が設けられている。また HCA の実装によっては仕様を破っているものもある。
2. 完了エラー(Completion Error)
ibv_poll_cq() で返される完了は struct ibv_wc
構造体を持っている。
この中で status は enum ibv_wc_status
列挙子型を持ち、完了エラーの種類を報告する。
完了エラーが ibv_poll_cq() から取り出された場合、表中で明示的に「QP をエラーに落とさない」と書いてないものは、QP を Error ステートまたは Send Queue Error(SQE) ステートへ強制遷移させる。
Side の列は、requester side と responder side のどちらで発生するかを示している。 Services の列は、この完了エラーが発生する可能性のあるサービスタイプを示している。
イベント名 | 値 | Side | Services | QP Error | 備考 |
---|---|---|---|---|---|
Success | IBV_WC_SUCCESS | Both | All | None | |
Local Length Error | IBV_WC_LOC_LEN_ERR | Responder | RC/UC | Error | Receive WRバッファ長の不足 |
All | RC/UC | Error or SQE | メッセージ最大長の超過 | ||
Local QP Operation Error | IBV_WC_LOC_QP_OP_ERR | Both | All | Error or SQE | |
Local Protection Error | IBV_WC_LOC_PROT_ERR | Both | All | Error or SQE | |
Work Request Flushed Error | IBV_WC_WR_FLUSH_ERR | Both | All | None | |
Memory Management Operation Error | IBV_WC_MW_BIND_ERR | ||||
Local Access Error | IBV_WC_LOC_ACCESS_ERR | Responder | RC/UC | Error | |
Bad Response Error | IBV_WC_BAD_RESP_ERR | Requester | RC | Error | |
Remote Invalid Request Error | IBV_WC_REM_INV_REQ_ERR | Requester | RC | Error | |
Remote Access Error | IBV_WC_REM_ACCESS_ERR | Requester | RC | Error | |
Remote Operation Error | IBV_WC_REM_OP_ERR | Requester | RC | Error | |
Transport Retry Counter Exceed | IBV_WC_RETRY_EXC_ERR | Requester | RC | Error | |
RNR Retry Counter Exceeded | IBV_WC_RNR_RETRY_EXC_ERR | Requester | RC | Error | |
Aborted Error | IBV_WC_REM_ABORT_ERR | Responder | UC | None | |
Fatal Error | IBV_WC_FATAL_ERR | Both | All | Error | |
Response Timeout Error | IBV_WC_RESP_TIMEOUT_ERR | Unknown | All | Error | |
General Error | IBV_WC_GENERAL_ERR | Unknown | All | Error? | |
Local EE Context Operation Error | IBV_WC_LOC_EEC_OP_ERR | RD | |||
Local RDD Violation Error | IBV_WC_LOC_RDD_VIOL_ERR | RD | |||
Remote Invalid RD Request | IBV_WC_REM_INV_RD_REQ_ERR | RD | |||
Invalid EE Context Number | IBV_WC_INV_EECN_ERR | RD | |||
Invalid EE Context State | IBV_WC_INV_EEC_STATE_ERR | RD |
2.1 Success (IBV_WC_SUCCESS)
Work Request が成功したことを示す。 これはエラーではない。 そのため QP をエラーに落とさない。
2.2 Local Length Error (IBV_LOC_LEN_ERR)
Local Length Error は 2 種類の原因で発生する。
1 つ目は responder が SEND オペレーションを受信した時、Receive Queue に登録してあった Receive WR のバッファサイズが受信メッセージの長さよりも小さいことが原因の場合である。 QP が SRQ を使っている場合にも、SRQ の Receive WR のバッファサイズが小さいと発生する。
2 つ目は requester が送信するメッセージ長が InfiniBand の仕様上の上限 231 バイトを越えるか、また HCA の実機のメッセージ長の上限を超えたことが原因の場合である。 また requester と responder で別の HCA カードを挿している場合、requester 側のメッセージ長の上限よりも responder 側の上限が小さい場合が考えられる。 この場合に、responder が自身のメッセージ長上限を超越える SEND オペレーションを受信した時にエラーが発生する。 理論上は RDMA WRITE with Immediate オペレーションでも発生することがある。 ただし非同期エラー(Invalid Request Local Work Queue Error; IBV_EVENT_QP_REQ_ERR)になる可能性が高い。
メッセージの上限は ibv_query_port() によって取得できるポート属性の max_msg_sz で確認できる。 また ibv_devinfo に -v オプションを与えて実行することでも確認可能である。 ちなみに Mellanox ConnectX-3 ではこの値は 0x40000000 (=1G) バイトとなっている。
(どちらの場合でも) RC サービスにおいてこのエラーが responder 側に出た場合、NAK-Invalid Request を返すので、(NAK がパケットロスを起こさなければ) requester は Remote Invalid Request Error を発生させる。
2.3 Local QP Operation Error (IBV_WC_LOC_QP_OP_ERR)
QP にエラーが発生した場合に起きる。 Send WR や Receive WR のパラメータが不正だった場合(オペコードとか)に発生する。
RC サービスにおいてこのエラーが responder 側に出た場合、NAK-Remote Operation Error を返すので、(NAK がパケットロスを起こさなければ) requester は Remote Operation Error を発生させる。
2.4 Local Protection Error (IBV_WC_LOC_PROT_ERR)
Send WR や Receive WR 内の L_Key が Memory Region と合致しない場合に発生する。 Local Protection Error が出る正確な条件は 5.1 も参照のこと。
RC サービスにおいてこのエラーが responder 側に出た場合、NAK-Remote Operation Error を返すので、(NAK がパケットロスを起こさなければ) requester は Remote Operation Error を発生させる。
2.5 Work Request Flushed Error (IBV_WC_WR_FLUSH_ERR)
QP が Error ステートになった場合、SQ と RQ 内の WR は CQ に吐き出される。 この時、吐き出された WR にはこのエラー番号が設定される。 また QP が Error ステートになった後に、ibv_post_send() や ibv_post_recv() で WR を登録した場合、直ちに CQ に完了エラーとして積まれるが、この時もこのエラー番号が設定される(ただし SRQ に紐付けられている QP が Error ステートになっても、SRQ の Receive WR はそのままなことに注意)。
また QP が SQE ステートになった場合、SQ 内の WR は CQ に吐き出される。 この時、吐き出された WR はこのエラー番号が設定される。 また QP が SQE ステートになった後に、ibv_post_send() で WR を登録した場合、直ちに CQ に完了エラーとして積まれるが、この時もこのエラー番号が設定される。
この完了エラーは QP をエラーにする原因そのものではなく、疑似エラーである。 そのため この完了エラーは QP をエラーに落とさない。
2.6 Local Access Error (IBV_WC_LOC_ACCESS_ERR)
RDMA WRITE with Immediate オペレーションを受けた時に R_Key が Memory Region と合致しない場合に発生する。 ただし完了エラーではなく非同期エラー(Local Access Violation Work Queue Error; IBV_EVENT_QP_ACCESS_ERR) として発生する場合もある。 Remote Protection Error が出る正確な条件は 5.1 も参照のこと。
RC サービスにおいてこのエラーが responder 側に出た場合、NAK-Remote Access Error を返すので、(NAK がパケットロスを起こさなければ) requester は Remote Access Error を発生させる。
2.7 Bad Response Error (IBV_WC_BAD_RESP_ERR)
Responder から返される応答メッセージ(ACK or NAK)を requester が解析した時に、不正なオペコードが含まれていた場合に発生する。
トランスポート層の障害によってのみ発生し、上位のプログラムのバグでは発生しえない。
2.8 Remote Invalid Request Error (IBV_WC_REM_INV_REQ_ERR)
Responder 側にエラーが発生し、NAK-Invalid Request が返ってきた結果を報告するエラーである。 具体的には以下が原因で発生する。
- Responder が受信したリクエストパケット内のオペコードが不正。
- Responder が受信したリクエストパケット内のペイロードの長さが不正。
- Responder が max_msg_sz を越える長さのメッセージを受信した。
- Responder が受信した SEND オペレーションのデータが Receive WR のバッファサイズを越えた。
- RDMA READ や ATOMIC オペレーションのリクエストを QP に設定された同時処理数の属性(max_dest_rd_atomic)以上に受け取った。 詳細は「InfiniBand の再送制御を理解する」を参照のこと。
- ATOMIC オペレーションが不正境界。
1. と 2. はトランスポート層の障害によってのみ発生し、上位のプログラムのバグでは発生しえない。
2.9 Remote Access Error (IBV_WC_REM_ACCESS_ERR)
Responder 側にエラーが発生し、NAK-Remote Access Error が返ってきた結果を報告するエラーである。 具体的には以下が原因で発生する。
- RDMA WRITE、RDMA READ、ATOMIC オペレーションで R_Key が Memory Region と合致しない場合に発生する。 正確な条件は 5.1 も参照のこと。
2.10 Remote Operation Error (IBV_WC_REM_OP_ERR)
Responder 側にエラーが発生し、NAK-Remote Operation Error が返ってきた結果を報告するエラーである。 以下の状況で発生する。
- Responder に Local QP Operation Error が発生
- Responder に Local Protection Error が発生
2.11 Transport Retry Counter Exceed (IBV_WC_RETRY_EXC_ERR)
Local ACK Timeout による再送が上限を越えた場合に発生する。 詳細は「InfiniBand の再送制御を理解する」を参照のこと。
2.12 RNR Retry Counter Exceeded (IBV_WC_RNR_RETRY_EXC_ERR)
RNR NAK Retry による再送が上限を越えた場合に発生する。 詳細は「InfiniBand の再送制御を理解する」を参照のこと。
2.13 Aborted Error (IBV_WC_REM_ABORT_ERR)
UC サービスはパケットロスが起きた時でも再送をしないが、QP を Error ステートに落とすこともしない。 RQ から取り出した Receive WR はリセットして、次のメッセージの受信用に再利用する。 しかし SRQ から取り出した Receive WR は、HCA の実装によっては SRQ に戻せない場合がある。 そのような実装では、処理を中断した Receive WR を「アボート」する。 この完了エラーは QP をエラーに落とさない。 ユーザープログラムは ibv_poll_cq() でアボート完了エラーを受け取った場合には、プログラムを停止させずに処理を続ける必要がある。
このエラーが responder 側に発生しても、requester は感知しない。
2.14 Fatal Error (IBV_WC_FATAL_ERR)
QP に対して致命的な異常が発生したことを通知する。 発生条件は具体的に規定されていない。
2.15 Response Timeout Error (IBV_WC_RESP_TIMEOUT_ERR)
InfiniBand の仕様ではなく、InfiniBand Verbs が内部的に定義しているエラーである。 現在はカーネルによって IB ドライバがアンロードされ、応答を待っている WQE を CQ に移す際にこのエラーが出現することがある。
現在はユーザーランドプログラムが見ることはない。
2.16 General Error (IBV_WC_GENERAL_ERR)
分類できないエラーはこのエラー番号で報告される。 例えば RMPP MAD の送信で後続パケットが送れない場合に発生する。
このエラーが responder に発生した場合の、requester の挙動は不明。
3. 非同期エラー(Asynchronous Error)
ibv_get_async_event() で返される非同期エラーは struct ibv_async_event
構造体を持っている。
この中で event_type は enum ibv_event_type
列挙子型を持ち、非同期エラーの種類を報告している。
struct ibv_async_event { union { struct ibv_cq *cq; struct ibv_qp *qp; struct ibv_srq *srq; int port_num; } element; enum ibv_event_type event_type; };
enum ibv_event_type
列挙子型で区別される非同期エラーの種類は以下の表のようになる。
発生箇所 | イベント名 | 値 | Services | Affiliated / Unaffiliated |
Event / Error |
---|---|---|---|---|---|
QP | Local Work Queue Catastrophic Error | IBV_EVENT_QP_FATAL | All | Affiliated | Error |
Invalid Request Local Work Queue Error | IBV_EVENT_QP_REQ_ERR | RC | Affiliated | Error | |
Local Access Violation Work Queue Error | IBV_EVENT_QP_ACCESS_ERR | RC | Affiliated | Error | |
Communication Established Event | IBV_EVENT_COMM_EST | RC/UC/RD (UD/Raw)* |
Affiliated | Event | |
Send Queue Drained Event | IBV_EVENT_SQ_DRAINED | All** | Affiliated | Event | |
Path Migrated Event | IBV_EVENT_PATH_MIG | All *** | Affiliated | Event | |
Path Migration Request Error | IBV_EVENT_PATH_MIG_ERR | All *** | Affiliated | Error | |
Last WQE Reached Event | IBV_EVENT_QP_LAST_WQE_REACHED | RC/UD/UC | Affiliated | Event | |
CQ | CQ Error | IBV_EVENT_CQ_ERR | All | Affiliated | Error |
SRQ | SRQ Catastrophic Error | IBV_EVENT_SRQ_ERR | All | Affiliated | Error |
SRQ Limit Reached Event | IBV_EVENT_SRQ_LIMIT_REACHED | RC/UD/UC | Affiliated | Event | |
Port | Port Active | IBV_EVENT_PORT_ACTIVE | Unaffiliated | Event | |
Port Error | IBV_EVENT_PORT_ERR | Unaffiliated | Error | ||
LID Change | IBV_EVENT_LID_CHANGE | Unaffiliated | Event | ||
P_Key Change | IBV_EVENT_PKEY_CHANGE | Unaffiliated | Event | ||
SM Change | IBV_EVENT_SM_CHANGE | Unaffiliated | Event | ||
Client Reregistration | IBV_EVENT_CLIENT_REREGISTER | Unaffiliated | Event | ||
GID Table Change | IBV_EVENT_GID_CHANGE | Unaffiliated | Event | ||
CA | Local Catastrophic Error | IBV_EVENT_DEVICE_FATAL | Unaffiliated | Error |
** Unreliable は再送を行わないので、意味があるのは RC だけである。
*** Connection (RC、UC) だけで意味がある。
3.1 Catastrophic Error
Local Work Queue Catastrophic Error(IBV_EVENT_QP_FATAL)、CQ Error(IBV_EVENT_CQ_ERR)、SRQ Catastrophic Error(IBV_EVENT_SRQ_ERR) の 3 種類は、オブジェクトに破壊的なエラーが発生したことを通知する。 この破壊的エラーが発生したオブジェクトは、再利用できず直ちに ibv_destroy_qp()、ibv_destroy_cq()、ibv_destroy_srq() で回収する必要がある。
また Local Catastrophic Error(IBV_EVENT_DEVICE_FATAL) は HCA に致命的な異常が発生したことを通知する。 この異常が発生したユーザーコンテキストは利用を中断する必要がある。
3.1.1 Local Work Queue Catastrophic Error (IBV_EVENT_QP_FATAL)
QP に致命的なエラーが発生したことを通知する。 QP 自身に致命的なエラーが生じた場合以外に、ibv_create_qp() で作成時に関連付けられた CQ に CQ Error や、SRQ に SRQ Catastrophic Error が発生した場合にもこのエラーが起きる。
このエラーが発生すると QP は一応 Error ステートになる。 ただし他の原因で Error ステートに遷移した場合と異なり、CQ から CQE が取り出せるという保証はない。 そのため QP がこのエラーになった場合、ibv_destroy_qp() で回収すべきであろう。
3.1.2 CQ Error (IBV_EVENT_CQ_ERR)
CQ に致命的なエラーが発生したことを通知する。 ユーザープログラムが CQ へ追加される CQE が最大数をオーバーフローした場合に発生する。 これ以外にも CQ に異常が発生した場合には、このエラーが発生するとされる。
CQ がこのエラーになった以降は、CQ に新しい CQE を積んだり ibv_poll_cq() で取り出すことはできなくなる。 つまり ibv_destroy_cq() 以外の操作ができなくなる。
CQ がこのエラーになった場合、この CQ を ibv_create_qp() で qp_init_attr->send_cq、qp_init_attr->recv_cq に指定している QP は全て連鎖的に Local Work Queue Catastrophic Error となる。
3.1.3 SRQ Catastrophic Error (IBV_EVENT_SRQ_ERR)
SRQ に致命的なエラーが発生したことを通知する。 このエラーが起こる具体的な事象は定義されていない。
SRQ がこのエラーになった以降は、SRQ に ibv_post_srq_recv() で新しい Receive WR を登録することや、SRQ から Receive WR を取り出すことができなくなる。 つまり ibv_destroy_srq() 以外の操作ができなくなる。
SRQ がこのエラーになった場合、この SRQ を ibv_create_qp() で qp_init_attr->srq に指定している QP は全て連鎖的に Local Work Queue Catastrophic Error となる。
3.1.4 Local Catastrophic Error (IBV_EVENT_DEVICE_FATAL)
HCA に何らかの致命的な異常が発生したことを意味する。 これが通知された場合、ユーザーコンテキストに属する全てのオブジェクトは以降正常に使えるという保証がなくなる。 すみやかにユーザーコンテキストに所属する全てのオブジェクトを破壊し、ユーザーコンテキストも ibv_close_device() で閉じるのが望ましい。 ただし、それも成功しない可能性がある。
3.2 Normal Error
3.2.1 Invalid Request Local Work Queue Error (IBV_EVENT_QP_REQ_ERR)
Responder がトランスポート層に異常を発見した場合に発生する。 具体的には以下が原因で発生する。
- Responder が受信したリクエストパケット内のオペコードが不正。
- Responder が受信したリクエストパケット内のペイロードの長さが不正。
- Responder が max_msg_sz を越える長さのメッセージを受信した。
3.2.2 Local Access Violation Work Queue Error (IBV_EVENT_QP_ACCESS_ERR)
Responder が RDMA WRITE with Immediate オペレーション以外の RDMA 操作を受信し、異常となった場合に発生する。 具体的には以下が原因で発生する。
- ATOMIC オペレーションが不正境界。
- RDMA READ や ATOMIC オペレーションのリクエストを QP に設定された同時処理数の属性(max_dest_rd_atomic)以上に受け取った。 詳細は「InfiniBand の再送制御を理解する」を参照のこと。
- RDMA WRITE without Immediate、RDMA READ、ATOMIC オペレーションで R_Key が Memory Region と合致しない。
- RDMA WRITE with Immediate オペレーションで R_Key が Memory Region と合致しない(場合によって)
3.3 プログラムによって利用できるイベント
3.3.1 Communication Established Event (IBV_EVENT_COMM_EST)
この非同期イベントは、「InfiniBand の QP ステートの遷移を理解する」で述べたように QP を RTR ステートに遷移後に最初のパケットを受信したことを通知する。 受信するパケットは SEND/RDMA WRITE/RDMA READ/ATOMIC 操作要求のいずれでもよい。 RTR ステートのまま複数のパケットを受信しても 2 度目以降は発生しない。 ただしステートを遷移させ、再び RTR ステートに変えた場合はまた発生する。
3.3.2 Send Queue Drained Event (IBV_EVENT_SQ_DRAINED)
この非同期イベントは、「InfiniBand の QP ステートの遷移を理解する」で述べたように QP が SQD ステートに遷移後に送信中の全ての Send WR に ACK が返ってきたことを通知する。 プログラムがこのイベントを拾うことで、QP の送信メッセージが停止したことを確認できる。 ibv_modfiy_qp() で SQD ステートから SQD ステートへ遷移することで、RTR や RTS で設定した属性の一部を受信を停止せずに変更することが可能である。
3.3.3 Last WQE Reached Event (IBV_EVENT_QP_LAST_WQE_REACHED)
この非同期イベントは、「InfiniBand の QP ステートの遷移を理解する」で述べたように SRQ に紐付けられた QP が Error ステートに落ちた後に、処理中の WQE の CQ への追加が完了したことを通知する。 発生条件は以下の 2 つである。
- 最後の WQE が CQ に CQE として積まれたタイミングで発生する。 ただし RECV を 1 度も受信したことがない QP がエラーになった場合は発生しないかもしれない。
- SRQ の WQE が尽きて空になった後に、その SRQ に紐付けられた QP がエラーになった場合に発生する。
ただし上記の条件を満たしても、QP が Local Catastrophic Error によって Error ステートに落ちた場合には、この非同期イベントは発生しないかもしれない。
3.3.4 SRQ Limit Reached Event (IBV_EVENT_SRQ_LIMIT_REACHED)
この非同期イベントは、チュートリアルで述べたように SRQ の WQE の残量が SRQ Limit を下回ったことを通知する。
ただし 1 度 IBV_EVENT_SRQ_LIMIT_REACHED 非同期イベントが発生すると、SRQ Limit は無効化されるので、もう 1 度使うには ibv_modify_srq() で再設定する必要がある。
ibv_modify_srq() は srq_attr_mask
に IBV_SRQ_MAX_WR を設定するには、HCA が IBV_DEVICE_SRQ_RESIZE をサポートしている必要がある。
しかし IBV_SRQ_LIMIT は IBV_DEVICE_SRQ_RESIZE サポートは不要である。
3.4 Path Migration に関係するもの
3.4.1 Path Migrated Event (IBV_EVENT_PATH_MIG)
通信パスがalternate pathに切り替わったことを通知する。
3.4.2 Path Migration Request Error (IBV_EVENT_PATH_MIG_ERR)
通信パスをalternate pathに切り替えようとしてエラーが発生したことを通知する。
3.5 ポートのリンク状態に関係するもの
Port Active Event(IBV_EVENT_PORT_ACTIVE) と Port Error(IBV_EVENT_PORT_ERR) は HCA のポートのリンク状態に変化があった時に発生する。
この 2 つ非同期エラーは HCA がこれらを報告する機能を実装している場合のみ発生する。 機能が実装されている場合、ibv_query_port() の中の port_cap_flags に IBV_DEVICE_PORT_ACTIVE_EVENT の属性がセットされていることで報告される。
3.5.1 Port Active Event (IBV_EVENT_PORT_ACTIVE)
ポートのリンク状態が通信不能から通信可能なステータスに遷移したことを通知する。 これはポートのリンク状態は物理的な結線がつながっただけではなく、Subnet Manager から LID の割り当てまでが完了した状態である。
このイベントの到着後は ibv_query_port() の state が、IBV_PORT_ACTIVE か IBV_PORT_ACTIVE_DEFER になる。
3.5.2 Port Error(IBV_EVENT_PORT_ERR)
ポートのリンク状態が通信可能から通信不能なステータスに遷移したことを通知する。
この非同期エラーが発生しても QP のステートはそのままである。
このイベントの到着後は ibv_query_port() の state が、IBV_PORT_ACTIVE か IBV_PORT_ACTIVE_DEFER 以外になる。
3.7 Subnet Manager に関係するもの
LID Change(IBV_EVENT_LID_CHANGE)、P_Key Change(IBV_EVENT_PKEY_CHANGE)、SM Change(IBV_EVENT_SM_CHANGE)、Client Reregistration(IBV_EVENT_CLIENT_REREGISTER)、GID Table Change(IBV_EVENT_GID_CHANGE) は Subnet Manager がポートへの設定の変更した際に発生する。
3.6.1 LID Change (IBV_EVENT_LID_CHANGE)
この非同期イベントは Subnet Manager がポートの LID を変更した時に発生する。 HCA のポートの LID は初期状態では 0 だが、Subnet Manager がサブネットを構成して LID を割り当てたタイミングでもこの非同期イベントは発生する。
この非同期イベント発生後は、Base port LID が変更されているので、ibv_query_port() の lid を確認すべきである。 またポートに属する各種情報は取得し直す必要がある。
Subnet Manager が停止した場合でも、いったんポートに割り当てられた LID は維持される。
3.6.2 P_Key Change (IBV_EVENT_PKEY_CHANGE)
この非同期イベントは Subnet Manager が Partition Key Table を変更した時に発生する。
この非同期イベント発生後は、Partition Key Table が変更されているので、ibv_query_pkey を確認すべきである。
3.6.3 SM Change (IBV_EVENT_SM_CHANGE)
この非同期イベントは Subnet Manager がマイグレーションした時に発生する。
この非同期イベント発生後は、ポートの SM LID が変更されているので、ibv_query_port() の sm_lid を確認すべきである。
3.6.4 Client Reregistration (IBV_EVENT_CLIENT_REREGISTER)
この非同期イベントは Subnet Manager が再起動などによりポートの情報を再登録した場合に発生する。
この非同期イベント発生後は、ポートに属する各種情報は取得し直す必要がある。
この非同期イベントは HCA が Client Reregistration をサポートしている場合のみ発生する。
Client Reregistration がサポートされている場合、ibv_query_port() の中の port_cap_flags に 1U << 25
の属性がセットされていることで報告される。
Mellanox ConnectX-3 ではこの機能はサポートされている。
3.6.5 GID Table Change (IBV_EVENT_GID_CHANGE)
この非同期イベントは Subnet Manager がポートの GID Table を変更した時に発生する。
この非同期イベント発生後は、GID Table が変更されているので、ibv_query_gid() を確認すべきである。
4. パターンごとの発生するエラー
4.1 Send Work Request または Receive Work Request の登録エラー
ibv_post_send() を使って Send Queue(SQ) に Send Work Request が登録可能かどうかは、QP のステートに依存する。
- Reset、Init、RTR ステートの場合は仕様上 Immediate Error となる。
- RTS、SQD ステートの場合は登録が成功する。ただし SQ の最大 WQE 数を越える場合は Immediate Error となる。 (ibv_post_send() は -1 を返し、errno が ENOMEM に設定される。
- Error、SQD ステートの場合は、Work Request はそのまま Flushed Error (IBV_WC_WR_FLUSH_ERR) の完了エラーとして CQ に積まれる。
ibv_post_recv() を使って Receive Queue(RQ) に Send Work Request が登録可能かどうかは、QP のステートに依存する。
- Reset ステートの場合は仕様上 Immediate Error となる。
- Init、RTR、SQD、SQE ステートの場合は登録が成功する。ただし RQ の最大 WQE 数を越える場合は Immediate Error となる。 (ibv_post_recv() は -1 を返し、errno が ENOMEM に設定される。
- Error ステートの場合は、Work Request はそのまま Flushed Error (IBV_WC_WR_FLUSH_ERR) の完了エラーとして CQ に積まれる。
この操作で QP のステートが変わることはない。
QP が Reset、Init、RTR ステートの時に ibv_post_send() を呼び出した場合と、Reset ステートの時に ibv_post_recv() を呼び出した場合には、仕様上 Immediate Error となる。 しかし実機では Immediate Error とならない場合がある。 その場合、登録に成功したように振舞う場合と、Local QP Operation Error (IBV_WC_LOC_QP_OP_ERR) となる場合がある。
4.2 Requester が Send Work Request 処理時にエラー
Send WQE の内容に誤りがあった場合にはエラーとなる。
- L_Key が Memory Region と合致しない場合は、Local Protection Error (IBV_WC_LOC_PROT_ERR) 完了エラーが発生する。
- それ以外の場合は Local QP Operation Error (IBV_WC_LOC_QP_OP_ERR) 完了エラーとなる。 それ以外のパターンは不正なオペコードの指定(opcode)、最大数を超える S/G 組を指定(num_sge)などである。
エラー発生時には RC サービスの場合は Error ステートに落ちる。 UC/UD サービスの場合は SQE ステートに落ちる。
4.3 Responder が受信不能
Responder はリクエストとなるパケットに含まれるパラメータが条件を満たさない場合、QP には渡さずにパケットを破棄する。
- 指定の QP 番号の QP がない
- QP のサービスタイプが不一致
- QP が受信可能なステート(RTR、RTS、SQE、SQD)以外
- P_Key が不一致
- 設定されたポート以外からパケットが侵入
- パケットの DLID と QP に設定された DLID が不一致
- UD サービスの場合、Q_Key が不一致
パケットの破棄で responder の QP はステートが変わることはない。
4.4 Responder QP でリクエスト受信時にエラー
Responder がリクエストパケットを受信した場合、オペレーション種類ごとに異なるエラーが発生する。
4.4.1 SEND
SEND オペレーションは RC/UC/UD サービスで利用できる。 SEND オペレーションのメッセージを受信した場合、responder のパターンによって以下のような完了エラーが発生する。 また responder の QP は Error ステートに落ちる。
RC サービスの場合は、これらのエラーが生じた場合は NAK が返されて、requester にも完了エラーが発生し、QP は Error ステートに落ちる。
エラー | Responder に生じるエラー | Requester に生じるエラー |
---|---|---|
L_Key が Memory Region と合致しない | Local Protection Error(IBV_WC_LOC_PROT_ERR) 完了エラー | Remote Operation Error(IBV_WC_REM_OP_ERR) 完了エラー |
Receive WR バッファ長の不足 | Local Length Error(IBV_LOC_LEN_ERR) 完了エラー(*1) | Remote Invalid Request Error(IBV_WC_REM_INV_REQ_ERR) 完了エラー |
メッセージ最大長を超過 | Local Length Error(IBV_LOC_LEN_ERR) 完了エラー(*2) | Remote Invalid Request Error(IBV_WC_REM_INV_REQ_ERR) 完了エラー |
それ以外 | Local QP Operation Error(IBV_WC_LOC_QP_OP_ERR) 完了エラー | Remote Operation Error(IBV_WC_REM_OP_ERR) 完了エラー |
- (*1) UD サービスの場合は受信可能なメッセージ長を越えた場合でもエラーとはならない。 パケットを破棄するだけとする。
- (*2) UD サービスは 1 パケットしかないので、メッセージ最大長を超過することはない。
4.4.2 RDMA WRITE
RDMA WRITE オペレーションは RC/UD サービスで利用できる。 RDMA WRITE オペレーションのメッセージを受信した場合、responder のパターンによって以下のような完了エラー・非同期エラーが発生する。 また responder の QP は Error ステートに落ちる。
RC サービスの場合は、これらのエラーが生じた場合は NAK が返されて、requester にも完了エラーが発生し、QP は Error ステートに落ちる。
エラー | Responder に生じるエラー | Requester に生じるエラー |
---|---|---|
R_Key が Memory Region と合致しない | Local Access Error(IBV_WC_LOC_ACCESS_ERR) 完了エラー Local Access Violation Work Queue Error(IBV_EVENT_QP_ACCESS_ERR) 非同期エラー |
Remote Access Error(IBV_WC_REM_ACCESS_ERR) 完了エラー |
メッセージ最大長を超過 | Local Length Error(IBV_LOC_LEN_ERR) 完了エラー Invalid Request Local Work Queue Error(IBV_EVENT_QP_REQ_ERR) 非同期エラー |
Remote Invalid Request Error(IBV_WC_REM_INV_REQ_ERR) 完了エラー |
それ以外 | Local QP Operation Error(IBV_WC_LOC_QP_OP_ERR) 完了エラー Invalid Request Local Work Queue Error(IBV_EVENT_QP_REQ_ERR) 非同期エラー |
Remote Operation Error(IBV_WC_REM_OP_ERR) 完了エラー |
RDMA WRITE without Immediate オペレーションの場合、responder は非同期エラーのみが発生する。 しかし RDMA WRITE with Immediate オペレーションの場合、responder に生じるのは完了エラーと非同期エラーの場合の2通りが考えられる。 詳細は 5.2 を参照のこと。
4.4.3 RDMA READ、ATOMIC Operations
RDMA READ、ATOMIC Operations は RC サービスで利用できる。 RDMA READ、ATOMIC Operations のメッセージを受信した場合、responder のパターンによって以下のような非同期エラーが発生する。 また responder の QP は Error ステートに落ちる。
RC サービスの場合は、これらのエラーが生じた場合は NAK が返されて、requester にも完了エラーが発生し、QP は Error ステートに落ちる。
エラー | Responder に生じるエラー | Requester に生じるエラー |
---|---|---|
R_Key が Memory Region と合致しない | Local Access Violation Work Queue Error (IBV_EVENT_QP_ACCESS_ERR) 非同期エラー | Remote Access Error (IBV_WC_REM_ACCESS_ERR) 完了エラー |
メッセージ最大長を超過 | Invalid Request Local Work Queue Error (IBV_EVENT_QP_REQ_ERR) 非同期エラー | Remote Invalid Request Error (IBV_WC_REM_INV_REQ_ERR) 完了エラー |
同時受信数が max_dest_rd_atomic を超過 | Local Access Violation Work Queue Error (IBV_EVENT_QP_ACCESS_ERR) 非同期エラー | Remote Invalid Request Error (IBV_WC_REM_INV_REQ_ERR) 完了エラー |
ATOMIC オペレーションの境界に沿わない | Local Access Violation Work Queue Error (IBV_EVENT_QP_ACCESS_ERR) 非同期エラー | Remote Invalid Request Error (IBV_WC_REM_INV_REQ_ERR) 完了エラー |
それ以外 | Invalid Request Local Work Queue Error (IBV_EVENT_QP_REQ_ERR) 非同期エラー | Remote Operation Error (IBV_WC_REM_OP_ERR) 完了エラー |
5. その他のトピックス
5.1 Local/Remote Protection Error の考え方
Local protection error は Send WR や Receive WR に設定した scatter/gather エントリが事前に ibv_reg_mr() で登録した memory region と合致しない場合に発生する。
Scatter/gather エントリの 1 組は struct ibv_sge
構造体で渡すことになる。
struct ibv_sge { uint64_t addr; uint32_t length; uint32_t lkey; };
実際に local protection error は以下のパターンで生じる。
- S/G エントリが memory region として登録されていない。
- S/G エントリが memory region として登録した範囲からはみ出している。
- L_Key が memory region と一致しない。
- オペレーションの要求する memory region で登録したアクセス権限と一致しない。
Remote protection error は、requester で登録した RDMA オペレーションがパケットに埋め込まれて responder に送信され、responder で登録した memory region と合致しない場合に発生する。
比較されるのは struct ibv_send_wr
構造体の rkey で示される R_Key、remote_addr のアドレス、バイト長である。
バイト長は明示的に指定するのではなく、Send WR で指定する scatter/gather エントリの length を足したものがバイト長になる。
struct ibv_send_wr { union { struct { uint64_t remote_addr; uint32_t rkey; } rdma; } wr; };
Remote protection error も 1.〜4. のパターンで生じる。
1. 〜 4. が全部 local/remote protection error として丸められるのは、やや大雑把な感じがするがこれは protection domain、memory region の内部実装から来ていると思われる。 Memory region は概念的には Fig 2 のようにメモリ空間をカバーする範囲を登録しておき、アドレスから memory region を決定するのだが、実際に memory region を木構造で管理したりすると探索に時間がかかる。

そこで実際の memory region の探索はアドレスからではなく、L_Key や R_Key を用いて行う。 Memory region と QP は protection domain 内に作成されることは概念編で説明したが、protection domain 内には memory region を登録する表がある。 ibv_reg_mr() はこの表の空きエントリに挿入するのだが、その際に表のインデックス番号を L_Key や R_Key の一部に埋め込んでおく。 検索は L_Key や R_Key から表のインデックス番号をデコードして特定する。

上記のような実装をとるため 1. は表にエントリがあるかどうかのチェック、2. 〜 4. はエントリ内のパラメータを使った比較となり、一律なエラーとして扱われている。
5.2 RDMA WRITE with Immediate の特殊事情
大概のエラーは完了エラーで返すか非同期エラーで返すかが決まっている中で、RDMA WRITE with Immediate だけは状況に応じて完了エラーが出たり非同期エラーが出たりする。 これには以下のような事情がある。
RC/UC は 1 つの Send WR が 1 つのメッセージとして送信されるが、1 メッセージの最大長は 231 であり、MTU を越えるサイズの場合は複数のパケットに分割して送信される。 しかし responder から見ると、自身に送られてきたメッセージが RDMA WRITE オペレーションなのか、RDMA WRITE with Immediate オペレーションなのかを判定するには最後のパケットの到着を待たなくてはならない。
オペレーション | メッセージ長 | 最初のパケット | 真ん中のパケット | 最後のパケット |
---|---|---|---|---|
RDMA WRITE | MTU 以下 | RDMA WRITE Only | ||
RDMA WRITE with Immediate | MTU 以下 | RDMA WRITE Only with Immediate | ||
RDMA WRITE | MTU 超過 | RDMA WRITE First | RDMA WRITE Middle | RDMA WRITE Last |
RDMA WRITE with Immediate | MTU 超過 | RDMA WRITE First | RDMA WRITE Middle | RDMA WRITE Last with Immediate |
一方、最初のパケットを受け取った段階でエラーだと分かることが多い。 例えば R_Keyは最初のパケットに含まれているので Remote Access Error かどうかは分かる。 この場合、RDMA WRITE オペレーションか RDMA WRITE with Immediate オペレーションなのかを判別するためだけに、最後のパケットまで待つのは効率が悪い。 HCA は実装によって、判定ができない状況では RDMA WRITE (without Immediate) オペレーションだとみなして非同期エラーを投げることになる。
これが RDMA WRITE with Immediate オペレーションが完了エラーになったり非同期エラーになったりする理由である。