如何利用SNMP(结合pysnmp)高效批量获取SDN网络主机的多维度关联信息?
Great question—SNMP is exactly the right tool here to slash your data collection time from hours to minutes (or even seconds, with proper optimization). Let’s walk through how to retrieve each piece of info you need, including relevant OIDs, and share a practical pysnmp framework to implement this.
First, a quick prerequisite: Make sure your Leaf devices have SNMP configured (use SNMPv3 for security, or a read-only community string for SNMPv2c) and have access to the required MIBs (most modern EVPN-capable switches like Cisco Nexus, Arista EOS, etc., support these out of the box).
1. Retrieve Leaf Port & VLAN (Equivalent to sh mac address-table address {MAC})
Use the CISCO-MAC-ADDRESS-TABLE-MIB (or vendor-specific equivalents) to map MAC addresses to their VLAN and interface index. You’ll then translate the interface index to a physical port name using the standard IF-MIB.
Key OIDs:
1.3.6.1.4.1.9.9.221.1.1.1.1.4(cmacAddrTableVlanId): VLAN ID associated with a MAC address1.3.6.1.4.1.9.9.221.1.1.1.1.6(cmacAddrTableIfIndex): Interface index for the port hosting the MAC1.3.6.1.2.1.2.2.1.2(ifDescr): Maps interface index to human-readable port name (e.g.,Ethernet1/1)
Optimization Tip:
Instead of querying each MAC individually, use bulkCmd to fetch the entire MAC address table in one go, then build a local lookup dictionary for your 5000 hosts.
2. Retrieve L2VNI & L3VNI (Equivalent to sh bgp l2vpn evpn {IP})
For EVPN-specific data, use the CISCO-BGP-EVPN-MIB to link MAC/IP addresses to their VNIs.
Key OIDs:
1.3.6.1.4.1.9.9.712.1.2.1.1.4(cbgpEvpnMacRouteVni): L2VNI associated with an EVPN MAC route1.3.6.1.4.1.9.9.712.1.3.1.1.4(cbgpEvpnIpRouteVni): L3VNI associated with an EVPN IP route
Optimization Tip:
Fetch all EVPN routes in bulk, then map your target IP/MAC addresses to their VNIs locally. This avoids 5000 separate SNMP requests per Leaf.
3. Retrieve VRF (Equivalent to sh vrf detail | i {L3VNI})
Use the CISCO-VRF-MIB to map L3VNIs to their corresponding VRF names.
Key OIDs:
1.3.6.1.4.1.9.9.461.1.1.1.1.1(cvrfName): Name of the VRF1.3.6.1.4.1.9.9.461.1.1.1.1.7(cvrfVni): L3VNI associated with the VRF
Optimization Tip:
Fetch the full VRF-VNI mapping once per Leaf, cache it in a dictionary, then look up VRF names by L3VNI instantly for all hosts.
Practical pysnmp Implementation Framework
Here’s a sample script to automate this workflow, optimized for bulk data collection:
from pysnmp.hlapi import * def get_leaf_snmp_data(leaf_ip, community): # Configure SNMP parameters (switch to SNMPv3 for production!) snmp_auth = CommunityData(community) transport = UdpTransportTarget((leaf_ip, 161)) # 1. Fetch full MAC address table (VLAN + ifIndex) mac_table = {} mac_oids = [ObjectType(ObjectIdentity('CISCO-MAC-ADDRESS-TABLE-MIB', 'cmacAddrTable'))] for errorIndication, _, _, varBinds in bulkCmd( snmp_auth, transport, ContextData(), 0, 100, *mac_oids ): if errorIndication: print(f"Error fetching MAC table for {leaf_ip}: {errorIndication}") continue for oid, val in varBinds: # Extract MAC from OID (last 6 nodes are MAC bytes) mac_bytes = oid[-6:] mac = ':'.join(f'{b:02X}' for b in mac_bytes) # Update VLAN or ifIndex in the mapping if 'cmacAddrTableVlanId' in str(oid): mac_table[mac] = mac_table.get(mac, {}) mac_table[mac]['vlan'] = val elif 'cmacAddrTableIfIndex' in str(oid): mac_table[mac] = mac_table.get(mac, {}) mac_table[mac]['ifIndex'] = val # 2. Fetch interface index to port name mapping if_map = {} if_oids = [ObjectType(ObjectIdentity('IF-MIB', 'ifDescr'))] for errorIndication, _, _, varBinds in bulkCmd( snmp_auth, transport, ContextData(), 0, 100, *if_oids ): if errorIndication: print(f"Error fetching interfaces for {leaf_ip}: {errorIndication}") continue for oid, val in varBinds: if_index = oid[-1] if_map[if_index] = val # 3. Fetch EVPN IP route to L3VNI mapping ip_to_l3vni = {} evpn_ip_oids = [ObjectType(ObjectIdentity('CISCO-BGP-EVPN-MIB', 'cbgpEvpnIpRouteVni'))] for errorIndication, _, _, varBinds in bulkCmd( snmp_auth, transport, ContextData(), 0, 50, *evpn_ip_oids ): if errorIndication: print(f"Error fetching EVPN IP routes for {leaf_ip}: {errorIndication}") continue for oid, val in varBinds: # Extract IPv4 address from OID (last 4 nodes) ip = '.'.join(str(b) for b in oid[-4:]) ip_to_l3vni[ip] = val # 4. Fetch VRF to L3VNI mapping l3vni_to_vrf = {} current_vrf = None vrf_oids = [ ObjectType(ObjectIdentity('CISCO-VRF-MIB', 'cvrfName')), ObjectType(ObjectIdentity('CISCO-VRF-MIB', 'cvrfVni')) ] for errorIndication, _, _, varBinds in bulkCmd( snmp_auth, transport, ContextData(), 0, 50, *vrf_oids ): if errorIndication: print(f"Error fetching VRFs for {leaf_ip}: {errorIndication}") continue for oid, val in varBinds: if 'cvrfName' in str(oid): current_vrf = val elif 'cvrfVni' in str(oid) and current_vrf: l3vni_to_vrf[val] = current_vrf return mac_table, if_map, ip_to_l3vni, l3vni_to_vrf # Example usage if __name__ == "__main__": # Your pre-existing host list (MAC, IP, Leaf IP) host_list = [ {"mac": "AA:BB:CC:DD:EE:FF", "ip": "192.168.1.1", "leaf_ip": "10.0.0.1"}, # Add all 5000 hosts here ] # Process each Leaf (parallelize this with threads/processes for speed!) for leaf_ip in set(h["leaf_ip"] for h in host_list): mac_table, if_map, ip_to_l3vni, l3vni_to_vrf = get_leaf_snmp_data(leaf_ip, "your_ro_community") # Match hosts to this Leaf and compile full info for host in [h for h in host_list if h["leaf_ip"] == leaf_ip]: mac_info = mac_table.get(host["mac"], {}) l3vni = ip_to_l3vni.get(host["ip"]) vrf = l3vni_to_vrf.get(l3vni) port = if_map.get(mac_info.get("ifIndex")) print(f"Host IP: {host['ip']}") print(f"MAC: {host['mac']}, Leaf Port: {port}, VLAN: {mac_info.get('vlan')}") print(f"VRF: {vrf}, L3VNI: {l3vni}, L2VNI: {mac_info.get('l2vni')}\n")
Critical Optimization Tips
- Parallelize Leaf Processing: Use Python’s
concurrent.futuresto query multiple Leaf devices at the same time—this will cut your total time from 70 sequential runs to a handful of parallel batches. - SNMPv3 Instead of v2c: For production environments, use SNMPv3 with authentication and encryption to avoid exposing sensitive network data.
- Adjust Bulk Sizes: Tweak the
0, 100parameters inbulkCmdto match your switch’s maximum allowed bulk response size (check vendor docs for optimal values). - Vendor-Specific MIBs: If you’re not using Cisco switches, replace the Cisco-specific OIDs with your vendor’s equivalent MIBs (e.g., Arista uses
ARISTA-MAC-ADDRESS-MIB).
内容的提问来源于stack exchange,提问作者Vida Eninkio

