Add VPP API support to retrieve mtu/ifspeed/operstatus/adminstatus/mac
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from vppstats import VPPStats
|
from vppstats import VPPStats
|
||||||
|
import vppapi
|
||||||
import time
|
import time
|
||||||
import pyagentx
|
import pyagentx
|
||||||
import logging
|
import logging
|
||||||
@ -13,7 +14,7 @@ class NullHandler(logging.Handler):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('pyagentx.vpp')
|
logger = logging.getLogger('pyagentx.vppstats')
|
||||||
logger.addHandler(NullHandler())
|
logger.addHandler(NullHandler())
|
||||||
|
|
||||||
|
|
||||||
@ -47,6 +48,105 @@ class ifType(pyagentx.Updater):
|
|||||||
self.set_INTEGER(str(i + 1), t)
|
self.set_INTEGER(str(i + 1), t)
|
||||||
|
|
||||||
|
|
||||||
|
class ifMtu(pyagentx.Updater):
|
||||||
|
def update(self):
|
||||||
|
global vppstat, vpp
|
||||||
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
|
for i in range(len(vppstat['/if/names'])):
|
||||||
|
ifname = vppstat['/if/names'][i]
|
||||||
|
mtu = 0
|
||||||
|
if not ifname in ifaces:
|
||||||
|
logger.warning("Could not get MTU for interface %s", ifname)
|
||||||
|
else:
|
||||||
|
mtu = ifaces[ifname].mtu[0]
|
||||||
|
self.set_INTEGER(str(i + 1), mtu)
|
||||||
|
|
||||||
|
|
||||||
|
class ifSpeed(pyagentx.Updater):
|
||||||
|
def update(self):
|
||||||
|
global vppstat, vpp
|
||||||
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
|
for i in range(len(vppstat['/if/names'])):
|
||||||
|
ifname = vppstat['/if/names'][i]
|
||||||
|
speed = 0
|
||||||
|
if ifname.startswith("loop") or ifname.startswith("tap"):
|
||||||
|
speed = 1000000000
|
||||||
|
elif not ifname in ifaces:
|
||||||
|
logger.warning("Could not get link speed for interface %s",
|
||||||
|
ifname)
|
||||||
|
else:
|
||||||
|
speed = ifaces[ifname].link_speed * 1000
|
||||||
|
if speed >= 2**32:
|
||||||
|
speed = 2**32 - 1
|
||||||
|
self.set_GAUGE32(str(i + 1), speed)
|
||||||
|
|
||||||
|
|
||||||
|
class ifAdminStatus(pyagentx.Updater):
|
||||||
|
def update(self):
|
||||||
|
global vppstat, vpp
|
||||||
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
|
for i in range(len(vppstat['/if/names'])):
|
||||||
|
ifname = vppstat['/if/names'][i]
|
||||||
|
state = 3 # testing
|
||||||
|
if not ifname in ifaces:
|
||||||
|
logger.warning("Could not get AdminStatus for interface %s",
|
||||||
|
ifname)
|
||||||
|
else:
|
||||||
|
if int(ifaces[ifname].flags) & 2:
|
||||||
|
state = 1 # up
|
||||||
|
else:
|
||||||
|
state = 2 # down
|
||||||
|
self.set_INTEGER(str(i + 1), state)
|
||||||
|
|
||||||
|
|
||||||
|
class ifOperStatus(pyagentx.Updater):
|
||||||
|
def update(self):
|
||||||
|
global vppstat, vpp
|
||||||
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
|
for i in range(len(vppstat['/if/names'])):
|
||||||
|
ifname = vppstat['/if/names'][i]
|
||||||
|
state = 3 # testing
|
||||||
|
if not ifname in ifaces:
|
||||||
|
logger.warning("Could not get OperStatus for interface %s",
|
||||||
|
ifname)
|
||||||
|
else:
|
||||||
|
if int(ifaces[ifname].flags) & 1:
|
||||||
|
state = 1 # up
|
||||||
|
else:
|
||||||
|
state = 2 # down
|
||||||
|
self.set_INTEGER(str(i + 1), state)
|
||||||
|
|
||||||
|
|
||||||
|
class ifPhysAddress(pyagentx.Updater):
|
||||||
|
def update(self):
|
||||||
|
global vppstat, vpp
|
||||||
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
|
for i in range(len(vppstat['/if/names'])):
|
||||||
|
ifname = vppstat['/if/names'][i]
|
||||||
|
mac = "00:00:00:00:00:00"
|
||||||
|
if not ifname in ifaces:
|
||||||
|
logger.warning("Could not get PhysAddress for interface %s",
|
||||||
|
ifname)
|
||||||
|
else:
|
||||||
|
mac = str(ifaces[ifname].l2_address)
|
||||||
|
self.set_OCTETSTRING(str(i + 1), mac)
|
||||||
|
|
||||||
|
|
||||||
class ifAlias(pyagentx.Updater):
|
class ifAlias(pyagentx.Updater):
|
||||||
def update(self):
|
def update(self):
|
||||||
global vppstat
|
global vppstat
|
||||||
@ -178,11 +278,22 @@ class ifHCOutBroadcastPkts(pyagentx.Updater):
|
|||||||
|
|
||||||
class ifHighSpeed(pyagentx.Updater):
|
class ifHighSpeed(pyagentx.Updater):
|
||||||
def update(self):
|
def update(self):
|
||||||
global vppstat
|
global vppstat, vpp
|
||||||
vppstat.connect()
|
vppstat.connect()
|
||||||
|
|
||||||
|
ifaces = vppapi.get_ifaces(vpp)
|
||||||
|
|
||||||
for i in range(len(vppstat['/if/names'])):
|
for i in range(len(vppstat['/if/names'])):
|
||||||
self.set_GAUGE32(str(i + 1), 1000)
|
ifname = vppstat['/if/names'][i]
|
||||||
|
speed = 0
|
||||||
|
if ifname.startswith("loop") or ifname.startswith("tap"):
|
||||||
|
speed = 1000
|
||||||
|
elif not ifname in ifaces:
|
||||||
|
logger.warning("Could not get link speed for interface %s",
|
||||||
|
ifname)
|
||||||
|
else:
|
||||||
|
speed = int(ifaces[ifname].link_speed / 1000)
|
||||||
|
self.set_GAUGE32(str(i + 1), speed)
|
||||||
|
|
||||||
|
|
||||||
class ifPromiscuousMode(pyagentx.Updater):
|
class ifPromiscuousMode(pyagentx.Updater):
|
||||||
@ -319,6 +430,11 @@ class MyAgent(pyagentx.Agent):
|
|||||||
self.register('1.3.6.1.2.1.2.2.1.1', ifIndex)
|
self.register('1.3.6.1.2.1.2.2.1.1', ifIndex)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.2', ifName)
|
self.register('1.3.6.1.2.1.2.2.1.2', ifName)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.3', ifType)
|
self.register('1.3.6.1.2.1.2.2.1.3', ifType)
|
||||||
|
self.register('1.3.6.1.2.1.2.2.1.4', ifMtu)
|
||||||
|
self.register('1.3.6.1.2.1.2.2.1.5', ifSpeed)
|
||||||
|
self.register('1.3.6.1.2.1.2.2.1.6', ifPhysAddress)
|
||||||
|
self.register('1.3.6.1.2.1.2.2.1.7', ifAdminStatus)
|
||||||
|
self.register('1.3.6.1.2.1.2.2.1.8', ifOperStatus)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.9', ifCounterDiscontinuityTime)
|
self.register('1.3.6.1.2.1.2.2.1.9', ifCounterDiscontinuityTime)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.10', ifInOctets)
|
self.register('1.3.6.1.2.1.2.2.1.10', ifInOctets)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.11', ifInUcastPkts)
|
self.register('1.3.6.1.2.1.2.2.1.11', ifInUcastPkts)
|
||||||
@ -332,13 +448,6 @@ class MyAgent(pyagentx.Agent):
|
|||||||
self.register('1.3.6.1.2.1.2.2.1.19', ifOutDiscards)
|
self.register('1.3.6.1.2.1.2.2.1.19', ifOutDiscards)
|
||||||
self.register('1.3.6.1.2.1.2.2.1.20', ifOutErrors)
|
self.register('1.3.6.1.2.1.2.2.1.20', ifOutErrors)
|
||||||
|
|
||||||
# TODO(pim) -- these require VPP API calls
|
|
||||||
#4 .iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry.ifMtu.132 = INTEGER: 1500
|
|
||||||
#5 .iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry.ifSpeed.132 = Gauge32: 10000000
|
|
||||||
#6 .iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry.ifPhysAddress.132 = Hex-STRING: 68 05 CA 32 46 15
|
|
||||||
#7 .iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry.ifAdminStatus.132 = INTEGER: 1
|
|
||||||
#8 .iso.org.dod.internet.mgmt.mib_2.interfaces.ifTable.ifEntry.ifOperStatus.132 = INTEGER: 1
|
|
||||||
|
|
||||||
# iso.org.dod.internet.mgmt.mib_2.ifMIB.ifMIBObjects.ifXTable.ifXEntry
|
# iso.org.dod.internet.mgmt.mib_2.ifMIB.ifMIBObjects.ifXTable.ifXEntry
|
||||||
self.register('1.3.6.1.2.1.31.1.1.1.1', ifName)
|
self.register('1.3.6.1.2.1.31.1.1.1.1', ifName)
|
||||||
self.register('1.3.6.1.2.1.31.1.1.1.2', ifInMulticastPkts)
|
self.register('1.3.6.1.2.1.31.1.1.1.2', ifInMulticastPkts)
|
||||||
@ -364,13 +473,18 @@ class MyAgent(pyagentx.Agent):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global vppstat
|
global vppstat, vpp, logger
|
||||||
|
|
||||||
pyagentx.setup_logging(debug=False)
|
pyagentx.setup_logging(debug=False)
|
||||||
|
|
||||||
vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
|
vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
|
||||||
vppstat.connect()
|
vppstat.connect()
|
||||||
|
|
||||||
|
vpp = vppapi.vpp_connect()
|
||||||
|
if not vpp:
|
||||||
|
logger.error("Can't connect to VPP API, bailing")
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a = MyAgent()
|
a = MyAgent()
|
||||||
a.start()
|
a.start()
|
||||||
|
85
vppapi.py
Normal file
85
vppapi.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
'''
|
||||||
|
The functions in this file interact with the VPP API to retrieve certain
|
||||||
|
interface metadata.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from vpp_papi import VPPApiClient
|
||||||
|
import os
|
||||||
|
import fnmatch
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class NullHandler(logging.Handler):
|
||||||
|
def emit(self, record):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger('pyagentx.vppapi')
|
||||||
|
logger.addHandler(NullHandler())
|
||||||
|
|
||||||
|
vpp_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
def vpp_connect():
|
||||||
|
global logger
|
||||||
|
|
||||||
|
vpp_json_dir = '/usr/share/vpp/api/'
|
||||||
|
|
||||||
|
# construct a list of all the json api files
|
||||||
|
jsonfiles = []
|
||||||
|
for root, dirnames, filenames in os.walk(vpp_json_dir):
|
||||||
|
for filename in fnmatch.filter(filenames, '*.api.json'):
|
||||||
|
jsonfiles.append(os.path.join(root, filename))
|
||||||
|
|
||||||
|
if not jsonfiles:
|
||||||
|
logger.error('no json api files found')
|
||||||
|
return False
|
||||||
|
|
||||||
|
vpp = VPPApiClient(apifiles=jsonfiles, server_address='/run/vpp/api.sock')
|
||||||
|
try:
|
||||||
|
vpp.connect('vpp-snmp-agent')
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
v = vpp.api.show_version()
|
||||||
|
logger.info('VPP version is %s' % v.version)
|
||||||
|
|
||||||
|
return vpp
|
||||||
|
|
||||||
|
|
||||||
|
def get_iface(vpp, ifname):
|
||||||
|
global logger
|
||||||
|
|
||||||
|
vpp_lock.acquire()
|
||||||
|
iface_list = vpp.api.sw_interface_dump(name_filter=ifname,
|
||||||
|
name_filter_valid=True)
|
||||||
|
if not iface_list:
|
||||||
|
logger.error("Can't get interface %s" % ifname)
|
||||||
|
vpp_lock.release()
|
||||||
|
return None
|
||||||
|
|
||||||
|
for iface in iface_list:
|
||||||
|
if iface.interface_name == ifname:
|
||||||
|
vpp_lock.release()
|
||||||
|
return iface
|
||||||
|
vpp_lock.release()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_ifaces(vpp):
|
||||||
|
global logger
|
||||||
|
|
||||||
|
vpp_lock.acquire()
|
||||||
|
ret = {}
|
||||||
|
iface_list = vpp.api.sw_interface_dump()
|
||||||
|
if not iface_list:
|
||||||
|
logger.error("Can't get interface list")
|
||||||
|
vpp_lock.release()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
for iface in iface_list:
|
||||||
|
ret[iface.interface_name] = iface
|
||||||
|
|
||||||
|
vpp_lock.release()
|
||||||
|
return ret
|
Reference in New Issue
Block a user