2018年6月11日月曜日

FreeBSD 11.1でbxe(QLogic NetXtreme II BCM57840, 10GbE)がリンクアップしない

あるサーバーにFreeBSD 11.1をインストールしたところ、bxe(QLogic NetXtreme II BCM57840, 10GbE)がリンクアップしないという現象に出会いました。

サーバーは
SuperMicro SuperServer1018R-WC0R
https://www.supermicro.com/products/system/1u/1018/sys-1018r-wc0r.cfm
で、CPUは、
CPU: Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz (2100.05-MHz K8-class CPU)
ネットワークインターフェイスは、PCIeの拡張カードで10GbE×1の
bxe0: <QLogic NetXtreme II BCM57840 4x10GbE (B1) BXE v:1.78.90
というものです。

症状としては以下のようなものでした。
  1. FreeBSD 11.1ではリンクアップしない
  2. bxeでPXEによる起動を試みるとリンクアップする
  3. Ubuntu 16.04を入れるとリンクアップする
FreeBSD 11.1でいろいろと操作していると、起動後にifconfig bxe downとしてからifconfig bxe0 upとするとリンクアップすることがわかりました。

rc.dにそのような操作を追加してくれるようなスクリプトを探しましたが、ちょうどよいものがありません。/etc/rc.dにそのようなスクリプトを追加することを、最初、考えましたが、スクリプトの依存性の設定のために既存のスクリプトに少しだけ追記が必要です。しかし、そうしてしまうとOSのアップデートでその設定が失われてしまうかもしれません。

そこで、使っていない/etc/rc.d/netwaitを改造することにしました。これは次のような判断からです。
  1. netwaitを使う記述は/etc/rc.confにするので、netwaitの改造方法もrc.confに書いておく
  2. rc.confは今までのOSのアップデートの際には、書き変割らなかったので、netwaitの記述が失われても取り戻すことができる
  3. 変更はrc.confとnetwaitのみ
具体的には次のように設定しました。
  • /etc/rc.conf
    ### Network link/usability verification options
    netwait_enable="YES"             # Enable rc.d/netwait (or NO)
    #netwait_ip=""                  # Wait for ping response from any IP in this list.
    netwait_timeout="60"            # Total number of seconds to perform pings.
    netwait_if="bxe0"                  # Wait for active link on each intf in this list.
    netwait_if_timeout="30"         # Total number of seconds to monitor link state.

    ###
    #
    #       # Handle SIGINT (Ctrl-C); force abort of while() loop
    #       trap break SIGINT
    #       while [ ${count} -le ${netwait_if_timeout} ]; do
    #
    ## ADDED
    #               /sbin/ifconfig ${wait_if} down 2>/dev/null
    #               /sbin/ifconfig ${wait_if} up 2>/dev/null
    ## ADDED
    #
    #               if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then
    #                       if [ ${got_if} -eq 0 ]; then
    #
    ###
  • /etc/rc.d/netwait
            if [ -n "${netwait_if}" ]; then
                    any_error=0
                    for wait_if in ${netwait_if}; do
                            echo -n "Waiting for ${wait_if}"
                            link=""
                            got_if=0
                            count=1
                            # Handle SIGINT (Ctrl-C); force abort of while() loop
                            trap break SIGINT
                            while [ ${count} -le ${netwait_if_timeout} ]; do
    #
    # ADDED           
                                    /sbin/ifconfig ${wait_if} down 2>/dev/null
                                    /sbin/ifconfig ${wait_if} up 2>/dev/null
    # ADDED                             
    #

                                    if output=`/sbin/ifconfig ${wait_if} 2>/dev/null`; then
                                            if [ ${got_if} -eq 0 ]; then
                                                    echo -n ", interface present"
                                                    got_if=1
                                            fi
                                            link=`expr "${output}" : '.*[[:blank:]]status: \(no carrier\)'`
                                            if [ -z "${link}" ]; then
                                                    echo ', got link.'
                                                    break
                                            fi
                                    fi
                                    sleep 1
                                    count=$((count+1))
                            done
netwaitではifconfigでネットワークインターフェイスが存在するかどうかを確かめているところの前でネットワークインターフェイスをdown、upしています。

こうすることでうまく動作するようになりました。今のところ、OSのアップデート程度の通信であれば動作しています。CIFSやNFSの利用でのようすをみてみることにします。