summaryrefslogtreecommitdiffstats
path: root/src/tools/vppapigen
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2021-07-23 08:51:10 +0000
committerFilip Tehlar <ftehlar@cisco.com>2021-09-28 16:06:19 +0000
commit36217e3ca8a1ca2e7a341b6b44ffc25e6497191c (patch)
treeba45e2b144e0d66a69c0502a7823c28239d0bc66 /src/tools/vppapigen
parent3459ece6da90627b161e2128b5926f1e58e7db65 (diff)
api: API trace improvements
Type: improvement * add support for JSON format in API trace * add ability to replay JSON API trace in both VPP and VAT2 * use CRC for backward compatibility check during JSON API replay * fix API trace CLI (and remove duplicits) * remove custom dump * remove vppapitrace.py * update docs accordingly Change-Id: I5294f68bebe6cbe738630f457f3a87720e06486b Signed-off-by: Filip Tehlar <ftehlar@cisco.com> Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/tools/vppapigen')
-rw-r--r--src/tools/vppapigen/vppapigen_c.py71
1 files changed, 53 insertions, 18 deletions
diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py
index db684adb06d..ae47625a474 100644
--- a/src/tools/vppapigen/vppapigen_c.py
+++ b/src/tools/vppapigen/vppapigen_c.py
@@ -66,7 +66,10 @@ class ToJSON():
write('#ifndef included_{}_api_tojson_h\n'.format(self.module))
write('#define included_{}_api_tojson_h\n'.format(self.module))
write('#include <vppinfra/cJSON.h>\n\n')
- write('#include <vat2/jsonconvert.h>\n\n')
+ write('#include <vppinfra/jsonformat.h>\n\n')
+ if self.module == 'interface_types':
+ write('#define vl_printfun\n')
+ write('#include <vnet/interface_types.api.h>\n\n')
def footer(self):
'''Output the bottom boilerplate.'''
@@ -231,6 +234,8 @@ class ToJSON():
write(' cJSON *o = cJSON_CreateObject();\n')
write(' cJSON_AddStringToObject(o, "_msgname", "{}");\n'
.format(o.name))
+ write(' cJSON_AddStringToObject(o, "_crc", "{crc:08x}");\n'
+ .format(crc=o.crc))
for t in o.block:
self._dispatch[t.type](self, t)
@@ -312,7 +317,7 @@ class FromJSON():
write('#ifndef included_{}_api_fromjson_h\n'.format(self.module))
write('#define included_{}_api_fromjson_h\n'.format(self.module))
write('#include <vppinfra/cJSON.h>\n\n')
- write('#include <vat2/jsonconvert.h>\n\n')
+ write('#include <vppinfra/jsonformat.h>\n\n')
write('#pragma GCC diagnostic ignored "-Wunused-label"\n')
def is_base_type(self, t):
@@ -338,7 +343,7 @@ class FromJSON():
if o.modern_vla:
write(' char *p = cJSON_GetStringValue(item);\n')
write(' size_t plen = strlen(p);\n')
- write(' {msgvar} = realloc({msgvar}, {msgsize} + plen);\n'
+ write(' {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen, {msgsize});\n'
.format(msgvar=msgvar, msgsize=msgsize))
write(' if ({msgvar} == 0) goto error;\n'.format(msgvar=msgvar))
write(' vl_api_c_string_to_api_string(p, (void *){msgvar} + '
@@ -393,7 +398,7 @@ class FromJSON():
cJSON *array = cJSON_GetObjectItem(o, "{n}");
int size = cJSON_GetArraySize(array);
{lfield} = size;
- {realloc} = realloc({realloc}, {msgsize} + sizeof({t}) * size);
+ {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size, {msgsize});
{t} *d = (void *){realloc} + {msgsize};
{msgsize} += sizeof({t}) * size;
for (i = 0; i < size; i++) {{
@@ -419,8 +424,8 @@ class FromJSON():
write(' if (!s) goto error;\n')
write(' {} = vec_len(s);\n'.format(lfield))
- write(' {realloc} = realloc({realloc}, {msgsize} + '
- 'vec_len(s));\n'.format(msgvar=msgvar, msgsize=msgsize, realloc=realloc))
+ write(' {realloc} = cJSON_realloc({realloc}, {msgsize} + '
+ 'vec_len(s), {msgsize});\n'.format(msgvar=msgvar, msgsize=msgsize, realloc=realloc))
write(' memcpy((void *){realloc} + {msgsize}, s, '
'vec_len(s));\n'.format(realloc=realloc, msgsize=msgsize))
write(' {msgsize} += vec_len(s);\n'.format(msgsize=msgsize))
@@ -553,7 +558,7 @@ class FromJSON():
write(' cJSON *item __attribute__ ((unused));\n')
write(' u8 *s __attribute__ ((unused));\n')
write(' int l = sizeof(vl_api_{}_t);\n'.format(o.name))
- write(' vl_api_{}_t *a = malloc(l);\n'.format(o.name))
+ write(' vl_api_{}_t *a = cJSON_malloc(l);\n'.format(o.name))
write('\n')
for t in o.block:
@@ -573,7 +578,7 @@ class FromJSON():
if error:
write('\n error:\n')
- write(' free(a);\n')
+ write(' cJSON_free(a);\n')
write(' return 0;\n')
write('}\n')
@@ -928,10 +933,13 @@ def printfun(objs, stream, modulename):
#define _uword_cast long
#endif
+#include "{module}.api_tojson.h"
+#include "{module}.api_fromjson.h"
+
'''
signature = '''\
-static inline void *vl_api_{name}_t_print (vl_api_{name}_t *a, void *handle)
+static inline void *vl_api_{name}_t_print{suffix} (vl_api_{name}_t *a, void *handle)
{{
u8 *s = 0;
u32 indent __attribute__((unused)) = 2;
@@ -946,7 +954,7 @@ static inline void *vl_api_{name}_t_print (vl_api_{name}_t *a, void *handle)
if t.manual_print:
write("/***** manual: vl_api_%s_t_print *****/\n\n" % t.name)
continue
- write(signature.format(name=t.name))
+ write(signature.format(name=t.name, suffix=''))
write(' /* Message definition: vl_api_{}_t: */\n'.format(t.name))
write(" s = format(s, \"vl_api_%s_t:\");\n" % t.name)
for o in t.block:
@@ -957,6 +965,16 @@ static inline void *vl_api_{name}_t_print (vl_api_{name}_t *a, void *handle)
write(' return handle;\n')
write('}\n\n')
+ write(signature.format(name=t.name, suffix='_json'))
+ write(' cJSON * o = vl_api_{}_t_tojson(a);\n'.format(t.name))
+ write(' (void)s;\n');
+ write(' char *out = cJSON_Print(o);\n')
+ write(' vl_print(handle, out);\n');
+ write(' cJSON_Delete(o);\n')
+ write(' cJSON_free(out);\n');
+ write(' return handle;\n')
+ write('}\n\n');
+
write("\n#endif")
write("\n#endif /* vl_printfun */\n")
@@ -1346,6 +1364,9 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
' .print = vl_api_{n}_t_print,\n'
' .traced = 1,\n'
' .replay = 1,\n'
+ ' .print_json = vl_api_{n}_t_print_json,\n'
+ ' .tojson = vl_api_{n}_t_tojson,\n'
+ ' .fromjson = vl_api_{n}_t_fromjson,\n'
' .is_autoendian = {auto}}};\n'
.format(n=s.caller, ID=s.caller.upper(),
auto=d.autoendian))
@@ -1359,6 +1380,11 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
' .cleanup = vl_noop_handler,\n'
' .endian = vl_api_{n}_t_endian,\n'
' .print = vl_api_{n}_t_print,\n'
+ ' .traced = 1,\n'
+ ' .replay = 1,\n'
+ ' .print_json = vl_api_{n}_t_print_json,\n'
+ ' .tojson = vl_api_{n}_t_tojson,\n'
+ ' .fromjson = vl_api_{n}_t_fromjson,\n'
' .is_autoendian = {auto}}};\n'
.format(n=s.reply, ID=s.reply.upper(),
auto=d.autoendian))
@@ -1455,7 +1481,10 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
' vl_noop_handler,\n'
' vl_api_{n}_t_endian, '
' vl_api_{n}_t_print,\n'
- ' sizeof(vl_api_{n}_t), 1);\n'
+ ' sizeof(vl_api_{n}_t), 1,\n'
+ ' vl_api_{n}_t_print_json,\n'
+ ' vl_api_{n}_t_tojson,\n'
+ ' vl_api_{n}_t_fromjson);\n'
.format(n=s.reply, ID=s.reply.upper()))
write(' hash_set_mem (vam->function_by_name, "{n}", api_{n});\n'
.format(n=s.caller))
@@ -1474,7 +1503,10 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
' vl_noop_handler,\n'
' vl_api_{n}_t_endian, '
' vl_api_{n}_t_print,\n'
- ' sizeof(vl_api_{n}_t), 1);\n'
+ ' sizeof(vl_api_{n}_t), 1,\n'
+ ' vl_api_{n}_t_print_json,\n'
+ ' vl_api_{n}_t_tojson,\n'
+ ' vl_api_{n}_t_fromjson);\n'
.format(n=e, ID=e.upper()))
write('}\n')
@@ -1526,7 +1558,7 @@ api_{n} (cJSON *o)
mp->_vl_msg_id = vac_get_msg_index(VL_API_{N}_CRC);
vl_api_{n}_t_endian(mp);
vac_write((char *)mp, len);
- free(mp);
+ cJSON_free(mp);
/* Read reply */
char *p;
@@ -1559,7 +1591,7 @@ api_{n} (cJSON *o)
mp->_vl_msg_id = msg_id;
vl_api_{n}_t_endian(mp);
vac_write((char *)mp, len);
- free(mp);
+ cJSON_free(mp);
vat2_control_ping(123); // FIX CONTEXT
cJSON *reply = cJSON_CreateArray();
@@ -1615,7 +1647,7 @@ api_{n} (cJSON *o)
vl_api_{n}_t_endian(mp);
vac_write((char *)mp, len);
- free(mp);
+ cJSON_free(mp);
cJSON *reply = cJSON_CreateArray();
@@ -1713,13 +1745,16 @@ def generate_c_test2_boilerplate(services, defines, module, stream):
continue
c_test_api_service(s, s.stream, stream)
- write('void vat2_register_function(char *, cJSON * (*)(cJSON *), cJSON * (*)(void *));\n')
+ write('void vat2_register_function(char *, cJSON * (*)(cJSON *), cJSON * (*)(void *), u32);\n')
# write('__attribute__((constructor))')
write('clib_error_t *\n')
write('vat2_register_plugin (void) {\n')
for s in services:
- write(' vat2_register_function("{n}", api_{n}, (cJSON * (*)(void *))vl_api_{n}_t_tojson);\n'
- .format(n=s.caller))
+ if s.reply not in define_hash:
+ continue
+ crc = define_hash[s.caller].crc
+ write(' vat2_register_function("{n}", api_{n}, (cJSON * (*)(void *))vl_api_{n}_t_tojson, 0x{crc:08x});\n'
+ .format(n=s.caller, crc=crc))
write(' return 0;\n')
write('}\n')