X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vpp-api%2Fpython%2Fvpp_papi%2Fvpp_papi.py;h=02fe2457ef0e3ccbecb0c2db2edcbf1691c126ca;hb=f5984bde0462f21402ba5c2c3ad04e44440402eb;hp=8e7b7f66ff57c16cd798614e57f61e52bea4ce69;hpb=65cc8c0dbf04f2418200e682caeae9c1e7396e10;p=vpp.git diff --git a/vpp-api/python/vpp_papi/vpp_papi.py b/vpp-api/python/vpp_papi/vpp_papi.py index 8e7b7f66ff5..02fe2457ef0 100644 --- a/vpp-api/python/vpp_papi/vpp_papi.py +++ b/vpp-api/python/vpp_papi/vpp_papi.py @@ -15,7 +15,7 @@ # from __future__ import print_function -import sys, os, logging, collections, struct, json, threading +import sys, os, logging, collections, struct, json, threading, glob logging.basicConfig(level=logging.DEBUG) import vpp_api @@ -23,7 +23,7 @@ def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) class VPP(): - def __init__(self, apifiles): + def __init__(self, apifiles = None, testmode = False): self.messages = {} self.id_names = [] self.id_msgdef = [] @@ -34,6 +34,10 @@ class VPP(): self.timeout = 5 self.apifile = [] + if not apifiles: + # Pick up API definitions from default directory + apifiles = glob.glob('/usr/share/vpp/api/*.api.json') + for file in apifiles: self.apifile.append(file) with open(file) as apidef_file: @@ -45,8 +49,8 @@ class VPP(): self.add_message(m[0], m[1:]) # Basic sanity check - if not 'control_ping' in self.messages: - raise ValueError(1, 'Error in JSON message definitions') + if len(self.messages) == 0 and not testmode: + raise ValueError(1, 'Missing JSON message definitions') class ContextId(object): @@ -61,7 +65,7 @@ class VPP(): print('Connected') if self.connected else print('Not Connected') print('Read API definitions from', self.apifile) - def __struct (self, t, n = None, e = 0, vl = None): + def __struct (self, t, n = None, e = -1, vl = None): base_types = { 'u8' : 'B', 'u16' : 'H', 'u32' : 'I', @@ -73,33 +77,40 @@ class VPP(): if t in base_types: pack = base_types[t] if not vl: - if e and t == 'u8': + if e > 0 and t == 'u8': # Fixed byte array return struct.Struct('>' + str(e) + 's') - if e: + if e > 0: # Fixed array of base type return [e, struct.Struct('>' + base_types[t])] + elif e == 0: + # Old style variable array + return [-1, struct.Struct('>' + base_types[t])] else: # Variable length array - return [vl, struct.Struct('>s')] if t == 'u8' else [vl, struct.Struct('>' + base_types[t])] + return [vl, struct.Struct('>s')] if t == 'u8' else \ + [vl, struct.Struct('>' + base_types[t])] return struct.Struct('>' + base_types[t]) if t in self.messages: ### Return a list in case of array ### - if e and not vl: + if e > 0 and not vl: return [e, lambda self, encode, buf, offset, args: ( - self.__struct_type(encode, self.messages[t], buf, offset, args) - )] + self.__struct_type(encode, self.messages[t], buf, offset, + args))] if vl: return [vl, lambda self, encode, buf, offset, args: ( - self.__struct_type(encode, self.messages[t], buf, offset, args) - )] + self.__struct_type(encode, self.messages[t], buf, offset, + args))] + elif e == 0: + # Old style VLA + raise NotImplementedError(1, 'No support for compound types ' + t) return lambda self, encode, buf, offset, args: ( self.__struct_type(encode, self.messages[t], buf, offset, args) ) - raise ValueError + raise ValueError(1, 'Invalid message type: ' + t) def __struct_type(self, encode, msgdef, buf, offset, kwargs): if encode: @@ -120,10 +131,7 @@ class VPP(): if k in kwargs: if type(v) is list: if callable(v[1]): - if v[0] in kwargs: - e = kwargs[v[0]] - else: - e = v[0] + e = kwargs[v[0]] if v[0] in kwargs else v[0] size = 0 for i in range(e): size += v[1](self, True, buf, off + size, @@ -179,7 +187,7 @@ class VPP(): if callable(v[1]): # compound type size = 0 if v[0] in msgdef['args']: # vla - e = int(res[-1]) + e = res[v[2]] else: # fixed array e = v[0] res.append(lst) @@ -188,14 +196,19 @@ class VPP(): lst.append(l) size += s continue - if v[1].size == 1: - size = int(res[-1]) + if type(v[0]) is int: + size = len(buf) - off + else: + size = res[v[2]] res.append(buf[off:off + size]) else: - e = int(res[-1]) + e = v[0] if type(v[0]) is int else res[v[2]] + if e == -1: + e = (len(buf) - off) / v[1].size if e == 0: - raise ValueError + raise ValueError(1, + 'Variable length array, empty length: ' + k) lst = [] res.append(lst) size = 0 @@ -226,14 +239,18 @@ class VPP(): argtypes = collections.OrderedDict() fields = [] msg = {} - for f in msgdef: + for i, f in enumerate(msgdef): if type(f) is dict and 'crc' in f: msg['crc'] = f['crc'] continue field_type = f[0] field_name = f[1] + if len(f) == 3 and f[2] == 0 and i != len(msgdef) - 2: + raise ValueError('Variable Length Array must be last: ' + name) args[field_name] = self.__struct(*f) argtypes[field_name] = field_type + if len(f) == 4: # Find offset to # elements field + args[field_name].append(args.keys().index(f[3]) - i) fields.append(field_name) msg['return_tuple'] = collections.namedtuple(name, fields, rename = True) @@ -243,7 +260,7 @@ class VPP(): return self.messages[name] def add_type(self, name, typedef): - self.add_message('vl_api_' + name + '_t', typedef) + return self.add_message('vl_api_' + name + '_t', typedef) def make_function(self, name, i, msgdef, multipart, async): if (async):