・ロックの優先順位

  dev(lock) → qp → dev(schedule) → srq → pd → cq → dev(wq)

  mad.c の中で ib_post_send の外側で spin_lock_irqsave している。
  セマフォではなく spin_lock を使う必要がある。

	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
	if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
		ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,
				   &bad_send_wr);
		list = &qp_info->send_queue.list;
	} else {
		ret = 0;
		list = &qp_info->overflow_list;
	}

	if (!ret) {
		qp_info->send_queue.count++;
		list_add_tail(&mad_send_wr->mad_list.list, list);
	}
	spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);

・HCA & switch エミュレーション

   pib の HCA エミュレーションは IB の定義するパケットを UDP パケットとして送受信する。
   # CRC がない。Credit-based flow control のためのフィールドや MSN もない。

   pib のエミュレーションしている HCA 毎に 1 つのスレッドと 1 つの UDP ソケットを作成する。

  ・DR SMP                仕様通りの実装。
  ・Unicast               LID が分かれれば直接送信する。
  ・Multicast             easy switch に投げてフォワーディングする。

  実機の IB は HCA が接続された物理的なリンクを辿って送信を行うが、pib では通常のユニ
  キャスト通信は easy switch をバイパスして、直接通信相手のポートのソケットへ送信する。

  ただしマルチキャストと DR SMP MAD は、pibnetd 経由で行う。
  
・MR

  MR の L_Key と R_Key は PD に設けられた mr_table[] のインデックス値とする。
  ただし配列のインデックスとして使うのは下位ビットで、上位ビットは PD ごと
  に設定する乱数値とする。

・GID

  IB は 64-bit のユニークアドレス (EUI-64) が必要。

  マルチホストモードでは、複数のホスト間で衝突しない値をつける必要がある。

  このためにホスト内で見つかった最初のイーサーネット機器の MAC アドレス (EUI-48) を借用し、
  これを上位につめた 64 ビットを合成する。

  0x0000         Not use
  0x0100         Easy switch (for single-host-mode)
  0x0101～0x01FF pibnetd (for multi-host-mode)
  0x0200         SystemImageGUID 
  0xyyzz         NodeGUID or PortGUID
                 - yy は 3 から始まる HCA 番号
                 - zz は 0 なら NodeGUID で、1 以上は PortGUID

・送信処理は Send Queue は submitted(未送信)、sending(送信中)、waiting(ACK待ち) の 3 つのキューで処理する。

  - ibv_post_send は submitted queue につなげる。

    - QP が RESET または INIT 以外なら可能。

  - バックグラウンド処理が submitted queue から Send WR を取り出して、sending queue につなげる。
    これは QP が RTS の場合だけ実行する。

    - 先行する RMDA READ、Atomic 操作がある場合、SEND_FENCE がついている sending queue にはつなげない。
    - 同時実行中の RMDA READ、Atomic 操作 が上限を越えると  sending queue にはつなげない。

  - Sending queue の先頭からパケットを送信する。
    これは QP が RTS または SQD の場合だけ実行する。

  - 1回分の送信が完了すれば sending キューのエントリは waiting キューに送る。
    - ACK/NAK がないまま連続送信が続いた場合、waiting キューに移す。

  - QP が Send Drain(SQD) 属性になった場合は、submitted キューにあるのものは sending queue に移さない。

  - 送信が失敗(NAK受信、再送)になると wainting キューにある全エントリは sending キューに戻した上で、
    全ての未 ACK パケット分をクリアする。

  - ACK は sending キューと waiting キューにある場合の二通りが考えられる。

・輻輳制御

  ・Requester は一定数以上のリクエストパケットを送信した後は、ACK が返るまで送信を停止する。

  ・RDMA READ、Atomic 操作に関しては、いったんリトライがかかると retry_cnt を内部的に最小値にする
    という輻輳制御が入っている。以降の RDMA READ、Atomic 操作が成功される度に retry_cnt は +1 され
    る。
 
  ・RDMA READ はもう一つ工夫が必要。
