はじめに
SNMP(Simple Network Management Protocol)は、ルータやスイッチなどのネットワーク機器を監視・管理するためのプロトコルです。
SNMPv2では、SNMPv1にはなかったGetBulkRequestが追加され、複数のMIB情報を効率的に取得できるようになりました。
では、実際にGetNextRequestとGetBulkRequestでは、どの程度通信効率が変わるのでしょうか。
今回はCisco C1812JとRaspberry Piを使用し、同じMIB情報をGetNextとGetBulkで取得して、リクエスト数と実行時間の違いを比較してみました。
関連記事
以前の記事では、Cisco C1812JとRaspberry Piを使用し、SNMPv2cとSNMPv3の認証・暗号化の違いをWiresharkで比較しました。
今回は同じ検証環境を使い、SNMPの情報取得方式であるGetNextRequestとGetBulkRequestの通信効率を比較します。
関連記事: 【実機検証】Cisco C1812JとRaspberry PiでSNMPv2c・SNMPv3の違いをWiresharkで確認してみた
検証環境
使用機器
| 機器 | 用途 |
|---|---|
| Cisco C1812J | SNMPエージェント |
| Raspberry Pi | SNMPマネージャ |
| Wireshark | パケット解析 |
| Net-SNMP | SNMPコマンド実行 |
| tcpdump | パケットキャプチャ |
Cisco C1812JのIOSバージョンは以下のとおりです。
Cisco IOS Software, C181X Software
Version 12.4(15)T8
System image file is
"flash:c181x-advipservicesk9-mz.124-15.T8.bin"
ネットワーク構成
+---------------------+
| Cisco C1812J |
| |
| 192.168.20.1 |
| SNMP Agent |
+----------+----------+
|
| LANケーブル(直結)
|
+----------+----------+
| Raspberry Pi |
| |
| SNMP Manager |
| tcpdump |
+---------------------+
SNMPv2cを使用し、コミュニティ文字列は検証用のPublic01としています。
GetNextRequestとGetBulkRequestの違い
GetNextRequestとは
GetNextRequestは、指定したOIDの次に位置するOIDを取得するためのSNMP操作です。
MIBツリーを順番にたどりながら情報を取得できます。
例えば、複数のOIDを取得する場合、以下のようにリクエストとレスポンスを繰り返します。
SNMP Manager SNMP Agent
| |
|--- GetNextRequest ->|
|<---- GetResponse ---|
| |
|--- GetNextRequest ->|
|<---- GetResponse ---|
| |
|--- GetNextRequest ->|
|<---- GetResponse ---|
1つのOIDを指定したGetNextRequestでは、基本的に1つの次のOIDを取得します。
そのため、多数のOIDを順番に取得する場合、リクエスト回数が増加します。
なお、GetNextRequest自体は複数のOIDを指定することもできますが、今回使用するsnmpwalkでは1つのOIDを起点に順次取得しています。
GetBulkRequestとは
GetBulkRequestはSNMPv2で追加された操作です。
1回のリクエストで複数のOIDをまとめて取得できます。
SNMP Manager SNMP Agent
| |
|--- GetBulkRequest ->|
| |
|<---- GetResponse ---|
| OID 1 |
| OID 2 |
| OID 3 |
| ... |
| OID 10 |
GetBulkRequestでは、max-repetitionsを指定することで、繰り返し取得する最大回数を要求できます。
ただし、実際に返されるOIDの数はエージェントの実装や応答サイズなどによって変わります。
今回はmax-repetitions=10で検証します。
検証対象のMIB
今回はCisco C1812Jのインターフェース情報を取得します。
対象OIDは以下です。
1.3.6.1.2.1.2.2
これはMIB-IIのifTableです。
ifTableには、インターフェースに関するさまざまな情報が含まれています。
| 項目 | 内容 |
|---|---|
| ifIndex | インターフェース番号 |
| ifDescr | インターフェース名 |
| ifType | インターフェース種別 |
| ifMtu | MTU |
| ifSpeed | インターフェース速度 |
| ifAdminStatus | 管理状態 |
| ifOperStatus | 動作状態 |
このifTableをGetNextとGetBulkで取得し、比較します。
GetNextRequestで情報取得
Raspberry Piから以下のコマンドを実行します。
snmpwalk -v2c -c Public01 192.168.20.1 1.3.6.1.2.1.2.2
snmpwalkはGetNextRequestを繰り返し送信して、MIBツリーを順番に取得します。
取得結果の一部は以下のとおりです。
iso.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
iso.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2
...
iso.3.6.1.2.1.2.2.1.22.21 = OID: ccitt.0
iso.3.6.1.2.1.2.2.1.22.22 = OID: ccitt.0
iso.3.6.1.2.1.2.2.1.22.23 = OID: ccitt.0
正常にifTableの情報を取得できました。
GetBulkRequestで情報取得
続いてGetBulkRequestを使用します。
snmpbulkwalk -v2c -c Public01 -Cr10 192.168.20.1 1.3.6.1.2.1.2.2
-Cr10は、GetBulkRequestのmax-repetitionsを10に指定するオプションです。
取得結果の一部は以下です。
iso.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
iso.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2
iso.3.6.1.2.1.2.2.1.1.3 = INTEGER: 3
...
iso.3.6.1.2.1.2.2.1.22.21 = OID: ccitt.0
iso.3.6.1.2.1.2.2.1.22.22 = OID: ccitt.0
iso.3.6.1.2.1.2.2.1.22.23 = OID: ccitt.0
こちらも正常にifTableの情報を取得できました。
両コマンドで同じOID範囲の情報を取得できているため、次に通信効率を比較します。
Wiresharkでリクエスト数を比較
Raspberry Piでtcpdumpを使用し、SNMPパケットをキャプチャします。
GetNextRequestのキャプチャ
sudo tcpdump -i eth0 -nn -s 0 -w getnext.pcap 'host 192.168.20.1 and udp port 161'
キャプチャ中に、別のターミナルからsnmpwalkを実行します。
GetBulkRequestのキャプチャ
sudo tcpdump -i eth0 -nn -s 0 -w getbulk.pcap 'host 192.168.20.1 and udp port 161'
キャプチャ中にsnmpbulkwalkを実行します。
それぞれのpcapファイルをWiresharkで開き、GetNextRequestとGetBulkRequestのパケット数を確認しました。
検証結果
| 項目 | GetNextRequest | GetBulkRequest |
|---|---|---|
| リクエスト数 | 928 | 94 |
| max-repetitions | なし | 10 |

