「ほっ」と。キャンペーン
<   2010年 10月 ( 28 )   > この月の画像一覧
(ネットワーク)スイッチのフロー制御
これは調べるまで知らなかったんですが、スイッチにはフロー制御(フローコントロール)と呼ばれる機能があるようです。

フロー制御とは通信速度が異なる機器をつないだ時に送受信するパケットを動的に制御する仕組みのようです。

例えばあるギガスイッチに 1Gbps で繋いでいるサーバと、同じスイッチに 10Mbps で繋いでいるPCがあるとします。サーバからPC間にパケットを送ろうとすると、1Gbpsから10Mbpsに帯域が細くなるため、パケットがスイッチのバッファに詰まってしまします。そして、送りきれなかったパケットが破棄されてしまいます。


そこで、スイッチのバッファがあふれそうになると、送信元に送信停止要求を投げてバッファが掃けるまで送信中止するのがフロー制御の簡単な仕組みみたいですね。

送信停止要求は、半二重通信の場合は、コリジョン発生時に送るジャム信号、全二重通信の場合はPAUSEフレームのようです。(全二重通信は IEEE802.3x で規格化されているようです。)

さて、このフロー制御ですが、手直にあるL2スイッチを見てみたところほとんど機能として備えていました。

ただ、FXC製のES1016Vというスマートスイッチはデフォルトでフロー制御が無効になっていました。

このせいで、以前に書いた SunRay2 の画面描画が遅くなる現象がおきたのかもしれません。このスイッチにつないだ時に画面描画遅延現象が起きてたので。。。


ということで、スマートスイッチの場合はフロー制御が無効になっていないかどうか気をつけておきましょう。

補足:
スマートスイッチ等でフロー制御がデフォルト無効になっている理由がパフォーマンス・チューニングに載っていました。
要は、Pauseフレームを受信すると、負荷の高くないマシンに送信するトラフィックを含め送信側のすべてのトラフィックがブロックされてしまうので、スイッチ上に過負荷マシンがあると他のマシンも影響を受けて速度が低下するということらしいです。

SIerのエンジニアに聞いてみても、スマートスイッチでフロー制御を有効にした客はいないとのことでした。
イーサネットのフロー制御の仕組みをつかなくても上位層のTCP等で制御できるので構わないようです。


参考:
ASCII.jp:高価な企業向けスイッチはここがすごい!|図で解剖!スイッチ&ルータ
特集 : 最適ネットワーク機器選択術
LAN技術研究室【ハブとスイッチ(2)】
Ethernet LAN - 全二重通信/半二重通信:フロー制御( ジャム信号/PAUSEフレーム )
パソコン関連のいろんなメモ書き : スイッチのフローコントロール こちらの方が言及してるスイッチもフロー制御が無効になっていたようで...
[PR]
by jehoshaphat | 2010-10-31 01:33 | ネットワーク | Trackback | Comments(0)
L2スイッチのカスケード接続
イーサネットのカスケード接続の話です。

ダムハブを使っていた時代は 10Base-T でカスケード接続は4段、100Base-T だと2段っていう制限がありました。

で、今数年前のネットワークの教科書を読んでるんですが、そこの補足部分にL2スイッチのカスケードは信号の減衰や遅延を考慮すれば最大で4段程度が限界だ と書いてます。

あれ、確かL2スイッチはカスケード無制限じゃなかったっけ?と思って調べたら、理論上は無制限ということみたいですね。
ただ、4段が限界というはちょっと無理があるかと思います。

で調べてたら実験! L2 スイッチは実用上、何個までカスケード接続可能か? という興味深い記事が。。。
(SoftEtherの開発者のブログです)

L2スイッチのVLANを利用して、74 台分のスイッチング HUB を直列にカスケードした場合とほぼ同等の環境でテストしたようです。
それでも遅延が1台のスイッチあたり 0.008msec くらいしか出ないようで通信自体は問題なくできているようですね。ただこのテストケースでは一台ずつの直列つなぎなので、実際にスイッチの全てにクライアントがぶら下がった時にどうなるかは分かりません。

ここをみてみると、「メーカーとしても3-5段程度を推奨」というようなことも出てきています。

