Ubuntu日和
【第28回】手のひらサイズの小型PCである「R86S」で夢の10GbE生活
2023年6月3日 06:37
第26回と第27回では、30年以上の歴史を誇るLinuxシステムにおける古くからの活用方法として「Sambaを利用したファイルサーバー」を紹介した。それ以外のLinuxサーバーの使い方として古くから存在するのが「Linuxルーター」だ。今回は、そんなLinuxルーター向きの少し怪しいデバイスである「R86S」を紹介しよう。
Linuxをソフトウェアルーターとして使う文化
Linuxを用いてPCをルーター化しようという考えは、それなりに昔から存在した。極端な話、複数のネットワークポートを用意して、届いたフレームを適切にルーティングすればそれでルーターの完成だ。たとえばDebianベースのルーターOSである「Vyatta」は2005年ぐらいに登場しているし、無線ルーターとしての出自を持つ「OpenWrt」も2004年に登場した。BSDベースの製品だともっと古くから存在していたが、Linuxベースだとおそらく2000年代の前半が1つのターニングポイントだったのだろう。
現在では、高機能なルーターだとその内部ではLinuxも使われていることもそれなりにある。また、CPUの高性能化とクラウドコンピューティングの発展に伴って、ネットワーク処理の大部分をCPUに任せるソフトウェアルーターの開発や大規模な利用も進んでおり、これもやはりLinuxの上でさまざまなソフトウェアが動いていることが多い。
Linux上で動くソフトウェアの多くはオープンソースでなおかつフリーソフトウェアでもあるため、これらをリソースが許す限り趣味の世界で使うことも可能だ。よってご家庭の基幹ルーターとして、専用のPCやサーバーを用意して運用するという高尚な嗜みも存在する。
コンピューターの進化に伴って、1つのポートが使える速度も10Mbpsから400GbEまでどんどんと増えてきたわけだが、現在の家庭レベルの普及帯は1GbEだろう。最近ようやく2.5GbEのポートが増えてきたという状況だ。またインターネットにつながるルーターのLANポートはほとんどが1Gbpsだが、10Gbpsサービスが増えてきたため10GBASE-Tなポートを搭載するケースも出てきている。そうすると家庭内ネットワークも10GbEで統一したいという気持ちも出てくるだろう。
ただし10GbEの製品は、一般的な感覚で言うと価格が高い。あと熱い=消費電力も大きい。だからこそ10GbEの規格化よりもあとに2.5GbE/5GbEが登場している。とは言えPCIeの進化も激しく、たとえばPCIe 3のx8だと64GT/sなので、数字だけ見ると10GbEが6ポート使えることになる。そんなわけで、最近は10GbEが複数のポート搭載されたPCIe NICもそれなりの価格で出てくるようになった。インフラの予算が潤沢なご家庭だと、そろそろ宅内ネットワーク向けに25GbEから100GbEが視野に入ってきたかもしれない。
ネットワークで遊ぶには最適なR86S
そんな中で昨年(2022年)末ぐらいから登場したのが、今回紹介する「R86S」だ。この製品は最近はやりの手のひらサイズの小型PCながら、なんと10GbEが2ポートと2.5GbEが3ポートというとんでないスペックの代物。しかもお値段が5万円台という、性能から考えると中身が心配になるほど格安な値付けになっている。
中国のGoWin Solutionが開発を行なっているこの製品は、現在のところ公式サイトやAliExpressで購入できる。ただし最新のモデルはAliExpressだけの模様だ。公式サイトは「About Us」も含めて、ほとんどが404か空のページになっている。わくわく度が増してきただろう。
ちなみに公式ドキュメントっぽいものも存在する。製品に同梱されているパンフレットから考えると公式だとは思われるが、「Contact Information」に「tentatively」(とりあえず)と書いてあったり、連絡先アドレスがGoWinのドメインではなく、Gmailだったりする。
さて、実際のスペックを見ていこう。R86Sにはさまざまなモデルが存在する。まずは、すべてのモデルをまとめておこう。スラッシュの前後はモデルによって異なるオプションだ。
- CPU:IntelN5100/N5105/N6005(Jasper Lake)
- RAM:4GB/8GB/16GB/32GB
- eMMC:128GB
- I/O:microSD(TF)、HDMI
- Power:DC/USB-C
- M.2:2280 x 1/2280 x 1 + 2230 x 1
- Network:2.5GbE x 3/2.5GbE x 3 + 10GbE(SFP+) x 2
大雑把にわけて、ケースが薄いモデルと厚いモデルが存在する。10GbEが搭載されるのが厚いモデル(G/U/Tシリーズ)で、それ以外は薄いモデル(B/Pシリーズ)になる。また、末尾の数字が大きくなるとCPUやRAMの性能も向上する。
- GW-R86S-B1/B2/B3:N5100を搭載した唯一のファンレスモデル。B1だけRAMが4GBでM.2スロットなしとなっている
- GW-R86S-P1/P2/P3/P4:BシリーズのCPUをN5105にしたファンありモデル。P1のRAMが8GBで、P2/P3が16GB、P4が32GB、P3/P4はCPUがN6005でWi-Fiありになっている
- GW-R86S-G1/G2/G3/G4:すべて10GbEが搭載され、G1/G2がN5105、G3/G4がN6005でWi-Fiありとなっている。RAMはG1から順番に8GB、16GB、16GB、32GB
- GW-R86S-T1/T2/T3/T4:Pシリーズの電源をType-Cにして、USB 3.0×2からUSB 3.0×1 + USB 2.0×1にしたもの
- GW-R86S-U1/U2/U3/U4:Gシリーズの電源をType-Cにして、USB 3.0×2からUSB 3.0×1 + USB 2.0×1にしたもの
TシリーズとUシリーズは最近出てきたモデルのようだ。10GbEを使いたいなら、GシリーズかUシリーズを使うことになるだろう。ちなみに2カ月前の開発者のコメントによると「4月半ばぐらいにAlder Lake-N100モデルを出すことを計画している」と書かれている。4月半ばは過ぎてしまっているものの、これから購入するならAlder Lake-Nモデルのリリースを待ってみるのも良いかもしれない。
形状からファンレスのように見えるが、ファンレスなのはBシリーズだけで、それ以外はファンありになっている。CPU用のファンだけでなく、10GbEが搭載されている場合はNIC用のファンも存在する。音はそこそこ大きいが、すごくうるさいという程度ではない。音が高めであり、ノートPCの少しうるさい時ぐらいだろうか。1mぐらい離れれば気にならない程度だ。ちなみに2ピンのファンであり、少なくともLinuxからはファンコントロールができない。負荷に関わらず、ずっとほぼ同じ音量で鳴り続ける。
今回は10GbEが使えてWi-Fiが搭載されていないGW-R86S-G2を購入してみた。冒頭の写真がその製品だ。10GbEはNVIDIAに買収されたMellanoxのConnectX-3のMCX342Aが搭載されている。PCIe 3.0のx4として接続されており、それをマルチデバイスとして見せているようだ。また、2.5GbEはIntelのI225-VのB3ステッピングとなっている。EEE(Energy Efficient Ethernet)は無効化されていた。
Gシリーズの難点はACアダプタが必要なことだろう。残念ながら購入時はUシリーズがまだ売られていなかったのだ。一応電源は同梱されるのだが、当然のことながらPSEマークは存在しない。そこで別途電源も調達することにした。届いたACアダプタのスペックが12V/4Aの出力で、DCプラグが外径5.5mm・内径2.5mmのセンタープラスのようだったため、12V/5AのACアダプタとDCプラグの口径を変換するアダプタを合わせて購入して使用することにした。
あとはHDMIケーブルと、OSインストール用のUSBストレージ、それに操作用のキーボードとマウスがあれば十分だろう。ちなみにUSBポートは2ポートしかないため、組み合わせには気をつけよう。Ubuntuをインストールするだけなら、USBストレージの代わりに、8GBぐらいのmicroSDを用意しておくのも1つの手だ。
R86SにUbuntuをインストールしよう
内蔵ストレージであるeMMCには、ルーター向けLinuxディストリビューションであるOpenWrtがインストールされている。rootのパスワードは「password」だ。ETH0はDHCPでアドレスを取得するようになっている。telnetやsshは不可だが、HTTP/HTTPS/FTPのポートは誰かが待ち受けているようだ。あとなぜかDockerがインストールされていた。
いずれにせよ、よく分からないコンフィグのOSをそのまま使い続けるのは怖いので、好みのOSをクリーンインストールしよう。この連載では当然のことながらUbuntuをインストールする。Intel/AMDのCPUが搭載されたこの手のデバイスは、ハードウェアの初期化をUEFI BIOSが担ってくれるし、GRUBのインストールもUEFIの流儀に従えば良いので、起動するだけならそこまで困ることはない。
平成の時代に存在した「CPUは64bit対応だけれどもUEFIは32bitのみ」みたいなデバイスでなければ、Ubuntuのインストーラを書き込んだUSBストレージを接続するだけで起動する。これはほかのLinuxディストリビューションでもおおよそは状況は同じだ。
ビデオ出力がないデバイスだとインストールにひと手間必要になるが、R86SはHDMIポートがついているため、そのへんにあるHDMIディスプレイを繋いでおけば良いだろう。ただし起動順はOpenWrtがインストールされているeMMCが最優先になっているため、まずはBISO画面に入らないといけない。 BIOS画面に入るには起動後のR86Sのロゴが表示されている間、DELキーを連打するだけだ 。
試しにUbuntu 23.04のデスクトップ版を起動してみたところ、何の問題もなくデスクトップが表示された。
デスクトップは動くものの、用途を考えるとインストールするのはUbuntuのサーバー版が無難だ。サーバー版にすることで、余計なサービスが立ち上がらなくなり、その分CPUやメモリのリソースを有効活用できる。機能的にはUbuntu 22.04 LTSでも問題ないため、22.04をインストールしよう。
Ubuntuサーバーの詳細なインストール手順は第26回を参照してほしい。ちなみにネットワーク設定時は、使わないネットワークインターフェイスに対して、Enterキーでメニューを表示し「Edit IPv4」から「Disabled」にしておくと、次の起動時間がはやくなる。
インストールが完了したら再起動だ。インストール後のソフトウェアのアップデートなどは第27回を参照しよう。最低限、「sudo apt update」と「sudo apt full-upgrade」だけやっておくと良いだろう。
ネットワーク機能の確認
Ubuntuをインストールしたら、システムのネットワーク部分の構成を確認しておこう。うまく設定できないなーと悩んでいたら、そもそもデバイスとして認識していませんでしたとなると目もあてられない。最近の内蔵の有線LANはおおよそPCIeデバイスとして見えるため、とりあえずlspciコマンドを打つと良い。
$ lspci
00:00.0 Host bridge: Intel Corporation Device 4e24
00:02.0 VGA compatible controller: Intel Corporation JasperLake [UHD Graphics] (rev 01)
00:14.0 USB controller: Intel Corporation Device 4ded (rev 01)
00:14.2 RAM memory: Intel Corporation Device 4def (rev 01)
00:16.0 Communication controller: Intel Corporation Management Engine Interface (rev 01)
00:1a.0 SD Host controller: Intel Corporation Device 4dc4 (rev 01)
00:1c.0 PCI bridge: Intel Corporation Device 4db8 (rev 01)
00:1c.1 PCI bridge: Intel Corporation Device 4db9 (rev 01)
00:1c.2 PCI bridge: Intel Corporation Device 4dba (rev 01)
00:1c.4 PCI bridge: Intel Corporation Device 4dbc (rev 01)
00:1f.0 ISA bridge: Intel Corporation Device 4d87 (rev 01)
00:1f.3 Audio device: Intel Corporation Device 4dc8 (rev 01)
00:1f.4 SMBus: Intel Corporation JaserLake SMBus (rev 01)
00:1f.5 Serial bus controller: Intel Corporation JaserLake SPI (flash) Controller (rev 01)
01:00.0 Ethernet controller: Intel Corporation Ethernet Controller I225-V (rev 03)
02:00.0 Ethernet controller: Intel Corporation Ethernet Controller I225-V (rev 03)
03:00.0 Ethernet controller: Intel Corporation Ethernet Controller I225-V (rev 03)
04:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]
1行ごとにデバイスが表示される。「バスの位置(Bus番号:デバイス番号.ファンクション番号)」「デバイスの種別」「デバイス名」の順番だ。ブリッジデバイス等も表示されるため、少し分かりにくいが、I225-Vが3台にMellanoxのNICが1台載っていることが分かるだろう。
$ sudo lspci -s 04:00.0 -vvv
04:00.0 Ethernet controller: Mellanox Technologies MT27500 Family [ConnectX-3]
Subsystem: Mellanox Technologies MT27500 Family [ConnectX-3]
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 29
Region 0: Memory at 7fd00000 (64-bit, non-prefetchable) [size=1M]
Region 2: Memory at 6000000000 (64-bit, prefetchable) [size=8M]
Expansion ROM at 7fc00000 [disabled] [size=1M]
Capabilities: [40] Power Management version 3
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [48] Vital Product Data
Product Name: CX341A - ConnectX-3 SFP+
Read-only fields:
[PN] Part number: MCX341A-XCDN
[EC] Engineering changes: A3
(中略)
Kernel driver in use: mlx4_core
Kernel modules: mlx4_core
上記のように、詳細な情報表示も可能だ。こうやって見てみるとデバイスは「CX341A」になっていて、mlx4_coreドライバが使われていることも分かる。
ネットワークデバイスがどのようなインターフェイス名になっているかは「ip link」コマンドを使おう。前世紀までしかLinuxを使っていなかった人に向けて説明すると、昔の「ifconfig」相当のコマンドだ。Ubuntuを含む最近のLinuxディストリビューションは、ifconfigではなくipコマンドを使う方向に進んでいる。Ubuntuだともうifconfigはインストールされていないので、必要ならnet-toolsパッケージをインストールしよう。ただし他のUnixとは異なり、Linux向けのifconfigは、ほぼメンテナンスされていないので、ipコマンドへの移行を強くおすすめする。
$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:f0:cb:ef:df:d7 brd ff:ff:ff:ff:ff:ff
3: enp2s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:f0:cb:ef:df:d8 brd ff:ff:ff:ff:ff:ff
4: enp3s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:f0:cb:ef:df:d9 brd ff:ff:ff:ff:ff:ff
5: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:02:c9:9c:02:0c brd ff:ff:ff:ff:ff:ff
6: enp4s0d1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:02:c9:9c:02:0d brd ff:ff:ff:ff:ff:ff
ネットワークのインターフェイス名のリストが欲しかったら「ip link」、IPアドレスも表示したかったら「ip addr」を使うことが多い。ちなみにUbuntuサーバーのようなsystemd-networkを使っている環境なら、networkctlコマンドも存在する。このあたりは好みで使い分けると良いだろう。
さて、Ubuntuのネットワークインターフェイス名は、「Predictable Network Interface Names」なる命名規則を採用している。これは何かと言うと、ネットワークデバイスがどのように接続されているかによって、自動的に名前を決める仕組みだ。
- ファームウェア・BIOSが番号付けしているデバイス:eno1
- ARMなどのDevice Treeで番号付けしているデバイス:end1
- PCIeデバイスで、スロット番号がファームウェアから提供される場合:ens1
- 上記以外のPCIeデバイス:enp1s2
- USBデバイスで、ポート番号がわかっている場合:enp0s3u1u2
先頭が「en」になっているのはEthernetで、無線LANだと「wl」と付く。ほかにも候補あるが、大抵の場合はこれのどちらかだろう。つまりPCIeとUSBデバイスにしろ、その設定によって名前が変わることになる。しかしながら大体のシステムにおいて起動の度に名前が変わることがないようになっている。上記の例だとlspciの結果と組み合わせると次のことが分かる。
- enp1s0、enp2s0、enp3s0はそれぞれPCIeのバス番号だけ違うので2.5GbEポートのI225-Vである
- enp4s0とenp4s0d1は、PCIeデバイスとしては同一でソフトウェア的に異なるデバイスを見せている10GbEポートのCX341Aである
ちなみに「lo」は「ローカルループバック」と呼ばれるインターフェイスで、要するに「自分自身」を指すものだ。
さらにネットワークデバイスの情報は、ethtoolコマンドで取得できる(ことが多い)。たとえば、10GbEのポートを表示してみよう。
$ sudo ethtool enp4s0
Settings for enp4s0:
Supported ports: [ FIBRE ]
Supported link modes: 10000baseKX4/Full
1000baseX/Full
10000baseCR/Full
10000baseSR/Full
Supported pause frame use: Symmetric Receive-only
Supports auto-negotiation: No
Supported FEC modes: Not reported
Advertised link modes: 10000baseKX4/Full
1000baseX/Full
10000baseCR/Full
10000baseSR/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: No
Advertised FEC modes: Not reported
Speed: Unknown!
Duplex: Unknown! (255)
Auto-negotiation: off
Port: FIBRE
PHYAD: 0
Transceiver: internal
Supports Wake-on: g
Wake-on: g
Current message level: 0x00000014 (20)
link ifdown
Link detected: no
光ケーブル(FIBRE)接続で、1GbEと10GbEに対応していることが分かる。これが2.5GbEポートだと「Supported link mode」や「Port」の欄が変わってくるので、比較してみると良いだろう。
先ほどI225-VのEEEが無効化されている説明したが、これもethtoolで確認できる。
$ sudo ethtool --show-eee enp1s0
EEE settings for enp1s0:
EEE status: disabled
Tx LPI: disabled
Supported EEE link modes: Not reported
Advertised EEE link modes: Not reported
Link partner advertised EEE link modes: Not reported
いずれにせよ、ここまでの確認でどのポートが2.5GbEでどのポートが10GbEなのか、そしてどんなデバイスが使われているかが分かった。
10GbEでの通信を体験してみる
2.5GbEは1GbEと同じく単にツイストペアケーブルを繋げるだけなので、ここからは10GbEポートを試してみよう。
R86Sの10GbEのポートは、いわゆる「RJ45」と呼ばれることが多い8P8Cコネクタではなく、 「SFP+」 コネクタになっている。これはその名の通りSFP+(Small Form-factor Pluggable plus)モジュールを接続するためのコネクタである。SFP+モジュールは、電気信号と光信号を相互に変換する、光ファイバーを繋ぐための変換器と考えておけば良いだろう。SFPと名前の付くものにはいくつか種類があり「SFP+」は主に10Gbpsまでの速度用として使われている。詳細は「光Ethernetの歴史と発展」の連載を参照してほしい。
つまりR86Sで10GbEを堪能するためにはSFP+モジュールが必要になる。とは言え、R86Sを買うような人ならそのへんに適当なSFP+が転がっているはずだからそこまで問題にはならないだろう。もし購入する場合は、後述するように使用するケーブルによって、必要なものが変わってくるので注意してほしい。
次に必要になるのがケーブルだ。SFP+モジュールは基本的に光ケーブルを接続するものだが、実はいくつかの拡張が存在する。よくあるのが「SFP-T」とも呼ばれることの多い、8P8Cコネクタに変換するものだ。これにより普通のLANケーブルを接続できる。R86Sの対向が8P8Cコネクタしかない場合は、10Gbpsに対応したSFP-Tモジュールを買うことになるだろう。この場合は、Cat6A以上のLANケーブルを使えば良い。
やっかいなのは光ファイバーだろう。こちらは波長やモード、対応距離でさまざまな規格が存在する。当然のことながら互換性の無い規格同士では接続できないと思っておこう。家庭内であれば対応規格や製品名に「SR」とついている波長が850nmでマルチモードの光ファイバーとそれに対応した光モジュールを選んでおこう。
とりあえず今回は「SFP+」の上位規格であり25Gbpsまで対応したSFP28モジュールと、10GbE以上に対応したマルチモードファイバーであるOM4ケーブルの組み合わせで確認することにする。
さて、実際に通信を試して見るためには対向装置が必要だ。しかしながら一般のご家庭にSFPポートのあるデバイスがあるわけがない。そうするとSFP-T等を使うことになるわけだが、せっかくだから光ファイバーをつないでみたいところ。幸いなことにR86Sには、10GbEのポートが「2個」存在する。これを直接繋いで通信してみよう。
ちなみにSFPモジュールはi2c経由でいろいろと制御できるようになっている。Linuxならethtoolコマンドを使うことで、SFPモジュールそのものの情報を取得可能だ。
$ sudo ethtool -m enp4s0d1
Identifier : 0x03 (SFP)
Extended identifier : 0x04 (GBIC/SFP defined by 2-wire interface ID)
Connector : 0x07 (LC)
Transceiver codes : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02
Transceiver type : Extended: 100G Base-SR4 or 25GBase-SR
Encoding : 0x06 (64B/66B)
BR, Nominal : 25750MBd
Rate identifier : 0x00 (unspecified)
Length (SMF,km) : 0km
Length (SMF) : 0m
Length (50um) : 0m
Length (62.5um) : 0m
Length (Copper) : 10m
Length (OM3) : 70m
Laser wavelength : 850nm
Vendor name : FS
Vendor OUI : 64:9d:99
Vendor PN : SFP28-25GSR-85
Vendor rev : B
Option values : 0x08 0x1a
Option : RX_LOS implemented
Option : TX_FAULT implemented
Option : TX_DISABLE implemented
Option : Retimer or CDR implemented
BR margin, max : 0%
BR margin, min : 0%
Vendor SN : F2034318318
Date code : 220222
このまま10GbEポートのインターフェイスにある、enp4s0やepn4s0d1にIPアドレスを割り振ることも可能だが、それだとポート間の疎通確認はできない。なぜならシステム内部のIPアドレス宛の通信は、基本的にローカルループバック経由の通信として扱ってしまうからだ。つまりenp4s0からenp4s0d1へ通信しようとしても、光ファイバーにデータは通らず、システムの中だけで完結してしまう。
そこでLinuxの「ネットワーク名前空間(network namespace)」の仕組みを使って、個々のインターフェイスを隔離してしまおう。ここからは、前述の「ipコマンド」が大活躍する。
「net0」「net1」という名前のネットワーク名前空間を作成する
$ sudo ip netns add net0
$ sudo ip netns add net1
ネットワークインターフェイスを、それぞれの名前空間に隔離する
$ sudo ip link set dev enp4s0 netns net0 name eth0
$ sudo ip link set dev enp4s0d1 netns net1 name eth1
たとえばenp4s0は名前空間「net0」に隔離し、それに「eth0」という名前をつけている。一度隔離してしまえば、ホストからは見えなくなる。実際に「ip link」してみると、隔離したenp4s0とenp4s0d1は見えなくなっているだろう。
ネットワーク名前空間の中で任意のコマンドを実行したい場合は、「ip netns exec net0 コマンド」と実行する。「ip netns exec net0 ip link」すると、隔離した「eth0」が表示されているはずだ。そこでそれぞれの隔離したインターフェイスをリンクアップし、IPアドレスを割り振ろう。
リンクアップ
$ sudo ip netns exec net0 ip link set eth0 up
$ sudo ip netns exec net1 ip link set eth1 up
それぞれにIPアドレスを割り当てる
$ sudo ip netns exec net0 ip addr add 192.168.100.100/24 dev eth0
$ sudo ip netns exec net1 ip addr add 192.168.100.101/24 dev eth1
これで、eth0からeth1への通信は一旦外を経由することになる。
$ sudo ip netns exec net0 ping -c 3 192.168.100.101
PING 192.168.100.101 (192.168.100.101) 56(84) bytes of data.
64 bytes from 192.168.100.101: icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from 192.168.100.101: icmp_seq=2 ttl=64 time=0.034 ms
64 bytes from 192.168.100.101: icmp_seq=3 ttl=64 time=0.038 ms
--- 192.168.100.101 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2049ms
rtt min/avg/max/mdev = 0.034/0.044/0.062/0.012 ms
もし本当に送られているか心配になるようなら、光ケーブルに近づいてフレームが流れている息吹を感じ取ってみよう。息吹を感じる自信がないようなら、ネットワークデバイスの割り込みの数が増えているか確認してみるのも良いだろう。たとえば今回の10GbEポートはMellanox(現NVIDIA Mellanox)なので、割り込みの数を表示してくれる「/proc/interrupts」を「mlx」で検索すると該当する割り込みの数を確認できる。
$ grep mlx /proc/interrupts
143: 0 58 0 11693 IR-PCI-MSI 2097152-edge mlx4-async@pci:0000:04:00.0
144: 0 23 0 0 IR-PCI-MSI 2097153-edge mlx4-1@0000:04:00.0
145: 0 13 0 0 IR-PCI-MSI 2097154-edge mlx4-2@0000:04:00.0
146: 0 7 0 0 IR-PCI-MSI 2097155-edge mlx4-3@0000:04:00.0
147: 0 0 21 0 IR-PCI-MSI 2097156-edge mlx4-4@0000:04:00.0
148: 0 0 0 0 IR-PCI-MSI 2097157-edge mlx4-5@0000:04:00.0
149: 0 0 0 0 IR-PCI-MSI 2097158-edge mlx4-6@0000:04:00.0
150: 0 0 0 0 IR-PCI-MSI 2097159-edge mlx4-7@0000:04:00.0
151: 0 0 0 0 IR-PCI-MSI 2097160-edge mlx4-8@0000:04:00.0
CPUごとのカウントなので、どれかの数字が増えていたら、デバイス側での通信処理が行なわれたと判断できる。
さて実際に通信してみよう。この手の動作確認には「iperf」コマンドがよく使われる。Ubuntuの場合は、iperf3だ。まずはパッケージをインストールしておこう。
$ sudo apt install iperf3
iperf3はiperf3クライアントがUDP/TCPパケットを相手のマシン上で動いているiperf3サーバーに送り、そのスループットやパケットロス率などを調べるツールである。今回の場合、R86Sの10GbEポート1から、同10GbEポート2に送るため、クライアントとサーバーの両方をR86Sで動かすことになる。あらかじめ端末を複数用意しておこう。ここからはクライアント側のプロンプトを「client<数式>」、サーバー側のプロンプトを「server1</数式>」と表示しておく。
まずはiperf3サーバーを立ち上げる。TCPでの通信を考えているため、オプションはサーバーを示す「-s」と待ち受けるIPアドレスだ。10GbEポートはネットワーク名前空間に閉じ込めているため、次のように実行する。
server$ sudo ip netns exec net0 iperf3 -s 192.168.100.100
次にクライアント側でiperf3を動かしてみよう。これで速度計測が開始される。
client$ sudo ip netns exec net1 iperf3 -i 0 -O 3 -c 192.168.100.100
Connecting to host 192.168.100.100, port 5201
[ 5] local 192.168.100.101 port 37036 connected to 192.168.100.100 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-10.00 sec 10.9 GBytes 9.40 Gbits/sec 0 1.56 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 10.9 GBytes 9.40 Gbits/sec 0 sender
[ 5] 0.00-10.04 sec 11.0 GBytes 9.40 Gbits/sec receiver
iperf Done.
結果を見てみるとクライアントからの送信・サーバーでの受信ともに9.40Gbps程度は出ていることが分かる。クライアント側のオプションの「-i 0」は送信インターバルをなくして全力で送るモードであり、「-O 3」は最初の3回を無視するように伝えている。もしもう少しいろいろ試したければ、まずはMSSを変えてみよう。iperf3の場合、MSSの最小値は88なので、「-M 88」のようなオプションを指定するとMSSを変更できる。たとえば88だと1.58Gbpsまで下がり、ジャンボフレームの上限に近い9,000だと9.40Gbpsまであがった。
ちなみに2.5GbEポートであるETH1/ETH2に負荷をかけた状態でも、10GbEポートの速度は落ちなかった。またSSHログイン用のETH0を除くすべてのポートで5分ほどずっと通信してみたところ、10GbE用のクライアントを動かしているCPUが100%になるものの、システム全体としてのCPU使用率は50%を超えることはなく、CPUコアの温度も55℃ぐらいまでしか上昇しなかった。普段が45℃ぐらいなので、悪くない数字だろう。ただ、ケースは触り続けるのは避けたいぐらいの熱さにはなる。
つまり空冷がそれなりに効く冷暗所に配置してやれば、10GbEx2ポート・2.GbEx3ポートをフル活用しても耐えられる可能性が高い。CPUは非力だが、それ以外のハードウェアは強力だし、内蔵GPUもあるために一通りのハードウェアエンコード・デコード機能も備わっている。一般向けではないものの、いろいろな使い方を妄想できるデバイスだ。
ちなみにネットワーク名前空間に入れたインターフェイスは名前空間を削除すればホスト側に戻る。
$ sudo ip netns delete net0
$ ip link
(中略)
5: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:02:c9:9c:02:0c brd ff:ff:ff:ff:ff:ff
altname enp4s0
ただし上記のように、名前空間の中の名前が残ってしまっている。元に戻したければaltnameを一旦削除してからリネームする必要がある。
$ sudo ip link property del dev eth0 altname enp4s0
$ sudo ip link set eth0 name enp4s0
このあたりCLIでやっているために面倒に見えるが、普通はここまで面倒なことはやらないので安心してほしい。単にUbuntuに最初から入っているツールをできるだけ使うようにすれば、このような手順になったというだけのことだ。
最後にR8Sの10GbEポートをホームゲートウェイの10GBASE-Tポートに直接繋いで、インターネットの速度テストも試してみた。次の画像のように、きちんと1GbEの壁を超えていた。
我が家で10GbEの恩恵を得られるのはまだまだ遠そうだ。