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 <ot@cisco.com>
Change-Id: I7588f8ccb38b2d1e8d85ea17be99bac43f756267
Signed-off-by: Ole Troan <ot@cisco.com>
This commit is contained in:
Ole Troan
2020-05-18 11:14:05 +02:00
committed by Andrew Yourtchenko
parent 0ab36f5575
commit e796a18734
5 changed files with 65 additions and 9 deletions

@ -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;
}

@ -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')

@ -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;

@ -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; \

@ -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);
}