diff options
author | Ole Troan <ot@cisco.com> | 2019-09-04 09:12:29 +0200 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2019-09-16 12:23:27 +0000 |
commit | 33a58171e5995d9e649b414bfc77f2aab26e4c58 (patch) | |
tree | 85e072422b46ef44bbefbdf49231da507ec99536 /src/tools/vppapigen/vppapigen.py | |
parent | 1292d19c79c2fd4f09ffcc43ebf39f5d9d485c35 (diff) |
api: autogenerate api trace print/endian
In addition to the external vppapitrace tool, VPP itself supports dumping of API trace files.
In two formats, "custom-dump" and "dump". "dump" gives a human friendly list,
and "custom-dump" is meant to give a list of commands that can be fed to VAT.
This patch only deals with "dump".
Prior to this fix, auto-generation was only done for the basic types.
This fix adds support for any type, including lists, and supports pretty-printing
of enums, strings, IP addresses, MAC addresses and so on.
Usage: api trace dump <api-trace-file>
For example
Change-Id: I4e485680e6dcfce7489299ae6cf31d835071ac40
---------- trace 48 -----------
vl_api_sw_interface_set_flags_t:
_vl_msg_id: 75
client_index: 0
context: 10
sw_if_index: 1
flags: IF_STATUS_API_FLAG_ADMIN_UP
---------- trace 49 -----------
vl_api_sw_interface_add_del_address_t:
_vl_msg_id: 88
client_index: 0
context: 11
sw_if_index: 1
is_add: 1
del_all: 0
prefix: 172.16.1.1/24
---------- trace 51 -----------
vl_api_cli_inband_t:
_vl_msg_id: 819
client_index: 0
context: 13
cmd: packet-generator capture pg0 pcap /tmp/vpp-unittest-TestMAP-YhcmDX/pg0_out.pcap disable
---------- trace 58 -----------
vl_api_ip_neighbor_add_del_t:
_vl_msg_id: 199
client_index: 0
context: 20
is_add: 1
neighbor:
sw_if_index: 2
flags: IP_API_NEIGHBOR_FLAG_NONE
mac_address: 0202.0000.ff02
ip_address: fd01:2::2
Signed-off-by: Ole Troan <ot@cisco.com>
Change-Id: I5556d06008de2762e7c2d35a8b0963ae670b3db1
Type: fix
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/tools/vppapigen/vppapigen.py')
-rwxr-xr-x | src/tools/vppapigen/vppapigen.py | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/src/tools/vppapigen/vppapigen.py b/src/tools/vppapigen/vppapigen.py index 2a939647c67..fa7e47afb73 100755 --- a/src/tools/vppapigen/vppapigen.py +++ b/src/tools/vppapigen/vppapigen.py @@ -8,6 +8,7 @@ import keyword import logging import binascii import os +import sys log = logging.getLogger('vppapigen') @@ -78,6 +79,16 @@ class VPPAPILexer(object): t_ignore_LINE_COMMENT = '//.*' + def t_FALSE(self, t): + r'false' + t.value = False + return t + + def t_TRUE(self, t): + r'false' + t.value = True + return t + def t_NUM(self, t): r'0[xX][0-9a-fA-F]+|-?\d+\.?\d*' base = 16 if t.value.startswith('0x') else 10 @@ -150,6 +161,14 @@ class Typedef(): self.manual_print = True elif f == 'manual_endian': self.manual_endian = True + for b in block: + # Tag length field of a VLA + if isinstance(b, Array): + if b.lengthfield: + for b2 in block: + if b2.fieldname == b.lengthfield: + b2.vla_len = True + global_type_add(name, self) self.vla = False @@ -176,10 +195,18 @@ class Typedef(): class Using(): - def __init__(self, name, alias): + def __init__(self, name, flags, alias): self.name = name self.vla = False + self.manual_print = False + self.manual_endian = False + for f in flags: + if f == 'manual_print': + self.manual_print = True + elif f == 'manual_endian': + self.manual_endian = True + if isinstance(alias, Array): a = {'type': alias.fieldtype, 'length': alias.length} @@ -194,11 +221,20 @@ class Using(): class Union(): - def __init__(self, name, block): + def __init__(self, name, flags, block): self.type = 'Union' self.manual_print = False self.manual_endian = False self.name = name + + self.manual_print = False + self.manual_endian = False + for f in flags: + if f == 'manual_print': + self.manual_print = True + elif f == 'manual_endian': + self.manual_endian = True + self.block = block self.crc = str(block).encode() global_type_add(name, self) @@ -250,6 +286,12 @@ class Define(): 'VLA field "{}" must be the last ' 'field in message "{}"' .format(b.fieldname, name)) + # Tag length field of a VLA + if isinstance(b, Array): + if b.lengthfield: + for b2 in block: + if b2.fieldname == b.lengthfield: + b2.vla_len = True def __repr__(self): return self.name + str(self.flags) + str(self.block) @@ -298,8 +340,10 @@ class Import(): class Option(): - def __init__(self, option): + def __init__(self, option, value): + self.type = 'Option' self.option = option + self.value = value self.crc = str(option).encode() def __repr__(self): @@ -524,9 +568,17 @@ class VPPAPIParser(object): '''typedef : TYPEDEF ID '{' block_statements_opt '}' ';' ''' p[0] = Typedef(p[2], [], p[4]) + def p_typedef_flist(self, p): + '''typedef : flist TYPEDEF ID '{' block_statements_opt '}' ';' ''' + p[0] = Typedef(p[3], p[1], p[5]) + def p_typedef_alias(self, p): '''typedef : TYPEDEF declaration ''' - p[0] = Using(p[2].fieldname, p[2]) + p[0] = Using(p[2].fieldname, [], p[2]) + + def p_typedef_alias_flist(self, p): + '''typedef : flist TYPEDEF declaration ''' + p[0] = Using(p[3].fieldname, p[1], p[3]) def p_block_statements_opt(self, p): '''block_statements_opt : block_statements ''' @@ -620,7 +672,7 @@ class VPPAPIParser(object): def p_option(self, p): '''option : OPTION ID '=' assignee ';' ''' - p[0] = Option([p[1], p[2], p[4]]) + p[0] = Option(p[2], p[4]) def p_assignee(self, p): '''assignee : NUM @@ -653,7 +705,11 @@ class VPPAPIParser(object): def p_union(self, p): '''union : UNION ID '{' block_statements_opt '}' ';' ''' - p[0] = Union(p[2], p[4]) + p[0] = Union(p[2], [], p[4]) + + def p_union_flist(self, p): + '''union : flist UNION ID '{' block_statements_opt '}' ';' ''' + p[0] = Union(p[3], p[1], p[5]) # Error rule for syntax errors def p_error(self, p): @@ -716,7 +772,7 @@ class VPPAPI(object): isinstance(o, Union)): s['types'].append(o) elif isinstance(o, Using): - s['Alias'][o.name] = o.alias + s['Alias'][o.name] = o else: if tname not in s: raise ValueError('Unknown class type: {} {}' @@ -802,6 +858,7 @@ class VPPAPI(object): isinstance(o, Using)): continue if isinstance(o, Import): + result.append(o) self.process_imports(o.result, True, result) else: result.append(o) @@ -894,8 +951,12 @@ def main(): # Build a list of objects. Hash of lists. result = [] - parser.process_imports(parsed_objects, False, result) - s = parser.process(result) + + if args.output_module == 'C': + s = parser.process(parsed_objects) + else: + parser.process_imports(parsed_objects, False, result) + s = parser.process(result) # Add msg_id field s['Define'] = add_msg_id(s['Define']) |