実際どれくらいまでならOK何でしょうね?
ちなみに、職場では(ネットワーク図がないので詳しくは分かりませんが)おおよそ10数段のL2スイッチカスケードになっています。
[PR]
by jehoshaphat | 2010-10-31 01:33 | ネットワーク | Trackback | Comments(0)
Solarisでのネゴシエーション確認
(ネットワーク)オートネゴシエーションは信用できない?でネゴシエーションの話をしましたが、今回は Solaris でネゴシエーションの設定がどうなっているかの確認方法です。

これらのネットワークインターフェイスの確認や設定は Solraris では NDD コマンドを使うようですね。( ndd /dev/hme ? とすると使用できるパラメタの一覧が分かります。)

まず自身のインタフェース状況(速度やモード)は下記コマンドで分かります。

bash-3.00# ndd /dev/nge0 link_status
1 //0:切断 1:接続
bash-3.00# ndd /dev/nge0 link_speed
100 //スピード
bash-3.00# ndd /dev/bge link_duplex
2 //ドライババージョン < 0.37 0:半二重 1:全二重
//ドライババージョン >= 0.37 1:半二重 2:全二重
(ただし上記はBCMのNICの場合。他のベンダー(今回はngeということでnVidiaですが)のNICは意味が異なるかも)
//↓ドライババージョンの確認方法
bash-3.00# modinfo | grep bge

もしくは、dladm で搭載してるNIC一括で調べることもできるようです。

bash-3.00# dladm show-dev
nge0 リンク: up 速度: 100 Mbps デュプレックス: full
nge1 リンク: up 速度: 100 Mbps デュプレックス: full
bge0 リンク: unknown 速度: 0 Mbps デュプレックス: unknown
bge1 リンク: unknown 速度: 0 Mbps デュプレックス: unknown


自機のオートネゴシエーションが有効かどうかは下記コマンドで分かります。

ndd /dev/nge0 adv_autoneg_cap
1 //0:無効 1:有効

そして、AutoNegotiationモードの場合には,下記の1になっている項目の中からネゴシエーションを行うようですね。

ndd /dev/nge0 adv_1000fdx_cap //1G全二重
1 //0:無効 1:有効
ndd /dev/nge0 adv_1000hdx_cap //1G半二重
0
ndd /dev/nge0 adv_100fdx_cap
1
ndd /dev/nge0 adv_100T4_cap
0
ndd /dev/nge0 adv_100hdx_cap
1
ndd /dev/nge0 adv_10fdx_cap
1
ndd /dev/nge0 adv_10hdx_cap
1


さらにパラメータに lp_xxxxx とすると、リンク先(通常はスイッチ)のモードもわかるようです。(ただし正確とは言えないみたいなので、実際はスイッチを直接見た方がいいかもしれません。)

ndd /dev/nge0 lp_autoneg_cap //リンク先オートネゴシエーション
1
ndd /dev/nge0 adv_1000fdx_cap
0
ndd /dev/nge0 adv_1000hdx_cap
0
ndd /dev/nge0 lp_100fdx_cap
1
ndd /dev/nge0 lp_100hdx_cap
1
....



試してないので、確実とは言えませんが、ネットの情報見る限りモードを設定したいときは下記のような書式にすれば可能なようです。

ndd -set /dev/nge0 パラメタ

例えば1G/Fullだけ有効にし、オートネゴシエーションを無効にする時はこうします。

ndd -set /dev/nge0 adv_1000fdx_cap 1
ndd -set /dev/nge0 adv_1000hdx_cap 0
ndd -set /dev/nge0 adv_100fdx_cap 0
ndd -set /dev/nge0 adv_100hdx_cap 0
ndd -set /dev/nge0 adv_100T4_cap 0
ndd -set /dev/nge0 adv_10fdx_cap 0
ndd -set /dev/nge0 adv_10hdx_cap 0
ndd -set /dev/nge0 adv_autoneg_cap 0



しかし、Solaris というか Unix のネットワーク周り、ドライバ周りはあんまり触ったことないので四苦八苦しますね。

参考:
システム管理者のメモ帳
オートネゴシエーション設定の変更方法 - Solaris User
Solaris でネットワーク speed と duplex を変更する
3.3.2 nddコマンド使用方法
SUN/システム管理の手引き(ネットワーク) - ClassAct 技術情報
Solaris /dev/ge ドライバの設定パラメーター[nddコマンド] - Solaris User
[PR]
by jehoshaphat | 2010-10-24 21:50 | ネットワーク | Trackback | Comments(0)
(ネットワーク)オートネゴシエーションは信用できない?

