2011年05月27日
実践SNMP+Java MIBテーブルのフェッチ(TableUtils)
MIBテーブルとはデータベースのテーブルと同様に行と列で管理されたMIBオブジェクトの集まりです。
MIBテーブルを理解するにはMIBブラウザを使って視覚的に捉えることも重要です。ここではiREASONING社のMIBブラウザ(無料)を使って説明します。

これを見ると、ifTableにはifIndex, ifDescr, ifTypeなどがエントリされており、テーブルのインデックスはifIndexであることがわかります(鍵のアイコンになっています)。もちろん、MIBファイルを直接確認しても良いでしょう。
ifEntry OBJECT-TYPESYNTAX IfEntryACCESS not-accessibleSTATUS mandatoryDESCRIPTION"An interface entry containing objects at thesubnetwork layer and below for a particularinterface."INDEX { ifIndex }
このようにMIBテーブルには必ず行を特定する為のIndexが定義されており、この値を使って各OIDのインスタンスを指し示す事が出来ます(例:ifDescr.1)。尚、テーブルによっては複合indexの場合もあります。
早速、SNMP4Jを使ってifTableの値を幾つかフェッチしてみましょう。
Javaコード
public void getTable() throws IOException {
String host = "localhost";
//host = "192.168.10.1";
int port = 161;
String community = "public";
String[] oids = {
".1.3.6.1.2.1.2.2.1.1", // ifIndex
".1.3.6.1.2.1.2.2.1.2", // ifType
".1.3.6.1.2.1.2.2.1.3", // ifMtu
".1.3.6.1.2.1.2.2.1.4", // ifSpeed
".1.3.6.1.2.1.2.2.1.5" // ifPhysAddress
};
Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
snmp.listen();
CommunityTarget comTgt = new CommunityTarget();
comTgt.setAddress(new UdpAddress(host+"/"+port));
comTgt.setCommunity(new OctetString(community)); // snmp community.
comTgt.setVersion(SnmpConstants.version2c);
TableUtils table = new TableUtils(snmp, new DefaultPDUFactory());
OID[] columnOIDs = new OID[oids.length];
for (int i=0; i<oids.length; i++) {
columnOIDs[i] = new OID(oids[i]);
}
OID lowerBoundIndex = null; //new OID("1");
OID upperBoundIndex = null;
// getTable params.
// Target target, OID[] columnOIDs, OID lowerBoundIndex, OID upperBoundIndex
List result = table.getTable(
comTgt, columnOIDs, lowerBoundIndex, upperBoundIndex);
for (int i=0; i<result.size(); i++) {
TableEvent event = (TableEvent) result.get(i);
/*
* org.snmp4j.util.RetrievalEvent
* public static final int STATUS_EXCEPTION -4
* public static final int STATUS_OK 0
* public static final int STATUS_REPORT -3
* public static final int STATUS_TIMEOUT -1
* public static final int STATUS_WRONG_ORDER -2
*/
int status = event.getStatus();
if (status == RetrievalEvent.STATUS_OK) {
VariableBinding[] vbs = event.getColumns();
System.out.print("table index:"+event.getIndex().toString()+"¥t -> ");
for (int j=0; j<vbs.length; j++) {
VariableBinding vb = vbs[j];
System.out.print(
//vb.getOid()+"->"+
vb.getVariable()+"¥t");
}
}
System.out.println();
}
snmp.close(); // close local udp port and response dispacher.
}実行結果(サンプル)
table index:1 -> 1 lo0 24 16384 0
table index:2 -> 2 gif0 55 1280 0
table index:3 -> 3 stf0 57 1280 0
table index:4 -> 4 en0 6 1500 1000000000
table index:5 -> 5 en1 6 1500 10000000
table index:6 -> 6 fw0 144 4078 10000000
説明
7~13行目でifTableから取得するOIDの配列(ifIndex~ifPhysAddress)を定義しています。
22行目でテーブルのフェッチに利用するTabaleUtilsクラスのインスタンスを生成し、33行目でgetTableメソッドを呼出し、フェッチを実行しています。
ポーリング結果は、行に相当するTableEventインスタンスのListとして戻ります。この値を36行目以降で取り出しています。もし、OIDも合わせて確認したい場合、53行目のコメントを外してください。
TableEventクラスの面白い(便利な)ところはgetIndexメソッドでテーブルのインデックスを取得出来るところです。このIndexを取り出すという作業は大して難しい事では無く、VariableBinding::getOidメソッドの戻り値であるOIDインスタンスの値を分解すれば良いのですが、SNMP4J(API)側で提供してくれるとコード量も減って便利です。試しに複合Indexを持つipNetToMediaTableもフェッチしてみましょう。

実行結果は次の通りです。
table index:5.192.168.0.1 -> 00:a0:de:36:ff:30 1
table index:5.192.168.0.12 -> 90:27:e4:3a:57:69 1
table index:5.192.168.0.14 -> 00:1a:a0:90:17:81 1
table index:5.192.168.0.25 -> cc:08:e0:c9:f8:da 1
table index:5.192.168.0.30 -> 00:21:70:33:15:e3 1
table index:5.192.168.0.132 -> 00:0c:29:bd:1b:07 1
table index:5.192.168.0.135 -> 00:0c:29:d6:a4:89 1
複合indexでも問題ありませんね(難しい処理では無いので当然なのですが)。
最後にTableUtils::getTableメソッドの引数であるlowerBoundIndex、upperBoundIndexについて説明します。これは開始、終了行のインデックスを使い、フェッチ範囲を指定する為のオプションです。もし、29行目のlowerBoundIndexを new OID("1") とすると、実行結果は次のようになります。
table index:2 -> 2 gif0 55 1280 0
table index:3 -> 3 stf0 57 1280 0
table index:4 -> 4 en0 6 1500 1000000000
table index:5 -> 5 en1 6 1500 10000000
table index:6 -> 6 fw0 144 4078 10000000
index:1の行が無くなっていますね。つまりlowerBoundIndexを指定するとそれ以降のインデックス持つ行のみ取得します。upperBoundIndexはこの逆です。
実践で使えるか?
僕自身はTableUtilsクラスを利用していないので何とも言えません。僕の場合、より細かなチューニングが出来るよう、GetNext/GetBulkを組み合わせた独自クラスを用意しMIBテーブルをフィッチしています。
TableUtilsクラスはHight Level APIと言われる、ある程度の処理までをAPI側で隠蔽してくれる便利なクラスですが、その反面チューニングが難しい、SNMP4J APIに依存したアプリケーションになる、というリスクもあります。
複雑・巨大なテーブルはフェッチしない、SNMP4Jに依存しても問題無い、という方は是非どうぞ。
オライリー・ジャパン
売り上げランキング: 49043
技術評論社
売り上げランキング: 18925









![Transcend SDHCカード 32GB Class10 (無期限保証) [フラストレーションフリーパッケージ (FFP)] TS32GSDHC10E](http://ecx.images-amazon.com/images/I/51XB52M0hWL._SL160_.jpg)






















![闘うプログラマー[新装版] ビル・ゲイツの野望を担った男達](http://ecx.images-amazon.com/images/I/51cCs-aJ6xL._SL160_.jpg)
