2012年12月21日金曜日

FreeBSD 9.0 で ipfw + natd + em で通信速度が遅くなった

 前回に引き続き FreeBSD ネタ。 今,サーバーの更新をしようと思って,new machine に FreeBSD 9.0 をインストールしている。 そこでは ezjail を使って jail 環境を作り,その中で web server をたてよう,という作戦。 もともとあるシステムを移植したいので,元のサーバーで動いているサービスは全部動かないと困る。 その作業中に出くわした珍しいトラブルについて書こう。

 珍しいと言っても過去に遭遇された人が居たのだが,ネットで検索しても他の例がほとんど引っかからなかったので,珍しいんだと思っている。 どんなトラブルかというと,FreeBSD の比較的新しいバージョン(バージョン 7 以降ぐらいからおこっているみたい)で,network_interface として,emX か fxpX (X は整数。em1 とか fxp2 という名前の network_interface) を持つマシン上で,ipfw を使う際に,ipfw の中で divert port を使うと通信速度が極端に遅くなる,という症状。この divert port というのは,サーバーを通過するパケットを natd に渡して処理をしてもらうためのもので,ipfw というファイアーウォールの処理の初めの方で使われる。私が natd を使うのは,特定のポートに来たパケットを他のマシンに振り分けるのに使っている(なくてもいいという話もあるが…)。そのため /etc/ipfw.conf の初めの方に,上記の divert port へパケットを送れ,という処理を書いている。

 古い方のサーバーの時には何も問題が起こらなくなかったので,全然気にしていなかったのだが,今回のマシンでは,何をしていてもサーバーのレスポンスが遅い。FreeBSD 9.0 のインストールの初期の段階では気にならなかったのだが,いつの間にかレスポンスがとても遅い,と感じるようになってきた。当然,/etc/ の中の設定ファイルをいじっている時に何かをしたから,だと思って,/etc/rc.conf の中や /etc/resolv.conf などをなぶり倒してみたのだが,全く改善されなかった。特に顕著だったのが jail 環境の中でのサービスだった。apache22 で立てている web server などは,古い方のマシンの 100 倍ぐらい遅い感じのレスポンスだった。これじゃ,サーバーマシンは置き換えられへんなぁ,と思ってしまった。しかし,どうみてもマシンの性能的には新しい方がいいはずなので,どこかに問題があるはず,と思って,ごそごとといじったり,ネットで検索したりしてみた。

 そんなこんなでしばらく時間が経ったのだが,ふと ipfw の中の divert を含む行をなしにすると,見違えるように通信速度が速くなった。写真がいっぱいある web page もさくさく表示されるようになった。ということは,問題は natd に有りそう,ということになった。そこで,ネットで「FreeBSD 9.0 natd 遅い」というので検索してみた。幾つか候補はあったが,一番参考になったのが「のろいの em(4)/fxp(4)+natd(8) 解決編!! の巻」というブログエントリー。これによると,em(4)fxp(4) というネットワーク・インターフェースを持つマシンで,natd を使おうと思って,ipfw の中で divert port を使うと,「lo0 に ICMP unreachable - need to frag が大量発生して通信が遅くなる」らしい。よくわからんが…。まぁ,とにかく極端に通信速度が遅くなるらしい。まさに私が遭遇しているケースではないですか。

 対処としては TSO (TCP Segmentation Offload) を disable にすればいいらしい…。なんのこっちゃ?よくわからんが,とりあえずネットワーク・インターフェースが持っていたりいなかったりする機能みたい。今回,その機能が悪さをしているので,それをなしにしろ,ということみたい…(真逆かもしれない…)。 具体的な対処法として,
  ・「fxp(4) の場合は ifconfig -tso を使う」
  ・「em(4) の場合は sysctl -w net.inet.tcp.tso=0 をする」
ということでいいらしい。実は,この2つのネットワーク・インターフェースは,共に Intel 社製のものであり,dmesg によると,em は「Intel(R) PRO/1000 Network Connection 7.2.3」と出てくる。古い方のマシンは確か fxp ってのを使っていたはず…。調べてみると fxp は「Intel 82801DB (ICH4) Pro/100 VE Ethernet」と出てきた。つまり,Intel 社の特定のネットワーク・インターフェースを使っていると,このようなトラブルが発生するみたい。

 そうと分かれば,処理は簡単だった。em の場合,手動で一時的に対処するには
sysctl -w net.inet.tcp.tso=0
とすればいいらしい。でも,sysctl コマンドのマニュアル見ても -w ってオプションは見当たらなかった。かと言って,エラーも出なかったから,どっちでもいいみたい。 もし,起動時に勝手に設定したい場合は,/etc/sysctl.conf に以下のような行を追加するといいらしい。
net.inet.tcp.tso=0
ここで,最後にイコールと数字があるが,この前後にスペースをいれてはいけない。スペースを入れると値がちゃんとは設定されなかった。この設定をしたら,サーバーのレスポンスが驚くほど速くなった。これでなんとかサーバーマシンを新しいのに入れ替えることができそうだ。もうちょっと確認したい動作があるから,お正月休みの間に置き換えようかなぁ?

1 件のコメント:

二児パパ さんのコメント...

bgeインタフェースも同様処理にて改善できました。
ありがとうございました。