最近のイーサネット機器のほとんどには通信速度や通信モード(半二重、全二重)の設定を自動的にしてくれるというオートネゴシエーション機能がついてます。

ところが、この auto-negotiation は設定や認識ミスで誤認識するようなことがあるようです。
ググってみるといろいろこれに起因するトラブルが多いようでした。

しかも厄介なのは誤認識してもとりあえず通信は確保されてしまうということですね。
その場合、Rx CRC Error Count 等の通信エラーが発生するようです。

ですので、通信が遅いとかいう場合で思い当たる節が無い場合は、ネゴシエーションの誤認識を疑い、双方を固定にしてみるのもいいかもしれません。
(ただしどこのポートをどのモードの固定にしているかをしっかり管理する必要がありますが。。)

特にネットワーク機器(スイッチ)側とサーバ・PC側とのネゴシエーションの設定が違うと誤認識が発生する率が高いようです。
(片方がネゴシエーション固定、片方がオートネゴシエーションみたいな場合)


参考:
Auto-Negotiation (オートネゴシエーション) の問題 - ネットワーク管理者というお仕事
Auto-Negotiation(オートネゴシエーション)の問題 ~対策編 - ネットワーク管理者というお仕事
まだAuto-negotiation設定にしてますか?: sanonosa システム管理コラム集
スイッチ・ネットワークのトラブル対処法――(1) 第3回 - 1週間で学ぶネットワークの要点:ITpro
インフラエンジニアに成る:オートネゴの問題がなくならない - livedoor Blog(ブログ)
Ethernet LAN - 全二重通信/半二重通信:フロー制御( ジャム信号/PAUSEフレーム )スイッチ~サーバ間は固定がいいようです。
ふじきち日記: L2 L3スイッチ オートネゴシェーションの不具合スイッチメーカーによるオートネゴシエーションの不具合でフロー制御が動かないことがあるようです。
[PR]
by jehoshaphat | 2010-10-24 21:46 | ネットワーク | Trackback | Comments(0)
バッチファイルでUNCをカレントディレクトリにしたい

共有フォルダ上に配置するバッチファイルから、相対パス指定で同じフォルダにあるexeを呼び出す処理が必要になりました。

で、バッチファイルに当初下記のように書いていました。


cd %~dp0
test.exe
pause


そうすると下記のようにUNCパスは使えないって怒られます。

CMD では UNC パスは現在のディレクトリとしてサポートされません。


で、調べた結果初めて知ったんですが、Windowsには pushd というコマンドもあるようです。

pushd コマンドは cd コマンドと同じようにカレントフォルダを移動するコマンドなんですが、違いはスタックでカレントフォルダの履歴を残すことです。そして、popd コマンドでひとつ前のフォルダに移動することができます。
これは非常に便利ですね。

この pushd コマンドですが、もう一つうれしい機能があり、それは UNC をカレントディレクトリにしようとすると適当な空きドライブに対して、ネットワークドライブを設定し、そのドライブに移動してカレントフォルダを指定してくれるようです。
つまり、UNCパスが使えるということですね。

ということで共有フォルダ上のバッチファイルを下記のように変更すればうまくいきました。

pushd %~dp0
test.exe
pause



参考:
ネットワークドライブでのバッチファイルの実行 - ULog
pushd/popdでフォルダを移動する - @IT
共有フォルダ上のバッチファイルのカレントパスはどこになる?
[PR]
by jehoshaphat | 2010-10-24 21:44 | 豆知識 | Trackback | Comments(1)
i-Filterがプロキシ情報をHTTPヘッダに載せなくなった?

i-Filterを6から7.5にバージョンアップしたんですが、どうやら7.5からはHTTPヘッダの環境変数にプロキシ情報を載せなくなったらしいです。

以前のバージョン(6)では、HTTP_VIA や HTTP_CACHE_CONTROL 変数に情報が出てました。

何故かはわかりませんが、プロキシ情報で無くなると、プロキシの設定が効いてるかどうか分からなくなるので非常に不便です。

なお、これらHTTPの環境変数は、環境変数チェッカー・えんぶぅ~ - Environmental Variables Checkerで確認できます。
[PR]
by jehoshaphat | 2010-10-24 21:41 | ネットワーク | Trackback | Comments(0)
(.Net,ADSI)識別名(DN)のエスケープ