GetNextRequestでは928パケット、GetBulkRequestでは94パケットでした。


削減率を計算すると、

となります。
GetBulkRequestによってリクエスト数を約89.9%削減できました。
これはGetBulkRequestが1回のリクエストで複数のOIDをまとめて取得できるためです。
今回の結果では、GetNextRequestの約9.9分の1のリクエスト回数で情報を取得できています。
※ 今回の数値はWiresharkで数えたリクエストパケット数です。GetResponseを含む総パケット数とは区別しています。
実行時間を比較
続いて、リクエスト数の削減が実際の実行時間にどの程度影響するのかを確認します。
Linuxのtimeコマンドを使用して測定しました。
GetNextRequest
time sh -c 'snmpwalk -v2c -c Public01 192.168.20.1 1.3.6.1.2.1.2.2 > /dev/null'
GetBulkRequest
time sh -c 'snmpbulkwalk -v2c -c Public01 -Cr10 192.168.20.1 1.3.6.1.2.1.2.2 > /dev/null'
それぞれ5回ずつ実行し、realの値を比較しました。
測定結果
| 測定回 | GetNext | GetBulk |
|---|---|---|
| 1回目 | 0.434秒 | 0.092秒 |
| 2回目 | 0.426秒 | 0.127秒 |
| 3回目 | 0.534秒 | 0.102秒 |
| 4回目 | 0.447秒 | 0.092秒 |
| 5回目 | 0.447秒 | 0.103秒 |
| 平均 | 0.4576秒 | 0.1032秒 |

平均実行時間の短縮率を計算すると、

となります。
GetBulkRequestはGetNextRequestより平均実行時間が約77.4%短くなりました。
これは、約4.4倍の速度で情報取得を完了したことになります。
検証結果の考察
今回の結果をまとめると、以下のようになりました。
| 項目 | GetNext | GetBulk | 改善率 |
|---|---|---|---|
| リクエスト数 | 928 | 94 | 約89.9%削減 |
| 平均実行時間 | 0.4576秒 | 0.1032秒 | 約77.4%短縮 |
GetBulkRequestを使用することで、リクエスト数と実行時間の両方を削減できました。
一方、リクエスト数の削減率と実行時間の短縮率は一致しませんでした。
これは、通信の往復回数だけでなく、ルータ側のMIB処理、応答パケットのサイズ、SNMPマネージャ側の処理時間なども影響するためと考えられます。
また、今回の検証環境ではCisco C1812JとRaspberry PiをLANケーブルで直接接続しているため、ネットワーク遅延が小さい状態での測定となっています。
ネットワーク遅延が大きい環境では、リクエスト回数を削減できるGetBulkRequestの効果がさらに大きくなる可能性があります。
ただし、GetBulkRequestは1回の応答サイズが大きくなるため、総通信バイト数まで必ず削減されるわけではありません。
まとめ
今回はCisco C1812JとRaspberry Piを使用し、SNMPのGetNextRequestとGetBulkRequestを比較しました。
実機検証の結果、以下のことが分かりました。
- GetNextRequestは、MIB情報を順番に取得するため、リクエスト数が多くなりやすい
- GetBulkRequestは、複数のOIDをまとめて取得できる
- 今回の検証では、GetBulkRequestによってリクエスト数が約89.9%削減された
- 平均実行時間も約77.4%短縮された
- リクエスト数の削減率と実行時間の短縮率は必ずしも一致しない
GetBulkRequestは、特に多数のMIB情報を取得する場合に有効な仕組みであることを実機で確認できました。
次回の検証
次回はSNMPの通知方式であるTrapとInformRequestを比較し、受信確認応答の有無や通信の流れをWiresharkで確認したいと思います。

