10GbpsNIC環境でOSのネットワークスタックのパフォーマンスを測定しようとしたら意外と面倒だった.厳密には,面倒だったのはCentOS 6系での設定で結局あきらめた. 仕方がないからCentOS 5.9でやるとそれほどハマらずに設定できた.
2台のマシンがあり,オンボードNICと10GbpsNICが載っている.このとき,
- 10GbpsNIC同士を直接10Gbps Eternetで接続する.
- オンボードNICはゲートウェイを通してインターネットに接続できるようにする.
というのが課題.
これに対して以下の図のようなネットワーク構成にしたらちゃんと通信できた.
設定
大雑把な設定内容を以下のような感じ.
- オンボードNIC周りと10GbpsNIC周りを異なるサブネットに置く.
- インターネットに接続するために192.168.1.1をデフォルトゲートウェイとする.
- 10.0.0.1を10.0.0.0/8サブネットをゲートウェイとする.
- eth1に入ってきたパケットはeth1に出て行くようにルーティングする.
まず,eth0やeth1に対するIPアドレスなどの設定を/etc/sysconfig/network-scripts/ifcfg-eth*に書く.
以下,Host1のみだけどHost2においてもIPADDRとHWADDR以外は同様.
- /sbin/sysconfig/ifcfg-eth0
DEVICE=eth0 BOOTPROTO=static BROADCAST=192.168.1.255 HWADDR=xx:xx:xx:xx:xx:xx IPADDR=192.168.1.10 NETMASK=255.255.255.0 NETWORK=192.168.1.0 ONBOOT=yes
- /sbin/sysconfig/ifcfg-eth1
DEVICE=eth1 BOOTPROTO=static BROADCAST=10.255.255.255 HWADDR=yy:yy:yy:yy:yy:yy IPADDR=10.0.0.100 NETMASK=255.0.0.0 NETWORK=10.0.0.0 ONBOOT=yes GATEWAY=10.0.0.1
設定を有効にするためにnetworkを再起動.
# service network restart
しかし,ここでeth0経由でインターネットにつなげないという問題が発生した. routeコマンドでみるとデフォルトゲートウェイの設定がおかしかった(どうおかしかったかはメモってなくて忘れた)ので,/sbin/sysconfig/networkのGATEWAYDEVにデフォルトゲートウェイに対してパケットを送受信したいインタフェース名を書く.
GATEWAYDEV=eth0
networkを再起動すると,ipコマンドの出力は以下のようになり,eth0経由でインターネットに接続できた. これをHost1,Host2の両方で設定する.
host1% /sbin/ip -v Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.0.0 * 255.255.252.0 U 0 0 0 eth0 169.254.0.0 * 255.255.0.0 U 0 0 0 eth1 10.0.0.0 * 255.0.0.0 U 0 0 0 eth1 default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
次は,eth1側の方で,NICが複数あるとパケットを受信したときにそのパケットに対してどのインタフェースから送信するかをルーティングする必要がある.
今回の場合,eth1で受信したパケットはそのままeth1で返せば良い. 受信パケットに対するルーティングはiproute2で行う.
古来のrouteコマンドですと、宛先に応じてNICのデバイスやnext hop routerの指定を行いますが、Linuxではこのテーブルを複数持つことができ、さまざまな条件でどのテーブルを参照させるかを指定することができます。
「さまざまな条件」とは、例えば
- 送信元IPアドレス
- パケットが入ってきたデバイス名
- fwmark といったものです。
Host1を例にとり,まず10GbpsNIC通信用のテーブルexpを作成する.(新規に作成しなくても既存のmainテーブルにルールを追加すればよいだけな気がする) このテーブルはパケットの送信時に参照され,送信元IPアドレスが10.0.0.100であれば,eth1にパケットを送るという意味である.
- /sbin/sysconfig/network-scripts/route-eth2
dev eth1 src 10.0.0.100 table exp
次に,上記テーブルを参照する条件をrule-eth2に書く. 参照条件として送信元IPアドレスが10.0.0.100であればexpテーブルを見るというように設定する.
- /sbin/sysconfig/network-scripts/rule-eth2
from 10.0.0.100 table exp prio 200
networkを再起動して設定を有効にするとpingは通るようになった.
host1% service network restart host1% ping -I eth1 10.0.0.200
しかし,TCP/UDPのベンチマークツールであるiperfで通信すると,
host1% iperf -s -B 10.0.0.100 host2% iperf -c 10.0.0.100
No route to hostと怒られる.
tcpdumpでみてみると到達不能ICMPパケットが返ってきてるっぽい.
16:46:08.071054 IP 10.0.0.200.51674 > 10.0.0.100.ndmp: S 2955619377:2955619377(0) win 5840 <mss 1460,sackOK,timestamp 23138650 0,nop,wscale 7> 16:43:56.564510 IP 10.0.0.100 > 10.0.0.200: ICMP host 10.0.0.100 unreachable - admin prohibited, length 68
hidekiy blog: [linux] ping は通るのに No route to host と言われる
この辺はSELinuxとiptablesが邪魔をしている可能性があるので,あんまりよくないけどSELinuxとiptablesを切る.
SELinuxを切る.
# sestatus # setenforce 0
SELinuxを無効化する | Smart -Web Magazine
iptablesを切る
# service iptables off
ここまでやって,10GbpsNIC間で問題なく通信できるようになった.
参考
途中要らない設定が入ってそう. ネットワーク難しい.