aboutsummaryrefslogtreecommitdiffstats
path: root/src/tools/vppapigen/vppapigen.py
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2019-09-04 09:12:29 +0200
committerDave Barach <openvpp@barachs.net>2019-09-16 12:23:27 +0000
commit33a58171e5995d9e649b414bfc77f2aab26e4c58 (patch)
tree85e072422b46ef44bbefbdf49231da507ec99536 /src/tools/vppapigen/vppapigen.py
parent1292d19c79c2fd4f09ffcc43ebf39f5d9d485c35 (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-xsrc/tools/vppapigen/vppapigen.py79
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'])