diff options
author | Filip Tehlar <ftehlar@cisco.com> | 2021-07-23 08:51:10 +0000 |
---|---|---|
committer | Filip Tehlar <ftehlar@cisco.com> | 2021-09-28 16:06:19 +0000 |
commit | 36217e3ca8a1ca2e7a341b6b44ffc25e6497191c (patch) | |
tree | ba45e2b144e0d66a69c0502a7823c28239d0bc66 /src/tools/vppapigen/vppapigen_c.py | |
parent | 3459ece6da90627b161e2128b5926f1e58e7db65 (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/vppapigen_c.py')
-rw-r--r-- | src/tools/vppapigen/vppapigen_c.py | 71 |
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') |