pysnmp:值与 SNMPWalk 不同——为什么?
pysnmp: Values not same as SNMPWalk -- WHY?
简而言之,
我正在利用 pysnmp 获取多个值来创建包含路由 table 信息的 .CSV。
当我在 OID 上执行 SNMPWALK 时:.1.3.6.1.2.1.4.20.1.3 我得到:
IP-MIB::ipAdEntNetMask.10.30.0.0 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.2 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.14 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.18 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.22 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.26 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.30 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.32 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.65 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.97 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.128 = IpAddress: 255.255.255.255
IP-MIB::ipAdEntNetMask.127.0.0.50 = IpAddress: 255.0.0.0
在我的 pysnmp 脚本中使用相同的方法时,我得到以下输出:
-> snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))
(Pdb) pprint.pprint(snmpNetMAsk)
[[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.0)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.2)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.14)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.18)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.22)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.26)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.30)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.32)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.65)),
IpAddress(hexValue='fffffff8'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.97)),
IpAddress(hexValue='fffffff8'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.128)),
IpAddress(hexValue='ffffffff'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.127.0.0.50)),
IpAddress(hexValue='ff000000'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.0)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.2)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.14)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.18)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.22)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.26)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.30)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.32)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.65)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.97)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.128)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.127.0.0.50)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.5.10.30.0.0)), Integer(18024))]]
你可以清楚地看到,我所有的值都是十六进制的,然后复制到一些整数。我不完全明白这里发生了什么。在终端中 运行 一个 snmpwalk 并将其捕获到一个文件,然后使用 python 脚本编辑该文件似乎更容易。如果有一种方法可以使用 pysnnmp 维护字典中的值,我宁愿这样做。我只是在自己搜索了几天之后才问这个问题。感谢您的帮助!
编辑:显示我正在使用的脚本的完整版本。
#!/usr/bin/python
import pprint
import pysnmp
from snmp_helper import *
def snmpDictClean(input_list, input_num):
output_dict = dict()
for varBindTableRow in input_list:
for name, val in varBindTableRow:
name = str(name)
val = str(val)
splitKey = name.split('.')
del splitKey[0:input_num]
splitKey = '.'.join(splitKey)
output_dict[splitKey] = val
return output_dict
def main():
ipCidrRouteIfIndex = '.1.3.6.1.2.1.4.24.4.1.5'
ifDescr = '.1.3.6.1.2.1.2.2.1.2'
ipAdEntIfIndex = '.1.3.6.1.2.1.4.20.1.2'
ipAdEntNetMask = '.1.3.6.1.2.1.4.20.1.3'
# SNMPv3 Connection Parameters
a_user = 'USER'
auth_key = 'AUTH_KEY'
encrypt_key = 'ENCRYPT_KEY'
snmp_user = (a_user, auth_key, encrypt_key)
ipAddr = [
'host1',
'host2',
]
for hlist in ipAddr:
snmpDevice = (hlist, 161)
snmpRoute = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipCidrRouteIfIndex)
snmpRoute = (snmpDictClean(snmpRoute, 11))
snmpIfDescr = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ifDescr)
snmpIfDescr = (snmpDictClean(snmpIfDescr, 10))
snmpIpIndex = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntIfIndex)
snmpIpIndex = (snmpDictClean(snmpIpIndex, 10))
snmpNetMAsk = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntNetMask)
snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))
import pdb; pdb.set_trace()
if __name__ == '__main__':
main()
我正在使用来自@ktbyers 的snmp_helper:https://github.com/ktbyers/pynet/tree/master/snmp。我将其修改为使用 snmpbulk 而不是 get。
# Python
from __future__ import print_function
from pysnmp.entity.rfc3413.oneliner import cmdgen
import pprint
def snmp_bulk_oid_v3(snmp_device, snmp_user, oid='', auth_proto='sha',
encrypt_proto='des', display_errors=True):
# unpack snmp_user
a_user, auth_key, encrypt_key = snmp_user
auth_proto_map = {
'sha': cmdgen.usmHMACSHAAuthProtocol,
'md5': cmdgen.usmHMACMD5AuthProtocol,
'none': cmdgen.usmNoAuthProtocol
}
if auth_proto in auth_proto_map.keys():
auth_protocol = auth_proto_map[auth_proto]
else:
raise ValueError("Invalid authentication protocol specified: %s" % auth_proto)
encrypt_proto_map = {
'des': cmdgen.usmDESPrivProtocol,
'3des': cmdgen.usm3DESEDEPrivProtocol,
'aes128': cmdgen.usmAesCfb128Protocol,
'aes192': cmdgen.usmAesCfb192Protocol,
'aes256': cmdgen.usmAesCfb256Protocol,
'none': cmdgen.usmNoPrivProtocol,
}
if encrypt_proto in encrypt_proto_map.keys():
encrypt_protocol = encrypt_proto_map[encrypt_proto]
else:
raise ValueError("Invalid encryption protocol specified: %s" % encrypt_proto)
# Create a PYSNMP cmdgen object
cmdGen = cmdgen.CommandGenerator()
(errorIndication, errorStatus, errorIndex, varBindTable) = cmdGen.bulkCmd(
cmdgen.UsmUserData(a_user, auth_key, encrypt_key,
authProtocol=auth_protocol,
privProtocol=encrypt_protocol, ),
cmdgen.UdpTransportTarget(snmp_device),
0,
25,
oid,
lookupNames=True, lookupValues=True
)
if errorIndication:
print(errorIndication)
else:
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
)
)
'''
else:
for varBindTableRow in varBindTable:
for name, val in varBindTableRow:
snmp_data = print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
'''
return varBindTable
如果您希望输出看起来相同,则需要使用 pprint
以外的格式来格式化它。试试这个:
for row in snmpNetMAsk:
for name, val in row:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
参考:http://pysnmp.sourceforge.net/examples/current/v3arch/oneliner/manager/cmdgen/getnext-v2c.html
您看到的是从 SNMP 代理收到的原始 OID 值对。要使用 pysnmp 获得更漂亮的输出,您需要让它通过 MIB 解析器传递接收到的 OID 值对。使用 this 示例作为原型,但另外加载 IP-MIB,如下所示:
...
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
cmdgen.CommunityData('public'),
cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)),
MibVariable('1.3.6.1.2.1.4.20.1.3').loadMibs('IP-MIB'),
lookupNames=True, lookupValues=True
)
...
确保使用 .prettyPrint() 进行打印 OIDs/values。
请记住,您需要将传统的 ASN.1 IP-MIB 转换为 pysnmp 格式,以便 pysnmp 可以使用它。您可以使用(尚处于实验阶段)pysmi MIB compiler 或使用 pysnmp 附带的 build-pysnmp-mib 脚本来做到这一点,或者只需从 PyPI (pip pysnmp-mibs) 安装预构建的 MIB 集合。
如果您获得自己的 IP-MIB.py,而不是使用 pysnmp-mibs 包,您可以将您的 IP-MIB.py 放入一个目录并通过 [= 将 pysnmp 指向该自定义位置33=]() 方法。有关详细信息,请参阅 this example。所有 MibVariable 方法都可以这样链接:
MibVariable('1.3.6.1.2.1.4.20.1.3').addMibSource('/etc/pymibs').loadMibs('IP-MIB')
或者您可以通过指定要在初始化程序中加载的 MIB 名称来跳过 .loadMibs():
MibVariable('IP-MIB', 'ipRoute').addMibSource('/etc/pymibs')
MibVariable class 是 ObjectIdentifier 的多态,因此这两者可以互换使用。但是 MibVariable 可以从 MIB 文件中收集更多与它初始化时使用的 OID 相关的信息。例如,MibVariable 可能包含与相关 OID 相关联的 MIB 模块名称和 MIB 符号名称。它还可以保存与该 OID 关联的值的 SNMP 数据类型。
您可以将 MibVariable 视为 SNMPv2-SMI 的 OBJECT-TYPE 宏的实现。
简而言之,
我正在利用 pysnmp 获取多个值来创建包含路由 table 信息的 .CSV。
当我在 OID 上执行 SNMPWALK 时:.1.3.6.1.2.1.4.20.1.3 我得到:
IP-MIB::ipAdEntNetMask.10.30.0.0 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.2 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.14 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.18 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.22 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.26 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.30 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.32 = IpAddress: 255.255.255.254
IP-MIB::ipAdEntNetMask.10.30.0.65 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.97 = IpAddress: 255.255.255.248
IP-MIB::ipAdEntNetMask.10.30.0.128 = IpAddress: 255.255.255.255
IP-MIB::ipAdEntNetMask.127.0.0.50 = IpAddress: 255.0.0.0
在我的 pysnmp 脚本中使用相同的方法时,我得到以下输出:
-> snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))
(Pdb) pprint.pprint(snmpNetMAsk)
[[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.0)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.2)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.14)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.18)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.22)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.26)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.30)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.32)),
IpAddress(hexValue='fffffffe'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.65)),
IpAddress(hexValue='fffffff8'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.97)),
IpAddress(hexValue='fffffff8'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.10.30.0.128)),
IpAddress(hexValue='ffffffff'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.3.127.0.0.50)),
IpAddress(hexValue='ff000000'))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.0)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.2)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.14)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.18)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.22)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.26)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.30)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.32)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.65)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.97)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.10.30.0.128)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.4.127.0.0.50)), Integer(1))],
[(MibVariable(ObjectName(1.3.6.1.2.1.4.20.1.5.10.30.0.0)), Integer(18024))]]
你可以清楚地看到,我所有的值都是十六进制的,然后复制到一些整数。我不完全明白这里发生了什么。在终端中 运行 一个 snmpwalk 并将其捕获到一个文件,然后使用 python 脚本编辑该文件似乎更容易。如果有一种方法可以使用 pysnnmp 维护字典中的值,我宁愿这样做。我只是在自己搜索了几天之后才问这个问题。感谢您的帮助!
编辑:显示我正在使用的脚本的完整版本。
#!/usr/bin/python
import pprint
import pysnmp
from snmp_helper import *
def snmpDictClean(input_list, input_num):
output_dict = dict()
for varBindTableRow in input_list:
for name, val in varBindTableRow:
name = str(name)
val = str(val)
splitKey = name.split('.')
del splitKey[0:input_num]
splitKey = '.'.join(splitKey)
output_dict[splitKey] = val
return output_dict
def main():
ipCidrRouteIfIndex = '.1.3.6.1.2.1.4.24.4.1.5'
ifDescr = '.1.3.6.1.2.1.2.2.1.2'
ipAdEntIfIndex = '.1.3.6.1.2.1.4.20.1.2'
ipAdEntNetMask = '.1.3.6.1.2.1.4.20.1.3'
# SNMPv3 Connection Parameters
a_user = 'USER'
auth_key = 'AUTH_KEY'
encrypt_key = 'ENCRYPT_KEY'
snmp_user = (a_user, auth_key, encrypt_key)
ipAddr = [
'host1',
'host2',
]
for hlist in ipAddr:
snmpDevice = (hlist, 161)
snmpRoute = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipCidrRouteIfIndex)
snmpRoute = (snmpDictClean(snmpRoute, 11))
snmpIfDescr = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ifDescr)
snmpIfDescr = (snmpDictClean(snmpIfDescr, 10))
snmpIpIndex = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntIfIndex)
snmpIpIndex = (snmpDictClean(snmpIpIndex, 10))
snmpNetMAsk = snmp_bulk_oid_v3(snmpDevice, snmp_user, oid=ipAdEntNetMask)
snmpNetMAsk = (snmpDictClean(snmpNetMAsk, 10))
import pdb; pdb.set_trace()
if __name__ == '__main__':
main()
我正在使用来自@ktbyers 的snmp_helper:https://github.com/ktbyers/pynet/tree/master/snmp。我将其修改为使用 snmpbulk 而不是 get。
# Python
from __future__ import print_function
from pysnmp.entity.rfc3413.oneliner import cmdgen
import pprint
def snmp_bulk_oid_v3(snmp_device, snmp_user, oid='', auth_proto='sha',
encrypt_proto='des', display_errors=True):
# unpack snmp_user
a_user, auth_key, encrypt_key = snmp_user
auth_proto_map = {
'sha': cmdgen.usmHMACSHAAuthProtocol,
'md5': cmdgen.usmHMACMD5AuthProtocol,
'none': cmdgen.usmNoAuthProtocol
}
if auth_proto in auth_proto_map.keys():
auth_protocol = auth_proto_map[auth_proto]
else:
raise ValueError("Invalid authentication protocol specified: %s" % auth_proto)
encrypt_proto_map = {
'des': cmdgen.usmDESPrivProtocol,
'3des': cmdgen.usm3DESEDEPrivProtocol,
'aes128': cmdgen.usmAesCfb128Protocol,
'aes192': cmdgen.usmAesCfb192Protocol,
'aes256': cmdgen.usmAesCfb256Protocol,
'none': cmdgen.usmNoPrivProtocol,
}
if encrypt_proto in encrypt_proto_map.keys():
encrypt_protocol = encrypt_proto_map[encrypt_proto]
else:
raise ValueError("Invalid encryption protocol specified: %s" % encrypt_proto)
# Create a PYSNMP cmdgen object
cmdGen = cmdgen.CommandGenerator()
(errorIndication, errorStatus, errorIndex, varBindTable) = cmdGen.bulkCmd(
cmdgen.UsmUserData(a_user, auth_key, encrypt_key,
authProtocol=auth_protocol,
privProtocol=encrypt_protocol, ),
cmdgen.UdpTransportTarget(snmp_device),
0,
25,
oid,
lookupNames=True, lookupValues=True
)
if errorIndication:
print(errorIndication)
else:
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
)
)
'''
else:
for varBindTableRow in varBindTable:
for name, val in varBindTableRow:
snmp_data = print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
'''
return varBindTable
如果您希望输出看起来相同,则需要使用 pprint
以外的格式来格式化它。试试这个:
for row in snmpNetMAsk:
for name, val in row:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
参考:http://pysnmp.sourceforge.net/examples/current/v3arch/oneliner/manager/cmdgen/getnext-v2c.html
您看到的是从 SNMP 代理收到的原始 OID 值对。要使用 pysnmp 获得更漂亮的输出,您需要让它通过 MIB 解析器传递接收到的 OID 值对。使用 this 示例作为原型,但另外加载 IP-MIB,如下所示:
...
errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd(
cmdgen.CommunityData('public'),
cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161)),
MibVariable('1.3.6.1.2.1.4.20.1.3').loadMibs('IP-MIB'),
lookupNames=True, lookupValues=True
)
...
确保使用 .prettyPrint() 进行打印 OIDs/values。
请记住,您需要将传统的 ASN.1 IP-MIB 转换为 pysnmp 格式,以便 pysnmp 可以使用它。您可以使用(尚处于实验阶段)pysmi MIB compiler 或使用 pysnmp 附带的 build-pysnmp-mib 脚本来做到这一点,或者只需从 PyPI (pip pysnmp-mibs) 安装预构建的 MIB 集合。
如果您获得自己的 IP-MIB.py,而不是使用 pysnmp-mibs 包,您可以将您的 IP-MIB.py 放入一个目录并通过 [= 将 pysnmp 指向该自定义位置33=]() 方法。有关详细信息,请参阅 this example。所有 MibVariable 方法都可以这样链接:
MibVariable('1.3.6.1.2.1.4.20.1.3').addMibSource('/etc/pymibs').loadMibs('IP-MIB')
或者您可以通过指定要在初始化程序中加载的 MIB 名称来跳过 .loadMibs():
MibVariable('IP-MIB', 'ipRoute').addMibSource('/etc/pymibs')
MibVariable class 是 ObjectIdentifier 的多态,因此这两者可以互换使用。但是 MibVariable 可以从 MIB 文件中收集更多与它初始化时使用的 OID 相关的信息。例如,MibVariable 可能包含与相关 OID 相关联的 MIB 模块名称和 MIB 符号名称。它还可以保存与该 OID 关联的值的 SNMP 数据类型。
您可以将 MibVariable 视为 SNMPv2-SMI 的 OBJECT-TYPE 宏的实现。