インデックスのページへ。
更新履歴
(2015.02.12) 0.4.6 pib を SEND with Invalidate、Local Invalidate、Fast Register Physical MR 操作に対応。pibnetd が正常にシャットダウンできなかったノードと再接続できないバグを取る。
(2014.11.06) 0.4.5 i386 カーネルに対応。
(2014.10.30) 0.4.4 Linux カーネル 3.17 に対応。
(2014.05.03) 0.4.1 pib を Driver Update パッケージ化。
(2014.04.07) 0.4.0 pibnetd を RPM パッケージ化。
(2014.03.20) 0.4.0 RC 通信の SEND、RDMA WRITE、RDMA READ に輻輳制御を実装。
(2014.03.11) 0.3.4 カーネルスレッドの優先度をパラメータ化。ソケットのデフォルトのバッファサイズを 16MB に。
(2014.02.27) 0.3.1 マルチホストに対応
(2014.02.07) 0.2.8 error injection と execution trace に対応
(2014.01.29) 0.2.6 IB diagnostic utilities と object inspection に対応
(2014.01.19) 0.2.1 マルチキャストと IPoIB、RDMA Communication Manager に対応
(2013.12.28) 0.1.0 Subnet Manager(OpenSM)に対応
(2013.12.11) 0.0.6 RC サービスで IBV_WR_RDMA_READ をサポート
(2013.12.09) 0.0.5 UD サービスで IBV_WR_SEND_WITH_IMM をサポート
(2013.12.06) 2013.10.7の日記から作成。
Pseudo InfiniBand HCA driver (pib)
InfiniBand のプログラムを行ったり IPoIB や SRP などの InfiniBand のソフトスタックを試すには、高価な InfiniBand HCA、ケーブル、スイッチを購入する必要があった。 そのため開発環境に InfiniBand ハードが存在しない場合や、本番環境と同規模のシステムが手に入らない場合に試験が難しい。
そこで Linux 上で動作するソフトウェアベースの Pseudo InfiniBand HCA driver (pib) を開発する。 pib は InfiniBand HCA を模擬するカーネルモジュールであり、カーネル層で IP ソケットを作って他の pib と通信する。 つまり InfiniBand over IP (IBoIP) を実現する。
pib のメリットとしては、
- お金がかからずに InfiniBand を試せる。
- 実機ではできないエラー発生時のテストなどができる(ようになる)。
逆に性能はまったくでない。 また VL などハードウェアに深く依存した機構はエミュレーションできない。
目標と現在の実装
pib は Linux カーネルモジュールとしてロードされると、指定すると疑似 HCA を展開する。 疑似 HCA はカーネル内で UDP ソケットを開き、IB パケットを UDP パケットにカプセル化し、別の pib の疑似 HCA との間で通信する。
現在のバージョン(0.4.0)はシングルホストモードとマルチホストモードの2つを持っている。
シングルホストモードでは一つのノード内でだけ動作する。 デフォルトでは 2 ポート HCA を 2 枚生成し、その全てを隠された疑似 IB スイッチに接続する。 このスイッチは Easy Switch と呼ぶことにする。 同一ノード内で Subnet Manager を起動すると、2×2 ポートと easy switch が認識され IB サブネットとして構成される。 ただし OpenSM でしか未確認。
マルチホストモードでは疑似 IB スイッチデーモンである pibnetd を使って複数のノードを接続できる。 現在の pibnetd には 32 のポートがある。
機能 | 現在の状況 | |
---|---|---|
サービス | UD | 対応済み |
RC | 対応済み | |
UD | 未対応 | |
XRC | 未対応 | |
Subnet Manager | OpenSM のデフォルトオプションのみ対応。 | |
IPoIB | 対応 | |
RDMA Communication Manager | rdma_server と rdma_client で実行を確認 | |
MPI | ||
ノード間通信 | pibnetd を使ったマルチホストモード | |
開発支援機能 |
以下のような機能を実装。
|
免責
ソースコードとビルド方法
現在のコードを以下に公開する。 過去のバージョンは ここ においておく。
- ドライバー
- libpib ユーザープラグイン
- pibnet
また開発状況は https://github.com/nminoru/pib で公開する。
x86_64 版の CentOS 6.5 で開発しており、x86_64 の RHEL6 または CentOS 6 でしか動作しないと思われる。 動作環境のためには以下のパッケージが必要。
- rdma パッケージ、libibverbs パッケージ、opensm パッケージが必要。
- カーネルモジュールをビルドするので kernel-devel パッケージが必要。
- libpib-x.y.z-1.el6.src.rpm をビルドするためには libibverbs-devel パッケージが必要。
- ibv_ud_pingpong を使うには libibverbs-utils パッケージが必要。
- Mellanox 版の OFED を入れてはならない。
パッケージを使ったインストール
RHEL 6 と CentOS6 はパッケージでインストールができる。
- kmod-pib-x.y.z-1.el6.x86_64.rpm
- libpib-x.y.z-1.el6.src.rpm
- pibnetd-x.y.z-1.el6.x86_64.rpm
これを順番にインストールすればよい。
# rpm -ihv kmod-pib-x.y.z-1.el6.x86_64.rpm # rpm -ihv libpib-x.y.z-1.el6.src.rpm # rpm -ihv pibnetd-x.y.z-1.el6.x86_64.rpm
kmod-pib-x.y.z-1.el6.x86_64.rpm は Driver Update Package に対応しており、OS が新しいバージョンの Linux カーネルをインストールした場合は、自動的にリビルドしてくる。 ただしこのパッケージをインストールするには時間がかかる。
手動でインストール
手動でインストールする場合は、以下のファイルを必要とする。
- pib-x.y.z.tar.gz
- libpib-x.y.z.tar.gz
- pibnetd-x.y.z.tar.gz
これを順番に展開しビルド & インストールする。
$ tar xvf pibnetd-x.y.z.tar.gz $ cd pibnetd-x.y.z $ make # install -m 755 -D pibnetd /usr/sbin/pibnetd # install -m 755 -D scripts/redhat-pibnetd.init /etc/rc.d/init.d/pibnetd
$ tar xvf libpib-x.y.z.tar.gz $ cd libpib-x.y.z $ make # install -m 755 -D pibnetd /usr/sbin/pibnetd # install -m 755 -D scripts/redhat-pibnetd.init /etc/rc.d/init.d/pibnetd
$ tar xvf pib-x.y.z.tar.gz $ cd pib-x.y.z $ make # install -m 644 -D libpib-rdmav2.so /usr/lib64/libpib-rdmav2.so # install -m 644 -D pib.driver /etc/libibverbs.d/pib.driver
シングルホストモードでの起動と終了
pib をロードするためには事前に InfiniBand のコア & 関連モジュールをロードする必要がある。 このために rdma スクリプト(/etc/rc.d/init.d/rdma) を起動使用する。
起動手順
rdma スクリプトは /etc/rdma/rdma.conf の設定に従うので、この内容をチェックしておくこと。 現在は IPoIB は実行可能だが、SRP/iSER/RDS は未チェックなので動かないかもしれない。 設定を no にしておいた方が安全であろう。
# Load IPoIB IPOIB_LOAD=yes # IPOIB_LOAD=no # Load SRP module SRP_LOAD=no # Load iSER module ISER_LOAD=no # Load RDS network protocol RDS_LOAD=no # Should we modify the system mtrr registers? We may need to do this if you # get messages from the ib_ipath driver saying that it couldn't enable # write combining for the PIO buffs on the card. # # Note: recent kernels should do this for us, but in case they don't, we'll # leave this option FIXUP_MTRR_REGS=no # Should we enable the NFSoRDMA service? NFSoRDMA_LOAD=yes NFSoRDMA_PORT=2050
rdma スクリプトを起動する。 これは Linux が起動する際に自動的に呼び出すようにしておいてもよい。
# /etc/rc.d/init.d/rdma start
シングルホストモードの場合、次に pib.ko をロードする。
# modprobe pib
/sys/class/infiniband/pib_0/
ができれば成功である。
rdma.conf で IPoIB を有効にした場合、ib0、ib1、ib2、ib3 というネットワークインターフェイスができているはずである。 ただし IPoIB のネットワークインターフェイスはまだダウンしている。
この状態では pib の作り出した疑似 HCA には LID が割り振られていない。 OpenSM を起動する。
# /etc/rc.d/init.d/opensm start
ibv_devinfo で見れば LID が割り当てられたことを確認できるはずである。 IPoIB のネットワークインターフェイスがアップし、通信可能になっているはずである。
終了手順
使用が終わったら pib.ko をアンロードすること。 アンロードには 10 秒以上かかることもある。
# rmmod ./pib.ko
マルチホストモードでの起動と終了
起動手順
マルチホストモードの場合、最初に pibnetd を起動する。
# /etc/rc.d/init.d/pibnetd start
pibnetd は現在はデーモンではないので、ターミナル上でずっと実行が続く。 終了する場合は、Ctrl-C を呼ぶなど pibnetd プロセスを殺せばよい。
次に pib を動かす各サイトで rdma スクリプトを起動し、その後に pib.ko をロードする。
この際に pib.ko のオプションとして addr
オプションを付け、pibnetd が動作しているホストの IP アドレスを指定する。
# /etc/rc.d/init.d/rdma start # insmod ./pib.ko addr=10.0.0.1
pib.ko は pibnetd に接続開始信号を投げ、その応答があれば成功である。 pibnetd には自身のポートに接続が成功した link up のメッセージを出力する。
pibnetd: link up port[1]: port_guid=0xc2925551e0301, sock-addr=10.0.0.2:12983 pibnetd: link up port[2]: port_guid=0xc2925551e0302, sock-addr=10.0.0.2:21977 pibnetd: link up port[3]: port_guid=0xc2925551e0401, sock-addr=10.0.0.2:41375 pibnetd: link up port[4]: port_guid=0xc2925551e0402, sock-addr=10.0.0.2:11962
# /etc/rc.d/init.d/opensm start
最後に pib.ko を起動したホストのいずれかで OpenSM を起動する。
終了手順
終了時には各ホストの pib.ko をアンロードする。
# rmmod ./pib.ko
pib.ko をアンロードしたホストとは接続が切れるので、pibnetd には以下のように link down のメッセージが出力される。
pibnetd: link down port[3]: port_guid=0xc2925551e0401, sock-addr=10.0.0.2:41375 pibnetd: link down port[4]: port_guid=0xc2925551e0402, sock-addr=10.0.0.2:11962 pibnetd: link down port[1]: port_guid=0xc2925551e0301, sock-addr=10.0.0.2:12983 pibnetd: link down port[2]: port_guid=0xc2925551e0302, sock-addr=10.0.0.2:21977
確認
Verbs
libibverbs-utils パッケージに含まれる ibv_ud_pingpong を使ってサーバ-クライアント間通信を実行してみる。 ただし閉じたホストの中でだけ。
オプションなしで ibv_ud_pingpong を起動すると、サーバとして常駐する。
$ ibv_ud_pingpong local address: LID 0x0001, QPN 0x83755e, PSN 0xa66e41: GID :: remote address: LID 0x0001, QPN 0x83755f, PSN 0xaa3e43, GID :: 4096000 bytes in 0.09 seconds = 368.94 Mbit/sec 1000 iters in 0.09 seconds = 88.82 usec/iter
サーバが常駐しているホスト(当然、localhost)をオプション指定すると、ibv_ud_pingpong はクライアントとして起動し、サーバとの間で規定回数の UD 通信を行い、サーバ・クライアントの双方で結果を表示する。
$ ibv_ud_pingpong localhost local address: LID 0x0001, QPN 0x83755f, PSN 0xaa3e43: GID :: remote address: LID 0x0001, QPN 0x83755e, PSN 0xa66e41, GID :: 4096000 bytes in 0.09 seconds = 381.30 Mbit/sec 1000 iters in 0.09 seconds = 85.94 usec/iter
InfiniBand Diagnostic
完全ではないが MAD 対応を進めたため、infiniband-diags パッケージのツールが使えるようになっている。
例えば ibnetdiscover コマンドを使うと、OpenSM が解析した InfiniBand fabric の情報が表示できる。
# ibnetdiscover # # Topology file: generated on Wed Jan 29 22:11:09 2014 # # Initiated from node 000c2925551e0300 port 000c2925551e0301 vendid=0x0 devid=0x1 sysimgguid=0xc2925551e0200 switchguid=0xc2925551e0100(c2925551e0100) Switch 4 "S-000c2925551e0100" # "Pseudo InfiniBand HCA switch" base port 0 lid 2 lmc 0 [1] "H-000c2925551e0300"[1](c2925551e0301) # "Pseudo InfiniBand HCA driver" lid 1 12xQDR [2] "H-000c2925551e0300"[2](c2925551e0302) # "Pseudo InfiniBand HCA driver" lid 4 12xQDR [3] "H-000c2925551e0400"[1](c2925551e0401) # "Pseudo InfiniBand HCA driver" lid 3 12xQDR [4] "H-000c2925551e0400"[2](c2925551e0402) # "Pseudo InfiniBand HCA driver" lid 5 12xQDR vendid=0x0 devid=0x1 sysimgguid=0xc2925551e0200 caguid=0xc2925551e0400 Ca 2 "H-000c2925551e0400" # "Pseudo InfiniBand HCA driver" [1](c2925551e0401) "S-000c2925551e0100"[3] # lid 3 lmc 0 "Pseudo InfiniBand HCA switch" lid 2 12xQDR [2](c2925551e0402) "S-000c2925551e0100"[4] # lid 5 lmc 0 "Pseudo InfiniBand HCA switch" lid 2 12xQDR vendid=0x0 devid=0x1 sysimgguid=0xc2925551e0200 caguid=0xc2925551e0300 Ca 2 "H-000c2925551e0300" # "Pseudo InfiniBand HCA driver" [1](c2925551e0301) "S-000c2925551e0100"[1] # lid 1 lmc 0 "Pseudo InfiniBand HCA switch" lid 2 12xQDR [2](c2925551e0302) "S-000c2925551e0100"[2] # lid 4 lmc 0 "Pseudo InfiniBand HCA switch" lid 2 12xQDR
また PerfMgt に対応しポート毎のパフォーマンスカウンター情報が採取できる。
いまのところ UDP ソケットの送受信情報を PortXmitData
、PortRcvData
、PortXmitPkts
、PortRcvPkts
として公開している。
パフォーマンスカウンター値を見るには、infiniband-diags パッケージに含まれている perfquery コマンドを使うとよい。
# perfquery # Port counters: Lid 1 port 1 (CapMask: 0x200) PortSelect:......................1 CounterSelect:...................0x0000 SymbolErrorCounter:..............0 LinkErrorRecoveryCounter:........0 LinkDownedCounter:...............0 PortRcvErrors:...................0 PortRcvRemotePhysicalErrors:.....0 PortRcvSwitchRelayErrors:........0 PortXmitDiscards:................0 PortXmitConstraintErrors:........0 PortRcvConstraintErrors:.........0 CounterSelect2:..................0x00 LocalLinkIntegrityErrors:........0 ExcessiveBufferOverrunErrors:....0 VL15Dropped:.....................0 PortXmitData:....................22152 PortRcvData:.....................22720 PortXmitPkts:....................78 PortRcvPkts:.....................80
デバッグ支援機能
pib は InfiniBand 開発用に実機ではできないデバッグ支援機能を提供している。
機能を使うには debugfs をマウントする必要がある。
# mount -t debugfs nodev /sys/kernel/debug
Object Inspection
debugfs の下に pib/ ディレクトリが存在し、その下に pib_0/、pib_1/ が存在する。 さらにその下には ucontext、pd、mr、srq、ah、cq、qp が存在する。 それぞれのファイルは、現在 pib が持っている内部オブジェクトとそのパラメータの一部をリスト表示することができる。
$ cat /sys/kernel/debug/pib/pib_1/qp OID CREATIONTIME PD QT STATE S-CQ R-CQ SRQ MAX-S CUR-S MAX-R CUR-R 000000 [2014-02-07 12:49:43.470,928,849] 0001 SMI RTS 0001 0001 0000 128 0 512 0 000001 [2014-02-07 12:49:43.471,739,044] 0001 GSI RTS 0001 0001 0000 128 0 512 0 000000 [2014-02-07 12:49:43.475,457,857] 0002 SMI RTS 0002 0002 0000 128 0 512 0 000001 [2014-02-07 12:49:43.476,215,959] 0002 GSI RTS 0002 0002 0000 128 0 512 0 6d8478 [2014-02-07 12:49:43.486,957,659] 0003 UD RTS 0004 0003 0000 128 0 256 0 6d8479 [2014-02-07 12:49:43.494,445,613] 0004 UD RTS 0006 0005 0000 128 0 256 0
Execution trace
pib_0/、pib_1/ の下にある trace は、pib の実行トレースを一定エントリだけ蓄えている。
[2014-02-07 14:31:18.628,376,753] API poll_cq OID:0008 [2014-02-07 14:31:18.628,377,144] API poll_cq OID:0008 [2014-02-07 14:31:18.628,377,518] API poll_cq OID:0008 [2014-02-07 14:31:18.628,395,261] RCV1 UD/SEND_ONLY PORT:1 PSN:0003e7 LEN:2056 SLID:0004 DLID:0003 DQPN:6d847b [2014-02-07 14:31:18.628,395,550] RCV2 UD/SEND_ONLY PORT:1 PSN:0003e7 DATA:2048 SQPN:6d847b [2014-02-07 14:31:18.628,399,069] API poll_cq OID:0008 [2014-02-07 14:31:18.628,399,175] API poll_cq OID:0008 [2014-02-07 14:31:18.628,400,341] API post_send OID:6d847b [2014-02-07 14:31:18.628,402,680] SEND UD/SEND_ONLY PORT:1 PSN:0003e7 LEN:2076 SLID:0003 SQPN:6d847b DLID:0004 DQPN:88e06d [2014-02-07 14:31:18.628,423,911] API poll_cq OID:0008 [2014-02-07 14:31:18.628,424,073] API poll_cq OID:0008
Error injection
pib_0/、pib_1/ の下にある inject_err は書き込みのできる仮想ファイルである。 この仮想ファイルに設定を書き込むことで、CQ、QP、SRQ に非同期エラーを挿入することができる。
まず Object Inspection 機能でエラーを挿入したい CQ/SRQ/QP のオブジェクトID(OID)を調べておく。
その上でエラーを挿入したいオブジェクトの種類(CQ
、QP
、SRQ
)と OID をスペースで区切った文字列を inject_err に挿入する。
echo "CQ 0005" > /sys/kernel/debug/pib/pib_1/inject_err
echo を実行後は非同期エラーが発生し、プログラムは ibv_get_async_event
を使う必要に迫られている。
Object Inspection や execution trace を使って確認することが可能。