Disclaimer
本稿は筆者の解析の結果を記載したものであり、筆者はこの内容について何ら責任を負いません。試す場合は自己責任でお願いします。
Intel X520/X55x系NICにおけるSFP+ベンダーロック
Intel ixgbe系NICにおいては、10G SFP+を使用するにあたり、ドライバ内でSFP+のベンダーコード(OUI)を確認し、ホワイトリストに載っていないSFP+が挿入されている場合にエラーを出力し、ドライバの再読込が実施されるまでNICのポートを無効にするロジックが実装されている。
このロジックを回避する方法として、ドライバのオプションに"allow_unsupported_sfp=1"を渡すというものがあるが、これはあくまでLinux等ドライバオプションを指定できるOS上でしか使用することができず、Windows等においてはSFP+のベンダーロックを回避することは困難である。
本稿では、ドライバ上の実装を解説するとともに、これを根本的に回避する方法を解説する
ドライバ上でのSFP+ベンダーロックの実装
以下にLinux用ixgbeドライバにおけるSFP+ベンダーロックのロジック概要を記載する。
SFP+ベンダーロック機構は、ixgbe_phy.cのixgbe_identify_sfp_module_generic関数内で実装されている。
チェック機構は以下のようになっている:
- SFP/SFP+のEEPROMを取得し、サポート対象外のSFP/SFP+でないことを確認する
- サポートされるOpticsはチップごとに異なるためここには記載しないが、必要に応じてコードを確認のこと
- 10G DACの場合、ベンダーによらずすべてのOpticsを許可する
- 1G SFPのうち、サポートしていないものが挿入されている場合はエラーとする
- 82598EBベースのNICの場合、OpticsのベンダーによらずすべてのOpticsを許可する
- NICのEEPROM内に記録されているDEVICE_CAPS(Device Capabilities)を確認し、"IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP" (0x01)のフラグが立っていない場合、以下のチェックを実行する。
- 1G SFPの場合、ベンダーによらずサポートしている種類のトランシーバであれば許可する
- 10G SFP+の場合、SFP+のベンダーコードがIntelのものであれば許可する
- SFP+のベンダーコードがIntelでない場合、ドライバの"allow_unsupported_sfp"オプションを確認し、有効であれば警告メッセージを表示した上で許可する
- 上記の条件にマッチしない場合、エラーとする
- IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP (0x01)のフラグが立っている場合、すべてのトランシーバを許可する
NIC内EEPROMの書き換え
上記のチェック機構によると、NIC内のEEPROM内に保存されている"IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP"のフラグを1にセットすることにより、SFP+のベンダーロックを回避できることがわかる。
ixgbe_common.c内のixgbe_get_device_caps_generic関数およびixgbe_type.h内のIXGBE_DEVICE_CAPS定数によると、このフラグはEEPROMの0x2Cワード目、1word = 2bytesで計算すると0x58番地から2バイトに格納されていることがわかる。
また、ixgbe_type.h内のIXGBE_DEVICE_CAPS_ALLOW_ANY_SFP定数によると、このフラグは0x01とのANDで取り出されており、すなわち最下位ビットであることがわかる。
IXGBE_DEVICE_CAPSは2bytesの長さをもつが、EEPROM上ではリトルエンディアンで格納されているため、バイト単位でみるとEEPROMの0x58番地の最下位ビットがこのフラグになる。
NIC内のEEPROMはLinux上でethtoolコマンドの-eオプションを使用することで内容を確認できる。
$ sudo ethtool -e eth1 offset 0x58 length 1 Offset Values ------ ------ 0x0058: fe
上記の例では、IXGBE_DEVICE_CAPS(の下位バイト)として0xFE(0b11111110)が記録されており、IXGBE_DEVICE_CAPS_ALLOW_ANY_SFPのビットは立っていないことがわかる。この値を0xFF(0b11111111)に書き換えることができれば、SFP+のベンダーロックを根本的に回避できることになる。なお、この値はNICの種類等によって内容が異なる可能性があるため、必ず自身の環境において値を確認することを推奨する。
ethtoolコマンドでは、-Eオプションを使用することでNICのEEPROMを書き換えることが可能となっている。
Intel ixgbe系NICにおいては、EEPROMを書き換える際にはmagicとよばれるキーを指定する必要がある。このキーはNICのPCIのデバイスIDとベンダーIDを結合したもので、例えばX520の場合ほとんどは0x10fb8086となる。
この値はlspci -nnで確認することができる。
$ lspci -nn | grep X5
0a:00.0 Ethernet controller [0200]: Intel Corporation Ethernet Connection X553 10 GbE SFP+ [8086:15c4] (rev 11)
0a:00.1 Ethernet controller [0200]: Intel Corporation Ethernet Connection X553 10 GbE SFP+ [8086:15c4] (rev 11)
上記の例では、Intel X553ベースのNICの値を表示しており、このデバイスではベンダーIDが0x8086、デバイスIDが0x15c4となっている。この場合、magicは0x15c48086となる。
これらの情報を元に、以下のようなコマンドを実行することで、NIC内のEEPROMを書き換えることができる。
$ sudo ethtool -E eth1 magic 0x15c48086 offset 0x58 value 0xff
Linuxにおいては、IXGBE_DEVICE_CAPSはSFPのチェックを実行するたびに読み込まれるため、書き換えを完了したら動作に即時反映され、無事にSFP+のベンダーロックを回避することができる。この変更は永続的なものとなり、Windows等ドライバのオプションでは回避が難しいOS上においても動作するものと考えられる。
なお、デュアルポートNIC等では複数のポートが認識されるが、1つのポートに対して書き換えを実施すればすべてのポートで変更が有効となる。
確認
筆者の環境において上記手法を用いた際のログを以下に記載する。
$ sudo ethtool -e eth1 offset 0x58 length 1
Offset Values
------ ------
0x0058: fe
>>> SFP+の抜挿
$ dmesg | tail -n 2
[ 2790.220891] ixgbe 0000:0a:00.0 eth1: WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics. Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. Intel Corporation is not responsible for any harm caused by using untested modules.
[ 2790.220896] ixgbe 0000:0a:00.0 eth1: detected SFP+: 5
$ sudo ethtool -E eth1 magic 0x15c48086 offset 0x58 value 0xff
$ sudo ethtool -e eth1 offset 0x58 length 1
Offset Values
------ ------
0x0058: ff
>>> SFP+の抜挿
$ dmesg | tail -n 2
[ 2790.220896] ixgbe 0000:0a:00.0 eth1: detected SFP+: 5
[ 3097.967617] ixgbe 0000:0a:00.0 eth1: detected SFP+: 5
IXGBE_DEVICE_CAPSの最下位ビット(IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)が0の際はWARNINGとしてOpticsがサポートされていない旨が出力されているが、IXGBE_DEVICE_CAPSの最下位ビット(IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)を1にすることでWARNINGの出力がなくなっていることがわかる。(筆者の環境においてはallow_unsupported_sfpが有効になっているためWARNINGメッセージの出力にとどまっているが、allow_unsupported_sfpが無効の場合はNICのポートの動作が停止する)
コメントの追加