ページ ツリー
メタデータの末尾にスキップ
メタデータの先頭に移動

おうちで簡単SFPハック

SFP/SFP+のハードウェアについて

SFP/SFP+のハードウェアについては、以下の資料に詳細が記されています。

ftp://ftp.seagate.com/sff/INF-8074.PDF
ftp://ftp.seagate.com/sff/SFF-8419.PDF

Hackの為に必要な情報としては以下の通り。

  • 最低限必要な配線
    • VccT/VccE - Vcc(3.3V)
    • VeeT/VeeR - GND
    • MOD-DEF1 - I2C SCL (I2Cのクロック)
    • MOD-DEF2 - I2C SDA (I2Cのデータ
  • I2C
    • I2Cのプロトコル
      • Atmel AT24C01Aに代表されるI2C EEPROM互換のInterface
      • I2Cアドレスは0x50と0x51
        • 0x50: モジュールの定義情報を含むEEPROM(ハック対象)
        • 0x51: DDM等、デバイスの状態が反映されるEEPROM状のインターフェイス
          • SFPによってはこの中にパスワードを受け付けるアドレスがあり、そこに適切なパスワードを書き込む事によって0x50の書き込みが可能になるものがある。
          • 概ね0x7bからの4バイトがパスワード空間、Finisarのデフォルトは[0x00, 0x00, 0x00, 0x00]
    • I2Cは3.3Vロジックなので、Raspberry Piとは直結可能だが、Arduino Unoとは直結不可能なので注意
      • Arduino Pro Mini 3.3V等、3.3Vロジックのマイコンとなら接続可能
      • SCL, SDAともにプルアップが必要なので忘れずに


デバイスの接続

上記の情報を元に、何らかのコンピュータとSFPを接続する必要がある。SFPコネクタを入手して直接配線する事も可能ではあるが、専用の基板無しでSFPコネクタに半田付けを行うのは至難の業であるので、ここでは、入手及び配線が容易な以下のデバイスを使用する。

  • マイコン
    • Raspberry Pi(モデルは何でもOK)
      • Raspberry Piでi2cを使えるように設定しておくこと。(raspi-configで可能)
      • i2c-toolsを入れておくこと。
  • SFPスロット
    • Cisco TwinGig Converter CVR-X2-SFP

これらを以下のように接続する。プルアップ抵抗はCVR-X2-SFPに内蔵されているため直結でOK!I

接続の確認

上記手順の通りSFPスロットとRaspberry Piを接続した後、電源を起動し、SFPスロットにSFPを挿入する。以下のコマンドで、SFPが正しく認識されることを確認する。

i2cdetect
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

正しく認識されていると、上記のように0x50番地に何かが接続されていると表示される。0x51については前述の通りDDM用であるが、デバイスによっては表示されないこともある(1000BASE-TのSFPや中華製の安物等)。

データの吸い出し

SFPが正しく認識されていることを確認できたら、続いてデータの吸い出しを行う。I2C EEPROMは非常に単純なプロトコルなので、以下のコマンドで容易に吸い出しが可能である。

i2cdump
$ sudo i2cdump -y 1 0x50
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 03 04 07 00 00 00 01 20 40 0c 01 01 0c 00 00 00    ???...? @????...
10: 37 1e 00 00 46 49 4e 49 53 41 52 20 43 4f 52 50    7?..FINISAR CORP
20: 2e 20 20 20 00 00 90 65 46 54 52 4a 2d 38 35 31    .   ..?eFTRJ-851
30: 39 2d 37 44 2d 4a 55 4e 00 00 00 00 03 52 00 12    9-7D-JUN....?R.?
40: 00 12 00 00 48 35 46 30 51 30 35 20 20 20 20 20    .?..H5F0Q05
50: 20 20 20 20 30 34 30 34 31 39 20 20 68 10 00 c5        040419  h?.?
60: 37 34 30 2d 30 30 37 33 32 36 20 52 45 56 20 30    740-007326 REV 0
70: 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    1...............
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................


さて、吸い出したこのデータ、そのままでは読みにくいのでHuman-readableな形に変換したいところであるが、手で行うのは非常に面倒である。

そこで作成したParserがあるので、こちらを使ってみると、以下のようになる。このプログラムにはI2Cの読込/書込のプログラムも含まれているため、もはやi2ctoolsは用済みである。

read
$ cd ruby-libsfp/examples
$ ruby read.rb
raw data:
0304070000000120400c01010c000000371e000046494e4953415220434f52502e202020000090654654524a2d383531392d37442d4a554e000000000352001200120000483546305130352020202020202020203034303431392020681000c53734302d30303733323620524556203031000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
#<SFP::EEPROM:0x6504f0
 @br=:BR_1200M,
 @br_max=0,
 @br_min=0,
 @cc_base=18,
 @cc_ext=197,
 @connector=:LC,
 @date_code="040419",
 @diagnostic_monitoring_type=
  [:DDM, :INTERNAL_CALIBRATED, :RECEIVED_POWER_MEASUREMENT_AVERAGE],
 @encoding=:ENC_8B10B,
 @enhanced_options=[:SOFT_RX_LOS],
 @ext_identifier=4,
 @identifier=:SFP,
 @length_copper=0,
 @length_mm500_10m=55,
 @length_mm500_om3_10m=0,
 @length_mm625_10m=30,
 @length_sm_100m=0,
 @length_sm_km=0,
 @options=[:TX_DISABLE, :LOSS_OF_SIGNAL],
 @rate_identifier=0,
 @sff_8472_compliance=0,
 @transciever=
  [:GE_SX, :FC_LINK_I, :FC_TXT_SN, :FC_TXM_M6, :FC_TXM_M5, :FC_SPEED_100M],
 @transciever2=0,
 @used_for_dwdm_modules=0,
 @vendor_name="FINISAR CORP.",
 @vendor_oui=[0, 144, 101],
 @vendor_pn="FTRJ-8519-7D-JUN",
 @vendor_rev="",
 @vendor_sn="H5F0Q05",
 @vendor_specific=
  "740-007326 REV 01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
 @wavelength=850>
Base CC is valid? : false
Ext CC is valid? : true
Expected Base CC: 146
Expected Ext CC: 197

非常に読みすい(?)ですね。

raw data: 0304...というところが生データになるので、ここはバックアップしておきましょう。

書き換え


さて、読み込んだならば書き換えねばなるまい。ということで、実際に書き換えてみましょう。

irbで上記のライブラリを読み込み、OUIとベンダ名を書き換えてみます。

新しいベンダ名は"JITAKURACK", OUIはC0-A8-FE(192, 168, 254)とします。特に意味は無いです。


rewrite
$ cd ruby-libsfp
$ irb
# ライブラリの読み込み
irb(main):001:0> require './lib/sfp/rw.rb'
=> true
irb(main):002:0> require './lib/sfp/eeprom.rb'
=> true

# SFP R/Wライブラリの初期化
irb(main):003:0> rw = SFP::RW.new
=> #<SFP::RW:0xca85a0 @path="/dev/i2c-1", @addr=80>

# SFP R/Wで読み込んだ情報を元にSFP EEPROMライブラリのインスタンスを生成
irb(main):004:0> sfp = SFP::EEPROM.new(rw.read)
=> #<SFP::EEPROM:0xf92328 @identifier=:SFP, @ext_identifier=4, @connector=:LC, @transciever=[:GE_SX, :FC_LINK_I, :FC_TXT_SN, :FC_TXM_M6, :FC_TXM_M5, :FC_SPEED_100M], @encoding=:ENC_8B10B, @br=:BR_1200M, @rate_identifier=0, @length_sm_km=0, @length_sm_100m=0, @length_mm500_10m=55, @length_mm625_10m=30, @length_copper=0, @length_mm500_om3_10m=0, @vendor_name="FINISAR CORP.", @transciever2=0, @vendor_oui=[0, 144, 101], @vendor_pn="FTRJ-8519-7D-JUN", @vendor_rev="", @wavelength=850, @used_for_dwdm_modules=0, @options=[:TX_DISABLE, :LOSS_OF_SIGNAL], @br_max=0, @br_min=0, @vendor_sn="H5F0Q05", @date_code="040419", @diagnostic_monitoring_type=[:DDM, :INTERNAL_CALIBRATED, :RECEIVED_POWER_MEASUREMENT_AVERAGE], @enhanced_options=[:SOFT_RX_LOS], @sff_8472_compliance=0, @vendor_specific="740-007326 REV 01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", @cc_base=18, @cc_ext=197>

# オリジナルのベンダ名とOUIを確認
irb(main):005:0> sfp.vendor_name
=> "FINISAR CORP."
irb(main):006:0> sfp.vendor_oui
=> [0, 144, 101]

# ベンダ名とOUIの書き換え
irb(main):007:0> sfp.vendor_name = "JITAKURACK"
=> "JITAKURACK"
irb(main):008:0> sfp.vendor_oui = [ 0xC0, 0xA8, 0xFE ]
=> [192, 168, 254]

# 書き換え後の情報確認
irb(main):009:0> sfp
=> #<SFP::EEPROM:0xf92328 @identifier=:SFP, @ext_identifier=4, @connector=:LC, @transciever=[:GE_SX, :FC_LINK_I, :FC_TXT_SN, :FC_TXM_M6, :FC_TXM_M5, :FC_SPEED_100M], @encoding=:ENC_8B10B, @br=:BR_1200M, @rate_identifier=0, @length_sm_km=0, @length_sm_100m=0, @length_mm500_10m=55, @length_mm625_10m=30, @length_copper=0, @length_mm500_om3_10m=0, @vendor_name="JITAKURACK", @transciever2=0, @vendor_oui=[192, 168, 254], @vendor_pn="FTRJ-8519-7D-JUN", @vendor_rev="", @wavelength=850, @used_for_dwdm_modules=0, @options=[:TX_DISABLE, :LOSS_OF_SIGNAL], @br_max=0, @br_min=0, @vendor_sn="H5F0Q05", @date_code="040419", @diagnostic_monitoring_type=[:DDM, :INTERNAL_CALIBRATED, :RECEIVED_POWER_MEASUREMENT_AVERAGE], @enhanced_options=[:SOFT_RX_LOS], @sff_8472_compliance=0, @vendor_specific="740-007326 REV 01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", @cc_base=18, @cc_ext=197>

# 書き換え後のデータをSFPに書き込み
irb(main):010:0> rw.write(sfp.to_hex)
=> 9

# 比較用に再度SFPの情報を読み込み
irb(main):011:0> sfp2 = SFP::EEPROM.new(rw.read)
=> #<SFP::EEPROM:0xf41fb8 @identifier=:SFP, @ext_identifier=4, @connector=:LC, @transciever=[:GE_SX, :FC_LINK_I, :FC_TXT_SN, :FC_TXM_M6, :FC_TXM_M5, :FC_SPEED_100M], @encoding=:ENC_8B10B, @br=:BR_1200M, @rate_identifier=0, @length_sm_km=0, @length_sm_100m=0, @length_mm500_10m=55, @length_mm625_10m=30, @length_copper=0, @length_mm500_om3_10m=0, @vendor_name="JITAKURACK", @transciever2=0, @vendor_oui=[192, 168, 254], @vendor_pn="FTRJ-8519-7D-JUN", @vendor_rev="", @wavelength=850, @used_for_dwdm_modules=0, @options=[:TX_DISABLE, :LOSS_OF_SIGNAL], @br_max=0, @br_min=0, @vendor_sn="H5F0Q05", @date_code="040419", @diagnostic_monitoring_type=[:DDM, :INTERNAL_CALIBRATED, :RECEIVED_POWER_MEASUREMENT_AVERAGE], @enhanced_options=[:SOFT_RX_LOS], @sff_8472_compliance=0, @vendor_specific="740-007326 REV 01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", @cc_base=190, @cc_ext=197>

# 作成したデータとSFPのEEPROMの内容が一致していることを確認
irb(main):012:0> sfp.to_hex == sfp2.to_hex
=> true
irb(main):013:0>


こんな感じです。ライブラリの使い方はexamples/以下のファイルを見ていただけると大体分かるかと思います。


それでは、Let's enjoy hack life!

  • ラベルがありません
コメントを書く…