ActiveDirectoryというかLDAPの仕様だと思うんですが、重複した識別名(DN)のオブジェクトは作成できません。
で、.Netから新規ActiveDirectoryユーザを作成するツールを作ったんですが、DNの重複チェックができていませんでした。(ログインアカウント名の重複チェックはできてたんですけどね。。)

それで、新規作成するユーザ名からDNを生成して、それがActiveDirectoryに存在するかどうかのチェックをすることにしました。

単純にユーザ名、OU名、ドメイン名からDNを生成して、生成されたDNが既にあるかどうかをチェックすればいいだけなんですが、どうやらDNにはエスケープすべき特殊文字があるようです。

それは、「#」、「,」、「+」、「"」、「\」、「<」、「>」、「;」のようです。

ということで、ユーザ名を¥でエスケープしてActiveDirectoryから検索するコードを書いてみました。(C#)
(既にOU名とドメイン名は分かってることとします。)

string username = "hoge#<> ,hoge+";
string ou = "OU=testou";
string domain ="DC=hogedomain,DC=jp";
 
//識別名(DN)を作るにあたって「#」、「,」、「+」、「"」、「\」、「<」、「>」、「;」はエスケープ
string strDN = return System.Text.RegularExpressions.Regex.Replace(username, "#|,|\\+|\"|\\|<|>|;", "\\$&");
//DN名生成
strDN = "CN=" + strDN + "," + ou + "," + domain;
 
DirectoryEntry mDrctEntry;
mDrctEntry = new DirectoryEntry(@"LDAP://domaincontroler/DC=hogedomain,DC=jp", "administrator", "Passwd");
// LDAP検索オブジェクトを作成
DirectorySearcher drSearch = new DirectorySearcher(mDrctEntry);
 
// アカウントフィルターを設定 識別名で検索
drSearch.Filter = "(distinguishedName=" + strDN + ")";
 
// 検索する
SearchResultCollection scn = drSearch.FindAll();
//見つからなければnullを返す。
if (scn == null || scn.Count <= 0){
//見つからなかった時の処理
}else{
//見つかった時の処理
}

特殊文字をエスケープする部分は正規表現を使って置換しています。
正規表現での置換は、Text.RegularExpressions.Regex クラスの Replace メソッドを使えばいいようです。
置換する文字列に $& を指定すると、パターンで引っ掛かった文字を使うことができるようです。
久しぶりに正規表現つかましたが、しょっちゅう触ってないと難しいですね。

もしかしたら、エスケープしてくれるようなメソッドがあるのかもしれませんが、見当たらなかったので今回は手で書きました。


参考:
2.4.4 特殊文字を含むDNの指定
TechNet:オブジェクト名
dobon:正規表現の基本
dobon:正規表現を使って文字列を置換する
[PR]
by jehoshaphat | 2010-10-24 21:35 | .Net開発 | Trackback | Comments(0)
(.Net)別ユーザでプロセスを起動する
C++ で Windows API を使って別のユーザでアプリケーションを書く方法は、(C++)別ユーザでプロセスを起動するで書きました。
今回は .Net でそれを実現する方法です。
基本的には、ProcessStartInfo. Domain , ProcessStartInfo.UserName , ProcessStartInfo.Password プロパティを指定して、Process.Start すればいいだけのようですね。

ただし、 ProcessStartInfo.Password は SecureString オブジェクトを指定しないといけないのが曲者です。
SecureString に文字列をセットするには、SecureString.AppendChar(char型) で一文字ずつセットしないといけないようです。

で、今回コンソールアプケーションを作成し、引数に指定されたユーザ名とパスワードで別アプリケーション(今回はバッチファイル)を起動するというコードを書く必要がありました。
下記のような感じすればいいみたいです。(C#)

static void Main(string[] args)
{
//コマンドライン引数に下記のように情報が入ることとする。
//1:ユーザ名 2:パスワード 3:実行ファイル名 4:ドメイン名 ちなみに0には必ず自身のexeのパスが入るらしい
//コマンドライン引数配列取得
string[] cmds;
cmds = System.Environment.GetCommandLineArgs();
 
//プロセスオブジェクト生成
Process proc = new Process();
// 起動するアプリケーションを設定する
proc.StartInfo.FileName = cmds[3];
// 起動するアプリケーションに対するコマンドライン引数を設定する
proc.StartInfo.Arguments = "args";
// ウィンドウを作成しないかどうかを設定する (初期値 false)trueにするとウィンドウ表示なしとなる
proc.StartInfo.CreateNoWindow = false;
// シェルを使用するかどうか設定する (初期値 true)falseにするとコンソールウィンドウが表示なしとなる
proc.StartInfo.UseShellExecute = true;
// 起動できなかった時にエラーダイアログを表示するかどうかを設定する (初期値 false)
proc.StartInfo.ErrorDialog = false;
 
//プロセス実行時のドメイン名(ローカルユーザの場合はnullを指定)
proc.StartInfo.Domain = cmds[4];
//プロセス実行時のユーザ名
proc.StartInfo.UserName = cmds[1];
//パスワード(ProcessStartInfo.PasswordはSecureStringで指定しないといけない)
SecureString password = new SecureString();
foreach (char c in cmds[2].ToCharArray())
{
//SecureStringの文字追加
password.AppendChar(c);
}
//プロセス実行時のユーザのパスワード指定
proc.StartInfo.Password = password;
 
// 起動時のウィンドウの状態を設定する
proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal; //通常
// 起動する
proc.Start();
//起動したプロセスが終わるまで待つ。(60秒待つ)
proc.WaitForExit(60000);
 
//終了コード取得
int iExitCode = proc.ExitCode;
Console.WriteLine(iExitCode.ToString());
//終了コードをOSに返して終了
Environment.Exit(iExitCode);
}

上記で、ProcessStartInfoクラスに情報をセットする方法でしたが、それとは別に Process.Start のスタティックメソッドでプロセスを簡単に起動したい場合は、Process.Start(実行ファイル名,ユーザ名,パスワード,ドメイン名) としてもいいようです。


参考:
@IT:別のユーザーでほかのアプリケーションを実行するには?
@IT:コマンド・プロンプトを表示せずにコンソール・アプリケーションを実行するには?ProcessStartInfo.CreateNoWindow、ProcessStartInfo.UseShellExecuteプロパティがキックしたプロセスの表示にどう影響するかが参考になります。
C# - 細かい条件を指定してプログラムを起動する
[PR]
by jehoshaphat | 2010-10-24 21:33 | .Net開発 | Trackback | Comments(0)
(.Net)コマンドライン引数を取得する方法

コマンドライン引数の取得ですが大きく二つあるようです。

1.Environmentクラスを使う方法
Environment.CommandLine プロパティに自身のパスも含めたコマンドライン引数全体が格納されているようです。
ただこれだと使い辛いので普通は Environment.GetCommandLineArgs メソッドを使います。
Environment.GetCommandLineArgs メソッドを使うと自身のパスも含めたコマンドライン引数を文字列の配列として取得できるようです。(0番目は自身のexeのパス名となる)


2.Mainメソッドのパラメータを使う方法
これはCの時代から有る方法ですね。エントリポイントとなる Main メソッドの引数がコマンドライン引数となります。(自身のパスが引数となることはありません)


ちなみに、VisualStudioでデバッグ時にコマンドライン引数を渡したい場合はプロジェクトのプロパティの デバッグ → コマンドライン引数 に設定することで可能です。


参考:
dobon:起動時のコマンドライン引数を取得する
[PR]
by jehoshaphat | 2010-10-24 10:43 | .Net開発 | Trackback | Comments(0)
cacls.exe を使ってACL(NTFSアクセス権)を設定中に データが無効です と言われる

(cacls.exe を使ったACL(NTFSアクセス権)設定はcacls.exe を使ってACL(NTFSアクセス権)を設定するを参照)

cacls.exe を使った下記のようなバッチファイルで、テスト実行をしていたんですが、実行時に「データが無効です。」というメッセージが出てきます。

バッチファイル名:test.bat
rem @echo off
cd /d %~dp0
rem アクセス権設定 (第一引数にユーザ名があるとする)
cacls.exe "\\filesv\user\%1" /E /T /G "hogedomain\%1":C

実行時は下記のようにしてます。

>test.bat userA

ファイルサーバ上の個人フォルダに対して変更権限を持たすというものです。

で、いろいろ調査した結果、ACL適用先フォルダに既にuserAに対するフルコントロールが与えられてました。
どうやら、既にアクセス権を持っているのに、/G で既に設定されているより弱いアクセス権追加しようとすると、「データが無効です。」と表示される仕様のようです。
この不親切なメッセージで数時間潰されましたよ。。。
[PR]
by jehoshaphat | 2010-10-23 10:10 | 豆知識 | Trackback | Comments(0)