こんにちは、いつもお世話になっています、伊藤です。
ちょっと長文ですが、おつき合い頂ければと思います。
bgeドライバのパッチを作成して、send-prしたのですが、
私の英語が拙いせいか、あまり相手にしてもらえないので
どなたか、応援をお願いしたいのですが。
http://www.freebsd.org/cgi/query-pr.cgi?pr=98738
「bgeドライバの問題について」
5.5-RELEASE(i386), 7.0-CURRENT(i386),おそらく、6.X(i386)も
同様だと思うのですが、SMPカーネル + マルチプロセッサ(HTT
でも可)という環境において、
複数のプロセスが同時に、bgeドライバを通してNICのリンクステータ
スを取得しようとした場合、リンク状態が正常であるにも関わらず、
ごくまれに異常を返すという現象を確認しています。
具体的には、ifconfig コマンドを同時に複数実行した場合、非常にまれ
ですが、statusフィールドが no carrierを返して来るケースがあります。
(正常であれば、activeとなる。)
カーネルオプションから、 option SMP を抜いたカーネルでは
この現象が発生しないことから、ドライバのソースを追ったところ、
リンク状態を取得する処理にロックが掛けられていなかったため、
ロックを掛ける処理を追加したところ、現象は発生しなくなりました。
「再現させるためには」
(1)SMPカーネルを使う。
(2)マルチプロセッサもしくは、HTTで論理CPUを2つに設定する。
(3)bgeドライバを使用するNICを用意し、HUBに差しリンク状態を正常にする。
(4)以下のシェルスクリプトを2つ、同時に実行する。
タイミングさえ合えば、以下の様にぐるぐる回さなくても良いと思うんですが、
かなり微妙なタイミングなので、回しちゃってます。
#!/bin/csh
while 1
set aaa=`ifconfig bge0 | grep active | wc -l`
if ($aaa == 1) then
echo bge0 Link OK
else
echo bge0 Link NG
exit
endif
end
(5)しばらく待っていると、bge0 Link NGのメッセージが表示される。
ちなみに、fxpや、emでは、こういった現象は発生しませんでした。
「パッチに関して」
要は、 case SIOCGIFMEDIAの処理を、BGE_LOCKと、BGE_UNLOCKで
囲んだだけです。
*** if_bge.c.orig Fri Jun 9 14:34:29 2006
--- if_bge.cFri Jun 9 14:34:58 2006
***
*** 3325,3330
--- 3325,3331
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
+ BGE_LOCK(sc);
if (sc-bge_tbi) {
error = ifmedia_ioctl(ifp, ifr,
sc-bge_ifmedia, command);
***
*** ,3338
--- 3334,3340
error = ifmedia_ioctl(ifp, ifr,
mii-mii_media, command);
}
+ BGE_UNLOCK(sc);
break;
case SIOCSIFCAP:
mask = ifr-ifr_reqcap ^ ifp-if_capenable;
「その他」
bgeと、emでリンク状態の取り出し時間を計ってみると、
emの方が10倍程速いです。
処理的には、NICからステータスを取り出すだけなので
あまり差異はないと思っていたんですが。
ちょっと不思議です。(mii 側に処理があるからかなぁ。)