Tables
Efficiently query SNMP tables.
Overview
SNMP tables are indexed collections of rows. Each row has the same columns, indexed by one or more values. For example, ifTable is indexed by ifIndex:
ifDescr.1 = "lo"
ifDescr.2 = "eth0"
ifDescr.3 = "eth1"
ifType.1 = softwareLoopback(24)
ifType.2 = ethernetCsmacd(6)
ifType.3 = ethernetCsmacd(6)get_table
Retrieve an entire table as a structured dict:
from snmpkit.manager import Manager
async with Manager("192.168.1.1") as mgr:
# Walk ifTable entry OID
table = await mgr.get_table("1.3.6.1.2.1.2.2.1")
for index, columns in table.items():
print(f"Row {index}: {columns}")Output:
{
(1,): {2: Value.OctetString(b"lo"), 3: Value.Integer(24), 8: Value.Integer(1)},
(2,): {2: Value.OctetString(b"eth0"), 3: Value.Integer(6), 8: Value.Integer(1)},
(3,): {2: Value.OctetString(b"eth1"), 3: Value.Integer(6), 8: Value.Integer(2)},
}The return type is dict[tuple[int, ...], dict[int, Value]] where:
- Keys are index tuples (e.g.,
(1,)for single-index,(192, 168, 1, 1)for IP-indexed tables) - Values are dicts mapping column number to Value
Column Filtering
Only retrieve specific columns:
# Only ifDescr (2) and ifOperStatus (8)
table = await mgr.get_table(
"1.3.6.1.2.1.2.2.1",
columns=[2, 8],
)
for index, cols in table.items():
name = str(cols.get(2, ""))
status = str(cols.get(8, ""))
print(f"Interface {index}: {name} - {'up' if status == '1' else 'down'}")Bulk Size Tuning
Adjust bulk_size based on table width and network conditions:
# Large tables: bigger batches, fewer round-trips
table = await mgr.get_table("1.3.6.1.2.1.2.2.1", bulk_size=50)
# Slow devices: smaller batches
table = await mgr.get_table("1.3.6.1.2.1.2.2.1", bulk_size=10)Default bulk_size is 25. Most devices support 25-50. Some older devices may only support 10.
Manual Table Walk
For more control, walk columns individually:
Single Column
async with Manager("192.168.1.1") as mgr:
async for oid, value in mgr.bulk_walk("1.3.6.1.2.1.2.2.1.2"):
idx = oid.split(".")[-1]
print(f"Interface {idx}: {value}")Multiple Columns
async def get_interface_table(mgr: Manager) -> dict[str, dict]:
table = {}
base = "1.3.6.1.2.1.2.2.1"
columns = {
"ifDescr": "2",
"ifType": "3",
"ifOperStatus": "8",
}
for col_name, col_id in columns.items():
async for oid, value in mgr.bulk_walk(f"{base}.{col_id}"):
idx = oid.split(".")[-1]
if idx not in table:
table[idx] = {}
table[idx][col_name] = value
return tableCompound Indices
Some tables have multi-part indices. get_table handles this automatically — the index tuple will have multiple elements:
IP Route Table
# ipRouteTable is indexed by destination IP (4 octets)
table = await mgr.get_table("1.3.6.1.2.1.4.21.1")
for index, cols in table.items():
# index is a tuple like (10, 0, 0, 0)
dest = ".".join(str(i) for i in index)
print(f"Route to {dest}")TCP Connection Table
# tcpConnTable indexed by (localAddr x4, localPort, remoteAddr x4, remotePort)
table = await mgr.get_table("1.3.6.1.2.1.6.13.1")
for index, cols in table.items():
local_addr = ".".join(str(i) for i in index[:4])
local_port = index[4]
remote_addr = ".".join(str(i) for i in index[5:9])
remote_port = index[9]
print(f"{local_addr}:{local_port} -> {remote_addr}:{remote_port}")Common Tables
IF-MIB::ifTable
IF_TABLE_ENTRY = "1.3.6.1.2.1.2.2.1"
# Column numbers
IF_INDEX = 1
IF_DESCR = 2
IF_TYPE = 3
IF_MTU = 4
IF_SPEED = 5
IF_PHYS_ADDRESS = 6
IF_ADMIN_STATUS = 7
IF_OPER_STATUS = 8
IF_IN_OCTETS = 10
IF_IN_ERRORS = 14
IF_OUT_OCTETS = 16
IF_OUT_ERRORS = 20IF-MIB::ifXTable (64-bit counters)
IFX_TABLE_ENTRY = "1.3.6.1.2.1.31.1.1.1"
IF_NAME = 1
IF_HC_IN_OCTETS = 6
IF_HC_OUT_OCTETS = 10
IF_HIGH_SPEED = 15
IF_ALIAS = 18Example: Interface Report
import asyncio
from snmpkit.manager import Manager
async def main():
async with Manager("192.168.1.1") as mgr:
table = await mgr.get_table(
"1.3.6.1.2.1.2.2.1",
columns=[2, 3, 5, 8, 10, 16],
)
print(f"{'Name':<15} {'Status':<8} {'Speed':<12} {'In (MB)':<12} {'Out (MB)':<12}")
print("-" * 60)
for idx, row in sorted(table.items()):
name = str(row.get(2, ""))
status = "up" if str(row.get(8, "")) == "1" else "down"
speed = int(str(row.get(5, "0"))) // 1_000_000
in_mb = int(str(row.get(10, "0"))) / 1024 / 1024
out_mb = int(str(row.get(16, "0"))) / 1024 / 1024
print(f"{name:<15} {status:<8} {speed:<12} {in_mb:<12.1f} {out_mb:<12.1f}")
asyncio.run(main())Next Steps
- Operations — Full API reference
- Traps — Trap and notification handling
Last updated on