"""
Requirements:
memoized-property
Setup:
./opt/bin/build-pysnmp-mib -o usr/mibs/BRIDGE-MIB.py etc/mibs/rfc1493.mib
Run:
PYSNMP_MIB_DIRS=usr/mibs/ ./opt/bin/python ...
SNMP:
BRIDGE-MIB::dot1dTpFdbTable
Q-BRIDGE-MIB::dot1qTpFdbTable
Q-BRIDGE-MIB::dot1qVlanCurrentTable
"""
from pvl.snmp import snmp
from pvl.snmp.snmp import pysnmp
from memoized_property import memoized_property
import logging; log = logging.getLogger('pvl.snmp.vlan')
DOT1D_TP_AGING_TIME = pysnmp.MibVariable('BRIDGE-MIB', 'dot1dTpAgingTime', 0)
DOT1D_TP_FDB_PORT = pysnmp.MibVariable('BRIDGE-MIB', 'dot1dTpFdbPort')
DOT1Q_VLAN_FDB_ID = pysnmp.MibVariable('Q-BRIDGE-MIB', 'dot1qVlanFdbId') # [dot1qVlanIndex]
DOT1Q_TP_FDB_PORT = pysnmp.MibVariable('Q-BRIDGE-MIB', 'dot1qTpFdbPort') # [dot1qFdbId, dot1qTpFdbAddress]
def macaddr (value) :
"""
Excepts a MAC address from an SNMP OctetString.
"""
return ':'.join('{octet:02x}'.format(octet=c) for c in value.asNumbers())
class BridgeAgent (snmp.SNMPAgent) :
"""
Query Bridge configuration.
XXX: this is not VLAN-aware!
"""
def ping (self) :
for name, value in self.get(DOT1D_TP_AGING_TIME) :
# XXX: ????
if value.tagSet == pysnmp.rfc1905.NoSuchInstance.tagSet :
continue
return True
def fdb_ports (self) :
"""
Map hosts in the brige FDB to specific ports.
"""
for idx, data in self.table(DOT1D_TP_FDB_PORT) :
addr, = idx
port = data[DOT1D_TP_FDB_PORT]
yield macaddr(addr), int(port)
def vlan_fdb (self) :
"""
Get FDB id -> vlan mappings.
(fdb, vlan)
"""
for idx, data in self.table(DOT1Q_VLAN_FDB_ID) :
time, vlan = idx
fdb = int(data[DOT1Q_VLAN_FDB_ID])
yield fdb, vlan
def vlan_fdb_ports (self) :
"""
Get per-vlan host -> port mappings.
(macaddr, port, vlan)
"""
fdb_to_vlan = dict(self.vlan_fdb())
for idx, data in self.table(DOT1Q_TP_FDB_PORT) :
fdb, addr = idx
port = data[DOT1Q_TP_FDB_PORT]
vlan = fdb_to_vlan.get(fdb)
yield macaddr(addr), int(port), vlan
if __name__ == '__main__':
import doctest
doctest.testmod()