Pseudo InfiniBand HCA driver (pib)

作成日:2013.12.06
更新日:2015.02.12

インデックスのページへ。


更新履歴
(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 のメリットとしては、

逆に性能はまったくでない。 また 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 ManagerOpenSM のデフォルトオプションのみ対応。
IPoIB対応
RDMA Communication Managerrdma_server と rdma_client で実行を確認
MPI 
ノード間通信pibnetd を使ったマルチホストモード
開発支援機能 以下のような機能を実装。
  • UCONTEXT/MR/AH/QP/CQ/SRQ の状態を表示する機能。
  • CQ/SRQ/QP にエラーを挿入する機能。
  • API 呼び出し、パケットの送受信、非同期エラーの発生を表示する機能。
  • また以下のような機能の開発を予定している。
  • ポートを切断したり IB パケットの選択的にフィルターする機能
  • IB 仕様の揺れや、特定のベンダーの癖をオン・オフできる機能。
  • 免責

    現在の pib は開発段階のため、利用したシステムに致命的な障害を与える恐れがあります。

    ソースコードとビルド方法

    現在のコードを以下に公開する。 過去のバージョンは ここ においておく。

    また開発状況は https://github.com/nminoru/pib で公開する。

    x86_64 版の CentOS 6.5 で開発しており、x86_64 の RHEL6 または CentOS 6 でしか動作しないと思われる。 動作環境のためには以下のパッケージが必要。

    パッケージを使ったインストール

    RHEL 6 と CentOS6 はパッケージでインストールができる。

    これを順番にインストールすればよい。

    # 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 カーネルをインストールした場合は、自動的にリビルドしてくる。 ただしこのパッケージをインストールするには時間がかかる。

    手動でインストール

    手動でインストールする場合は、以下のファイルを必要とする。

    これを順番に展開しビルド & インストールする。

    $ 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 ソケットの送受信情報を PortXmitDataPortRcvDataPortXmitPktsPortRcvPkts として公開している。

    パフォーマンスカウンター値を見るには、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)を調べておく。 その上でエラーを挿入したいオブジェクトの種類(CQQPSRQ)と OID をスペースで区切った文字列を inject_err に挿入する。

    echo "CQ 0005" > /sys/kernel/debug/pib/pib_1/inject_err
    

    echo を実行後は非同期エラーが発生し、プログラムは ibv_get_async_event を使う必要に迫られている。 Object Inspection や execution trace を使って確認することが可能。

    コメント

    コメントを書き込む

    TOP    掲示板    戻る
    Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp