+logger = logging.getLogger(__name__)
+
+if sys.version[0] == '2':
+ import Queue as queue
+else:
+ import queue as queue
+
+
+class VppEnumType(type):
+ def __getattr__(cls, name):
+ t = vpp_get_type(name)
+ return t.enum
+
+
+# Python3
+# class VppEnum(metaclass=VppEnumType):
+# pass
+class VppEnum(object):
+ __metaclass__ = VppEnumType
+
+
+def vpp_atexit(vpp_weakref):
+ """Clean up VPP connection on shutdown."""
+ vpp_instance = vpp_weakref()
+ if vpp_instance and vpp_instance.transport.connected:
+ vpp_instance.logger.debug('Cleaning up VPP on exit')
+ vpp_instance.disconnect()
+
+if sys.version[0] == '2':
+ def vpp_iterator(d):
+ return d.iteritems()
+else:
+ def vpp_iterator(d):
+ return d.items()
+
+
+def call_logger(msgdef, kwargs):
+ s = 'Calling {}('.format(msgdef.name)
+ for k, v in kwargs.items():
+ s += '{}:{} '.format(k, v)
+ s += ')'
+ return s
+
+
+def return_logger(r):
+ s = 'Return from {}'.format(r)
+ return s
+
+
+class VppApiDynamicMethodHolder(object):
+ pass
+
+
+class FuncWrapper(object):
+ def __init__(self, func):
+ self._func = func
+ self.__name__ = func.__name__
+
+ def __call__(self, **kwargs):
+ return self._func(**kwargs)
+
+
+class VPPApiError(Exception):
+ pass
+
+
+class VPPNotImplementedError(NotImplementedError):
+ pass
+
+
+class VPPIOError(IOError):
+ pass
+
+
+class VPPRuntimeError(RuntimeError):
+ pass
+
+
+class VPPValueError(ValueError):
+ pass
+
+
+class VPP(object):
+ """VPP interface.
+
+ This class provides the APIs to VPP. The APIs are loaded
+ from provided .api.json files and makes functions accordingly.
+ These functions are documented in the VPP .api files, as they
+ are dynamically created.
+
+ Additionally, VPP can send callback messages; this class
+ provides a means to register a callback function to receive
+ these messages in a background thread.
+ """
+ VPPApiError = VPPApiError
+ VPPRuntimeError = VPPRuntimeError
+ VPPValueError = VPPValueError
+ VPPNotImplementedError = VPPNotImplementedError
+ VPPIOError = VPPIOError
+
+ def process_json_file(self, apidef_file):
+ api = json.load(apidef_file)
+ types = {}
+ for t in api['enums']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'enum', 'data': t}
+ for t in api['unions']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'union', 'data': t}
+ for t in api['types']:
+ t[0] = 'vl_api_' + t[0] + '_t'
+ types[t[0]] = {'type': 'type', 'data': t}
+ for t, v in api['aliases'].items():
+ types['vl_api_' + t + '_t'] = {'type': 'alias', 'data': v}
+ self.services.update(api['services'])
+
+ i = 0
+ while True:
+ unresolved = {}
+ for k, v in types.items():
+ t = v['data']
+ if not vpp_get_type(k):
+ if v['type'] == 'enum':
+ try:
+ VPPEnumType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'union':
+ try:
+ VPPUnionType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'type':
+ try:
+ VPPType(t[0], t[1:])
+ except ValueError:
+ unresolved[k] = v
+ elif v['type'] == 'alias':
+ try:
+ VPPTypeAlias(k, t)
+ except ValueError:
+ unresolved[k] = v
+ if len(unresolved) == 0:
+ break
+ if i > 3:
+ raise VPPValueError('Unresolved type definitions {}'
+ .format(unresolved))
+ types = unresolved
+ i += 1
+
+ for m in api['messages']:
+ try:
+ self.messages[m[0]] = VPPMessage(m[0], m[1:])
+ except VPPNotImplementedError:
+ self.logger.error('Not implemented error for {}'.format(m[0]))
+
+ def __init__(self, apifiles=None, testmode=False, async_thread=True,
+ logger=None, loglevel=None,
+ read_timeout=5, use_socket=False,
+ server_address='/run/vpp-api.sock'):
+ """Create a VPP API object.
+
+ apifiles is a list of files containing API
+ descriptions that will be loaded - methods will be
+ dynamically created reflecting these APIs. If not
+ provided this will load the API files from VPP's
+ default install location.
+
+ logger, if supplied, is the logging logger object to log to.
+ loglevel, if supplied, is the log level this logger is set
+ to report at (from the loglevels in the logging module).
+ """
+ if logger is None:
+ logger = logging.getLogger(__name__)
+ if loglevel is not None:
+ logger.setLevel(loglevel)
+ self.logger = logger