From: Ole Troan Date: Mon, 18 May 2020 09:14:05 +0000 (+0200) Subject: api: make vpp api handlers endian independent X-Git-Tag: v21.01-rc0~346 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;ds=sidebyside;h=e796a18734fae0783a226c38550796260f0acfec;p=vpp.git api: make vpp api handlers endian independent Add a new boolean to signal that the API infrastructure should performan any required endian conversions for the API handler. am->is_autoendian[mm->msg_id_base + VL_API_MAP_ADD_DOMAIN] = 1; Similarly add new REPLY_ macros that perform endian conversion. These changes do not change the on-the-wire encoding of the API messages, and therefore the API CRC is not changed. Type: feature Signed-off-by: Ole Troan Change-Id: I7588f8ccb38b2d1e8d85ea17be99bac43f756267 Signed-off-by: Ole Troan --- diff --git a/src/plugins/map/map_api.c b/src/plugins/map/map_api.c index 13f05526afa..94d2458dd79 100644 --- a/src/plugins/map/map_api.c +++ b/src/plugins/map/map_api.c @@ -48,14 +48,14 @@ vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp) mp->ip6_prefix.len, (ip6_address_t *) & mp->ip6_src.address, mp->ip6_src.len, mp->ea_bits_len, mp->psid_offset, - mp->psid_length, &index, ntohs (mp->mtu), flags, - mp->tag); + mp->psid_length, &index, mp->mtu, flags, mp->tag); /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY, + REPLY_MACRO2_END(VL_API_MAP_ADD_DOMAIN_REPLY, ({ - rmp->index = ntohl(index); + rmp->index = index; })); + /* *INDENT-ON* */ } @@ -556,6 +556,9 @@ map_plugin_api_hookup (vlib_main_t * vm) map_main_t *mm = &map_main; mm->msg_id_base = setup_message_id_table (); + + api_main_t *am = vlibapi_get_main (); + am->is_autoendian[mm->msg_id_base + VL_API_MAP_ADD_DOMAIN] = 1; return 0; } diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py index 46f60dea843..b7a62dc4102 100644 --- a/src/tools/vppapigen/vppapigen_c.py +++ b/src/tools/vppapigen/vppapigen_c.py @@ -394,6 +394,7 @@ def endianfun_array(o): name=o.fieldname)) return output +no_endian_conversion = {'client_index': None} def endianfun_obj(o): output = '' @@ -403,6 +404,9 @@ def endianfun_obj(o): output += (' s = format(s, "\\n{} {} {} (print not implemented");\n' .format(o.type, o.fieldtype, o.fieldname)) return output + if o.fieldname in no_endian_conversion: + output += ' /* a->{n} = a->{n} (no-op) */\n'.format(n=o.fieldname) + return output if o.fieldtype in endian_strings: output += (' a->{name} = {format}(a->{name});\n' .format(name=o.fieldname, @@ -594,6 +598,7 @@ def generate_include_types(s, module, stream): def generate_c_boilerplate(services, defines, file_crc, module, stream): write = stream.write + define_hash = {d.name:d for d in defines} hdr = '''\ #define vl_endianfun /* define message structures */ @@ -612,6 +617,7 @@ def generate_c_boilerplate(services, defines, file_crc, module, stream): write('static u16\n') write('setup_message_id_table (void) {\n') write(' api_main_t *am = my_api_main;\n') + write(' vl_msg_api_msg_config_t c;\n') write(' u16 msg_id_base = vl_msg_api_get_msg_ids ("{}_{crc:08x}", VL_MSG_FIRST_AVAILABLE);\n' .format(module, crc=file_crc)) @@ -621,11 +627,16 @@ def generate_c_boilerplate(services, defines, file_crc, module, stream): ' VL_API_{ID} + msg_id_base);\n' .format(n=d.name, ID=d.name.upper(), crc=d.crc)) for s in services: - write(' vl_msg_api_set_handlers(VL_API_{ID} + msg_id_base, "{n}",\n' - ' vl_api_{n}_t_handler, vl_noop_handler,\n' - ' vl_api_{n}_t_endian, vl_api_{n}_t_print,\n' - ' sizeof(vl_api_{n}_t), 1);\n' + d = define_hash[s.caller] + write(' c = (vl_msg_api_msg_config_t) {{.id = VL_API_{ID} + msg_id_base,\n' + ' .name = "{n}",\n' + ' .handler = vl_api_{n}_t_handler,\n' + ' .cleanup = vl_noop_handler,\n' + ' .endian = vl_api_{n}_t_endian,\n' + ' .print = vl_api_{n}_t_print,\n' + ' .is_autoendian = 0}};\n' .format(n=s.caller, ID=s.caller.upper())) + write(' vl_msg_api_config (&c);\n') write(' return msg_id_base;\n') write('}\n') diff --git a/src/vlibapi/api_common.h b/src/vlibapi/api_common.h index 0ea0943cb39..86b1c5ac3ee 100644 --- a/src/vlibapi/api_common.h +++ b/src/vlibapi/api_common.h @@ -132,6 +132,7 @@ typedef struct int replay; /**< is this message to be replayed? */ int message_bounce; /**< do not free message after processing */ int is_mp_safe; /**< worker thread barrier required? */ + int is_autoendian; /**< endian conversion required? */ } vl_msg_api_msg_config_t; /** Message header structure */ @@ -248,6 +249,9 @@ typedef struct /** Message is mp safe vector */ u8 *is_mp_safe; + /** Message requires us to do endian conversion */ + u8 *is_autoendian; + /** Allocator ring vectors (in shared memory) */ struct ring_alloc_ *arings; diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 57502570f11..c7348cfde97 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -59,6 +59,26 @@ do { \ vl_api_send_msg (rp, (u8 *)rmp); \ } while(0); +#define REPLY_MACRO2_END(t, body) \ +do { \ + vl_api_registration_t *rp; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + rp = vl_api_client_index_to_registration (mp->client_index); \ + if (rp == 0) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = t+(REPLY_MSG_ID_BASE); \ + rmp->context = mp->context; \ + rmp->retval = rv; \ + do {body;} while (0); \ + api_main_t *am = vlibapi_get_main (); \ + void (*endian_fp) (void *); \ + endian_fp = am->msg_endian_handlers[t]; \ + (*endian_fp) (rmp); \ + vl_api_send_msg (rp, (u8 *)rmp); \ +} while(0); + #define REPLY_MACRO2_ZERO(t, body) \ do { \ vl_api_registration_t *rp; \ diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c index fbaa9c9e013..c818668c09f 100644 --- a/src/vlibapi/api_shared.c +++ b/src/vlibapi/api_shared.c @@ -485,6 +485,14 @@ msg_handler_internal (api_main_t * am, vl_msg_api_barrier_trace_context (am->msg_names[id]); vl_msg_api_barrier_sync (); } + + if (am->is_autoendian[id]) + { + void (*endian_fp) (void *); + endian_fp = am->msg_endian_handlers[id]; + (*endian_fp) (the_msg); + } + (*am->msg_handlers[id]) (the_msg); if (!am->is_mp_safe[id]) vl_msg_api_barrier_release (); @@ -606,6 +614,13 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp, if (PREDICT_FALSE (vl_msg_api_fuzz_hook != 0)) (*vl_msg_api_fuzz_hook) (id, the_msg); + if (am->is_autoendian[id]) + { + void (*endian_fp) (void *); + endian_fp = am->msg_endian_handlers[id]; + (*endian_fp) (the_msg); + } + (*handler) (the_msg, vm, node); if (is_private) { @@ -772,7 +787,8 @@ _(msg_endian_handlers) \ _(msg_print_handlers) \ _(api_trace_cfg) \ _(message_bounce) \ -_(is_mp_safe) +_(is_mp_safe) \ +_(is_autoendian) void vl_msg_api_config (vl_msg_api_msg_config_t * c) @@ -813,6 +829,7 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c) am->msg_print_handlers[c->id] = c->print; am->message_bounce[c->id] = c->message_bounce; am->is_mp_safe[c->id] = c->is_mp_safe; + am->is_autoendian[c->id] = c->is_autoendian; am->api_trace_cfg[c->id].size = c->size; am->api_trace_cfg[c->id].trace_enable = c->traced; @@ -842,6 +859,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup, c->replay = 1; c->message_bounce = 0; c->is_mp_safe = 0; + c->is_autoendian = 0; vl_msg_api_config (c); }