api: verify message size on receipt
When a message is received, verify that it's sufficiently large to accomodate any VLAs within message. To do that, we need a way to calculate message size including any VLAs. This patch adds such funcionality to vppapigen and necessary C code to use those to validate message size on receipt. Drop messages which are malformed. Type: improvement Signed-off-by: Klement Sekera <ksekera@cisco.com> Change-Id: I2903aa21dee84be6822b064795ba314de46c18f4
This commit is contained in:
committed by
Ole Tr�an
parent
755042dec0
commit
9b7e8acf79
@@ -548,6 +548,10 @@ _(APP_DEL_CERT_KEY_PAIR_REPLY, app_del_cert_key_pair_reply)
|
||||
#include <vnet/session/session.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/session/session.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
#define vl_printfun
|
||||
#include <vnet/session/session.api.h>
|
||||
#undef vl_printfun
|
||||
@@ -573,7 +577,8 @@ echo_api_hookup (echo_main_t * em)
|
||||
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
|
||||
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
|
||||
vl_api_##n##_t_calc_size);
|
||||
foreach_quic_echo_msg;
|
||||
#undef _
|
||||
}
|
||||
|
||||
@@ -242,6 +242,9 @@ api_trace_clear_capture (vat_main_t * vam)
|
||||
#define vl_printfun
|
||||
#include <tracedump/tracedump.api.h>
|
||||
#undef vl_printfun
|
||||
#define vl_calcsizefun
|
||||
#include <tracedump/tracedump.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
void
|
||||
manual_setup_message_id_table (vat_main_t * vam)
|
||||
@@ -251,7 +254,8 @@ manual_setup_message_id_table (vat_main_t * vam)
|
||||
vl_api_trace_details_t_handler, vl_noop_handler,
|
||||
vl_api_trace_details_t_endian, vl_api_trace_details_t_print,
|
||||
sizeof (vl_api_trace_details_t), 1, vl_api_trace_details_t_print_json,
|
||||
vl_api_trace_details_t_tojson, vl_api_trace_details_t_fromjson);
|
||||
vl_api_trace_details_t_tojson, vl_api_trace_details_t_fromjson,
|
||||
vl_api_trace_details_t_calc_size);
|
||||
}
|
||||
|
||||
#define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE manual_setup_message_id_table
|
||||
|
||||
@@ -210,7 +210,8 @@ class ToJSON():
|
||||
if b[1] == 0:
|
||||
continue
|
||||
write(' if (a & {})\n'.format(b[0]))
|
||||
write(' cJSON_AddItemToArray(array, cJSON_CreateString("{}"));\n'.format(b[0]))
|
||||
write(
|
||||
' cJSON_AddItemToArray(array, cJSON_CreateString("{}"));\n'.format(b[0]))
|
||||
write(' return array;\n')
|
||||
write('}\n')
|
||||
|
||||
@@ -685,7 +686,7 @@ TOP_BOILERPLATE = '''\
|
||||
|| defined(vl_printfun) ||defined(vl_endianfun) \\
|
||||
|| defined(vl_api_version)||defined(vl_typedefs) \\
|
||||
|| defined(vl_msg_name)||defined(vl_msg_name_crc_list) \\
|
||||
|| defined(vl_api_version_tuple)
|
||||
|| defined(vl_api_version_tuple) || defined(vl_calcsizefun)
|
||||
/* ok, something was selected */
|
||||
#else
|
||||
#warning no content included from {input_filename}
|
||||
@@ -750,7 +751,7 @@ def msg_name_crc_list(s, suffix):
|
||||
|
||||
for t in s['Define']:
|
||||
output += "\\\n_(VL_API_%s, %s, %08x) " % \
|
||||
(t.name.upper(), t.name, t.crc)
|
||||
(t.name.upper(), t.name, t.crc)
|
||||
output += "\n#endif"
|
||||
|
||||
return output
|
||||
@@ -970,13 +971,13 @@ static inline void *vl_api_{name}_t_print{suffix} (vl_api_{name}_t *a, void *han
|
||||
|
||||
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(' (void)s;\n')
|
||||
write(' char *out = cJSON_Print(o);\n')
|
||||
write(' vl_print(handle, out);\n');
|
||||
write(' vl_print(handle, out);\n')
|
||||
write(' cJSON_Delete(o);\n')
|
||||
write(' cJSON_free(out);\n');
|
||||
write(' cJSON_free(out);\n')
|
||||
write(' return handle;\n')
|
||||
write('}\n\n');
|
||||
write('}\n\n')
|
||||
|
||||
write("\n#endif")
|
||||
write("\n#endif /* vl_printfun */\n")
|
||||
@@ -1145,7 +1146,7 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
|
||||
'''
|
||||
|
||||
for t in objs:
|
||||
if t.__class__.__name__ == 'Enum' or t.__class__.__name__ == 'EnumFlag' :
|
||||
if t.__class__.__name__ == 'Enum' or t.__class__.__name__ == 'EnumFlag':
|
||||
output += signature.format(name=t.name)
|
||||
if t.enumtype in ENDIAN_STRINGS:
|
||||
output += (' *a = {}(*a);\n'
|
||||
@@ -1187,6 +1188,78 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
|
||||
return output
|
||||
|
||||
|
||||
def calc_size_fun(objs, modulename):
|
||||
'''Main entry point for calculate size function generation'''
|
||||
output = '''\
|
||||
|
||||
/****** Calculate size functions *****/\n\
|
||||
#ifdef vl_calcsizefun
|
||||
#ifndef included_{module}_calcsizefun
|
||||
#define included_{module}_calcsizefun
|
||||
|
||||
'''
|
||||
output = output.format(module=modulename)
|
||||
|
||||
signature = '''\
|
||||
/* calculate message size of message in network byte order */
|
||||
static inline uword vl_api_{name}_t_calc_size (vl_api_{name}_t *a)
|
||||
{{
|
||||
'''
|
||||
|
||||
for o in objs:
|
||||
tname = o.__class__.__name__
|
||||
|
||||
output += signature.format(name=o.name)
|
||||
output += f" return sizeof(*a)"
|
||||
if tname == 'Using':
|
||||
if 'length' in o.alias:
|
||||
try:
|
||||
tmp = int(o.alias['length'])
|
||||
if tmp == 0:
|
||||
raise (f"Unexpected length '0' for alias {o}")
|
||||
except:
|
||||
# output += f" + vl_api_{o.alias.name}_t_calc_size({o.name})"
|
||||
print("culprit:")
|
||||
print(o)
|
||||
print(dir(o.alias))
|
||||
print(o.alias)
|
||||
raise
|
||||
elif tname == 'Enum' or tname == 'EnumFlag':
|
||||
pass
|
||||
else:
|
||||
for b in o.block:
|
||||
if b.type == 'Option':
|
||||
continue
|
||||
elif b.type == 'Field':
|
||||
if b.fieldtype.startswith('vl_api_'):
|
||||
output += f" - sizeof(a->{b.fieldname})"
|
||||
output += f" + {b.fieldtype}_calc_size(&a->{b.fieldname})"
|
||||
elif b.type == 'Array':
|
||||
if b.lengthfield:
|
||||
m = list(filter(lambda x: x.fieldname == b.lengthfield, o.block))
|
||||
if len(m) != 1:
|
||||
raise Exception(f"Expected 1 match for field '{b.lengthfield}', got '{m}'")
|
||||
lf = m[0]
|
||||
if lf.fieldtype in ENDIAN_STRINGS:
|
||||
output += f" + {ENDIAN_STRINGS[lf.fieldtype]}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])"
|
||||
elif lf.fieldtype == "u8":
|
||||
output += f" + a->{b.lengthfield} * sizeof(a->{b.fieldname}[0])"
|
||||
else:
|
||||
raise Exception(f"Don't know how to endian swap {lf.fieldtype}")
|
||||
else:
|
||||
# Fixed length strings decay to nul terminated u8
|
||||
if b.fieldtype == 'string':
|
||||
if b.modern_vla:
|
||||
output += f" + vl_api_string_len(&a->{b.fieldname})"
|
||||
|
||||
output += ";\n"
|
||||
output += '}\n\n'
|
||||
output += "\n#endif"
|
||||
output += "\n#endif /* vl_calcsizefun */\n\n"
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def version_tuple(s, module):
|
||||
'''Generate semantic version string'''
|
||||
output = '''\
|
||||
@@ -1336,6 +1409,10 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
|
||||
#include "{module}.api.h"
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include "{module}.api.h"
|
||||
#undef vl_calsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
@@ -1371,6 +1448,7 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
|
||||
' .print_json = vl_api_{n}_t_print_json,\n'
|
||||
' .tojson = vl_api_{n}_t_tojson,\n'
|
||||
' .fromjson = vl_api_{n}_t_fromjson,\n'
|
||||
' .calc_size = vl_api_{n}_t_calc_size,\n'
|
||||
' .is_autoendian = {auto}}};\n'
|
||||
.format(n=s.caller, ID=s.caller.upper(),
|
||||
auto=d.autoendian))
|
||||
@@ -1389,6 +1467,7 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
|
||||
' .print_json = vl_api_{n}_t_print_json,\n'
|
||||
' .tojson = vl_api_{n}_t_tojson,\n'
|
||||
' .fromjson = vl_api_{n}_t_fromjson,\n'
|
||||
' .calc_size = vl_api_{n}_t_calc_size,\n'
|
||||
' .is_autoendian = {auto}}};\n'
|
||||
.format(n=s.reply, ID=s.reply.upper(),
|
||||
auto=d.autoendian))
|
||||
@@ -1427,6 +1506,10 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
|
||||
#include "{module}.api.h"
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include "{module}.api.h"
|
||||
#undef vl_calsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
@@ -1488,7 +1571,8 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
|
||||
' 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'
|
||||
' vl_api_{n}_t_fromjson,\n'
|
||||
' vl_api_{n}_t_calc_size);\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))
|
||||
@@ -1510,7 +1594,8 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
|
||||
' 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'
|
||||
' vl_api_{n}_t_fromjson,\n'
|
||||
' vl_api_{n}_t_calc_size);\n'
|
||||
.format(n=e, ID=e.upper()))
|
||||
|
||||
write('}\n')
|
||||
@@ -1729,6 +1814,10 @@ def generate_c_test2_boilerplate(services, defines, module, stream):
|
||||
#include "{module}.api.h"
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include "{module}.api.h"
|
||||
#undef vl_calsizefun
|
||||
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
#include "{module}.api.h"
|
||||
@@ -1863,6 +1952,7 @@ def run(args, apifilename, s):
|
||||
output += stream.getvalue()
|
||||
stream.close()
|
||||
output += endianfun(s['types'] + s['Define'], modulename)
|
||||
output += calc_size_fun(s['types'] + s['Define'], modulename)
|
||||
output += version_tuple(s, basename)
|
||||
output += BOTTOM_BOILERPLATE.format(input_filename=basename,
|
||||
file_crc=s['file_crc'])
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
#include <vlibmemory/memclnt.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vlibmemory/memclnt.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#if VPP_API_TEST_BUILTIN == 0
|
||||
#define vl_print(handle, ...)
|
||||
@@ -2737,11 +2741,11 @@ void
|
||||
vat_api_hookup (vat_main_t * vam)
|
||||
{
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers (VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson);
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, vl_noop_handler, \
|
||||
vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
|
||||
foreach_vpe_api_reply_msg;
|
||||
#if VPP_API_TEST_BUILTIN == 0
|
||||
foreach_standalone_reply_msg;
|
||||
|
||||
+6
-1
@@ -276,6 +276,10 @@ vl_api_app_del_cert_key_pair_reply_t_handler (
|
||||
#include <vnet/session/session.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/session/session.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_printfun
|
||||
#include <vnet/session/session.api.h>
|
||||
@@ -303,7 +307,8 @@ vcl_bapi_hookup (void)
|
||||
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
|
||||
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
|
||||
vl_api_##n##_t_calc_size);
|
||||
foreach_sock_msg;
|
||||
#undef _
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ typedef struct
|
||||
void *print_json; /**< message print function (JSON format) */
|
||||
void *tojson; /**< binary to JSON convert function */
|
||||
void *fromjson; /**< JSON to binary convert function */
|
||||
void *calc_size; /**< message size calculation */
|
||||
int size; /**< message size */
|
||||
int traced; /**< is this message to be traced? */
|
||||
int replay; /**< is this message to be replayed? */
|
||||
@@ -170,17 +171,18 @@ VL_MSG_API_POISON (const void *a)
|
||||
}
|
||||
|
||||
/* api_shared.c prototypes */
|
||||
void vl_msg_api_handler (void *the_msg);
|
||||
void vl_msg_api_handler_no_free (void *the_msg);
|
||||
void vl_msg_api_handler_no_trace_no_free (void *the_msg);
|
||||
void vl_msg_api_trace_only (void *the_msg);
|
||||
void vl_msg_api_handler (void *the_msg, uword msg_len);
|
||||
void vl_msg_api_handler_no_free (void *the_msg, uword msg_len);
|
||||
void vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len);
|
||||
void vl_msg_api_trace_only (void *the_msg, uword msg_len);
|
||||
void vl_msg_api_cleanup_handler (void *the_msg);
|
||||
void vl_msg_api_replay_handler (void *the_msg);
|
||||
void vl_msg_api_socket_handler (void *the_msg);
|
||||
void vl_msg_api_socket_handler (void *the_msg, uword msg_len);
|
||||
void vl_msg_api_set_handlers (int msg_id, char *msg_name, void *handler,
|
||||
void *cleanup, void *endian, void *print,
|
||||
int msg_size, int traced, void *print_json,
|
||||
void *tojson, void *fromjson);
|
||||
void *tojson, void *fromjson,
|
||||
void *validate_size);
|
||||
void vl_msg_api_clean_handlers (int msg_id);
|
||||
void vl_msg_api_config (vl_msg_api_msg_config_t *);
|
||||
void vl_msg_api_set_cleanup_handler (int msg_id, void *fp);
|
||||
@@ -251,6 +253,9 @@ typedef struct api_main_t
|
||||
/** Message convert function vector */
|
||||
void *(**msg_fromjson_handlers) (cJSON *, int *);
|
||||
|
||||
/** Message calc size function vector */
|
||||
uword (**msg_calc_size_funcs) (void *);
|
||||
|
||||
/** Message name vector */
|
||||
const char **msg_names;
|
||||
|
||||
|
||||
+60
-29
@@ -500,8 +500,8 @@ vl_msg_api_barrier_release (void)
|
||||
}
|
||||
|
||||
always_inline void
|
||||
msg_handler_internal (api_main_t * am,
|
||||
void *the_msg, int trace_it, int do_it, int free_it)
|
||||
msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len,
|
||||
int trace_it, int do_it, int free_it)
|
||||
{
|
||||
u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
|
||||
u8 *(*print_fp) (void *, void *);
|
||||
@@ -545,8 +545,35 @@ msg_handler_internal (api_main_t * am,
|
||||
}
|
||||
}
|
||||
|
||||
if (do_it)
|
||||
uword calc_size = 0;
|
||||
uword (*calc_size_fp) (void *);
|
||||
calc_size_fp = am->msg_calc_size_funcs[id];
|
||||
ASSERT (NULL != calc_size_fp);
|
||||
if (calc_size_fp)
|
||||
{
|
||||
calc_size = (*calc_size_fp) (the_msg);
|
||||
ASSERT (calc_size <= msg_len);
|
||||
if (calc_size > msg_len)
|
||||
{
|
||||
clib_warning (
|
||||
"Truncated message '%s' (id %u) received, calculated size "
|
||||
"%lu is bigger than actual size %llu, message dropped.",
|
||||
am->msg_names[id], id, calc_size, msg_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
|
||||
"verify message size is correct",
|
||||
am->msg_names[id], id);
|
||||
}
|
||||
|
||||
/* don't process message if it's truncated, otherwise byte swaps
|
||||
* and stuff could corrupt memory even beyond message if it's malicious
|
||||
* e.g. VLA length field set to 1M elements, but VLA empty */
|
||||
if (do_it && calc_size <= msg_len)
|
||||
{
|
||||
|
||||
if (!am->is_mp_safe[id])
|
||||
{
|
||||
vl_msg_api_barrier_trace_context (am->msg_names[id]);
|
||||
@@ -569,6 +596,7 @@ msg_handler_internal (api_main_t * am,
|
||||
if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
|
||||
clib_call_callbacks (am->perf_counter_cbs, am, id,
|
||||
1 /* after */ );
|
||||
|
||||
if (!am->is_mp_safe[id])
|
||||
vl_msg_api_barrier_release ();
|
||||
}
|
||||
@@ -767,32 +795,30 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp,
|
||||
}
|
||||
|
||||
void
|
||||
vl_msg_api_handler (void *the_msg)
|
||||
vl_msg_api_handler (void *the_msg, uword msg_len)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
|
||||
msg_handler_internal (am, the_msg,
|
||||
(am->rx_trace
|
||||
&& am->rx_trace->enabled) /* trace_it */ ,
|
||||
1 /* do_it */ , 1 /* free_it */ );
|
||||
msg_handler_internal (am, the_msg, msg_len,
|
||||
(am->rx_trace && am->rx_trace->enabled) /* trace_it */,
|
||||
1 /* do_it */, 1 /* free_it */);
|
||||
}
|
||||
|
||||
void
|
||||
vl_msg_api_handler_no_free (void *the_msg)
|
||||
vl_msg_api_handler_no_free (void *the_msg, uword msg_len)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
msg_handler_internal (am, the_msg,
|
||||
(am->rx_trace
|
||||
&& am->rx_trace->enabled) /* trace_it */ ,
|
||||
1 /* do_it */ , 0 /* free_it */ );
|
||||
msg_handler_internal (am, the_msg, msg_len,
|
||||
(am->rx_trace && am->rx_trace->enabled) /* trace_it */,
|
||||
1 /* do_it */, 0 /* free_it */);
|
||||
}
|
||||
|
||||
void
|
||||
vl_msg_api_handler_no_trace_no_free (void *the_msg)
|
||||
vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
|
||||
0 /* free_it */ );
|
||||
msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */,
|
||||
0 /* free_it */);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -805,14 +831,13 @@ vl_msg_api_handler_no_trace_no_free (void *the_msg)
|
||||
*
|
||||
*/
|
||||
void
|
||||
vl_msg_api_trace_only (void *the_msg)
|
||||
vl_msg_api_trace_only (void *the_msg, uword msg_len)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
|
||||
msg_handler_internal (am, the_msg,
|
||||
(am->rx_trace
|
||||
&& am->rx_trace->enabled) /* trace_it */ ,
|
||||
0 /* do_it */ , 0 /* free_it */ );
|
||||
msg_handler_internal (am, the_msg, msg_len,
|
||||
(am->rx_trace && am->rx_trace->enabled) /* trace_it */,
|
||||
0 /* do_it */, 0 /* free_it */);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -863,14 +888,13 @@ vl_msg_api_get_msg_length (void *msg_arg)
|
||||
* vl_msg_api_socket_handler
|
||||
*/
|
||||
void
|
||||
vl_msg_api_socket_handler (void *the_msg)
|
||||
vl_msg_api_socket_handler (void *the_msg, uword msg_len)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
|
||||
msg_handler_internal (am, the_msg,
|
||||
(am->rx_trace
|
||||
&& am->rx_trace->enabled) /* trace_it */ ,
|
||||
1 /* do_it */ , 0 /* free_it */ );
|
||||
msg_handler_internal (am, the_msg, msg_len,
|
||||
(am->rx_trace && am->rx_trace->enabled) /* trace_it */,
|
||||
1 /* do_it */, 0 /* free_it */);
|
||||
}
|
||||
|
||||
#define foreach_msg_api_vector \
|
||||
@@ -882,6 +906,7 @@ vl_msg_api_socket_handler (void *the_msg)
|
||||
_ (msg_print_json_handlers) \
|
||||
_ (msg_tojson_handlers) \
|
||||
_ (msg_fromjson_handlers) \
|
||||
_ (msg_calc_size_funcs) \
|
||||
_ (api_trace_cfg) \
|
||||
_ (message_bounce) \
|
||||
_ (is_mp_safe) \
|
||||
@@ -927,6 +952,7 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
|
||||
am->msg_print_json_handlers[c->id] = c->print_json;
|
||||
am->msg_tojson_handlers[c->id] = c->tojson;
|
||||
am->msg_fromjson_handlers[c->id] = c->fromjson;
|
||||
am->msg_calc_size_funcs[c->id] = c->calc_size;
|
||||
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;
|
||||
@@ -948,7 +974,8 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
|
||||
void
|
||||
vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
|
||||
void *endian, void *print, int size, int traced,
|
||||
void *print_json, void *tojson, void *fromjson)
|
||||
void *print_json, void *tojson, void *fromjson,
|
||||
void *calc_size)
|
||||
{
|
||||
vl_msg_api_msg_config_t cfg;
|
||||
vl_msg_api_msg_config_t *c = &cfg;
|
||||
@@ -969,6 +996,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
|
||||
c->tojson = tojson;
|
||||
c->fromjson = fromjson;
|
||||
c->print_json = print_json;
|
||||
c->calc_size = calc_size;
|
||||
vl_msg_api_config (c);
|
||||
}
|
||||
|
||||
@@ -999,8 +1027,11 @@ vl_msg_api_queue_handler (svm_queue_t * q)
|
||||
{
|
||||
uword msg;
|
||||
|
||||
while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
|
||||
vl_msg_api_handler ((void *) msg);
|
||||
while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0))
|
||||
{
|
||||
msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data));
|
||||
vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len));
|
||||
}
|
||||
}
|
||||
|
||||
u32
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
static void
|
||||
vl_api_get_first_msg_id_t_handler (vl_api_get_first_msg_id_t *mp)
|
||||
{
|
||||
@@ -177,6 +181,7 @@ vlib_api_init (void)
|
||||
c->print_json = vl_api_##n##_t_print_json; \
|
||||
c->tojson = vl_api_##n##_t_tojson; \
|
||||
c->fromjson = vl_api_##n##_t_fromjson; \
|
||||
c->calc_size = vl_api_##n##_t_calc_size; \
|
||||
c->size = sizeof (vl_api_##n##_t); \
|
||||
c->traced = 1; /* trace, so these msgs print */ \
|
||||
c->replay = 0; /* don't replay client create/delete msgs */ \
|
||||
@@ -505,8 +510,9 @@ api_rx_from_node (vlib_main_t *vm, vlib_node_runtime_t *node,
|
||||
vec_add (long_msg, msg, msg_len);
|
||||
}
|
||||
msg = long_msg;
|
||||
msg_len = vec_len (long_msg);
|
||||
}
|
||||
vl_msg_api_handler_no_trace_no_free (msg);
|
||||
vl_msg_api_handler_no_trace_no_free (msg, msg_len);
|
||||
}
|
||||
|
||||
/* Free what we've been given. */
|
||||
@@ -704,20 +710,20 @@ rpc_api_hookup (vlib_main_t *vm)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_noop_handler, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \
|
||||
0 /* do not trace */, vl_api_##n##_t_print_json, \
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, vl_noop_handler, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0 /* do not trace */, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
|
||||
foreach_rpc_api_msg;
|
||||
#undef _
|
||||
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_noop_handler, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \
|
||||
1 /* do trace */, vl_api_##n##_t_print_json, \
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, vl_noop_handler, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1 /* do trace */, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
|
||||
foreach_plugin_trace_msg;
|
||||
#undef _
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) clib_warning (__VA_ARGS__)
|
||||
#define vl_printfun
|
||||
@@ -240,7 +244,8 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size)
|
||||
}
|
||||
rv = clib_net_to_host_u32 (rp->response);
|
||||
|
||||
vl_msg_api_handler ((void *) rp);
|
||||
msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
|
||||
vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
|
||||
break;
|
||||
}
|
||||
return (rv);
|
||||
@@ -289,6 +294,7 @@ vl_client_disconnect (void)
|
||||
svm_queue_t *vl_input_queue;
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
time_t begin;
|
||||
msgbuf_t *msgbuf;
|
||||
|
||||
vl_input_queue = am->vl_input_queue;
|
||||
vl_client_send_disconnect (0 /* wait for reply */ );
|
||||
@@ -321,10 +327,12 @@ vl_client_disconnect (void)
|
||||
if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY)
|
||||
{
|
||||
clib_warning ("queue drain: %d", ntohs (rp->_vl_msg_id));
|
||||
vl_msg_api_handler ((void *) rp);
|
||||
msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
|
||||
vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
|
||||
continue;
|
||||
}
|
||||
vl_msg_api_handler ((void *) rp);
|
||||
msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
|
||||
vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -364,11 +372,11 @@ vl_client_install_client_message_handlers (void)
|
||||
{
|
||||
api_main_t *am = vlibapi_get_main ();
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
noop_handler, vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson); \
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N, #n, vl_api_##n##_t_handler, noop_handler, \
|
||||
vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size); \
|
||||
am->api_trace_cfg[VL_API_##N].replay_enable = 0;
|
||||
foreach_api_msg;
|
||||
#undef _
|
||||
@@ -569,6 +577,11 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name)
|
||||
old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY];
|
||||
am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *)
|
||||
vl_api_get_first_msg_id_reply_t_handler;
|
||||
if (!am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY])
|
||||
{
|
||||
am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY] =
|
||||
(uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size;
|
||||
}
|
||||
|
||||
/* Ask the data-plane for the message-ID base of the indicated plugin */
|
||||
mm->first_msg_id_reply_ready = 0;
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
socket_main_t socket_main;
|
||||
|
||||
#define SOCK_API_REG_HANDLE_BIT (1<<31)
|
||||
@@ -200,7 +204,7 @@ vl_socket_process_api_msg (vl_api_registration_t * rp, i8 * input_v)
|
||||
|
||||
u8 *the_msg = (u8 *) (mbp->data);
|
||||
socket_main.current_rp = rp;
|
||||
vl_msg_api_socket_handler (the_msg);
|
||||
vl_msg_api_socket_handler (the_msg, ntohl (mbp->data_len));
|
||||
socket_main.current_rp = 0;
|
||||
}
|
||||
|
||||
@@ -792,11 +796,11 @@ vl_sock_api_init (vlib_main_t * vm)
|
||||
return 0;
|
||||
|
||||
#define _(N, n, t) \
|
||||
vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson); \
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, \
|
||||
vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size); \
|
||||
am->api_trace_cfg[VL_API_##N].replay_enable = 0;
|
||||
foreach_vlib_api_msg;
|
||||
#undef _
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vlibmemory/vl_memory_api_h.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) clib_warning (__VA_ARGS__)
|
||||
#define vl_printfun
|
||||
@@ -134,7 +138,7 @@ vl_socket_client_read_internal (socket_client_main_t * scm, int wait)
|
||||
|
||||
if (vec_len (scm->socket_rx_buffer) >= data_len + sizeof (*mbp))
|
||||
{
|
||||
vl_msg_api_socket_handler ((void *) (mbp->data));
|
||||
vl_msg_api_socket_handler ((void *) (mbp->data), data_len);
|
||||
|
||||
if (vec_len (scm->socket_rx_buffer) == data_len + sizeof (*mbp))
|
||||
_vec_len (scm->socket_rx_buffer) = 0;
|
||||
@@ -433,11 +437,11 @@ vl_sock_client_install_message_handlers (void)
|
||||
{
|
||||
|
||||
#define _(N, n) \
|
||||
vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
noop_handler, vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson);
|
||||
vl_msg_api_set_handlers ( \
|
||||
VL_API_##N, #n, vl_api_##n##_t_handler, noop_handler, \
|
||||
vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
|
||||
vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
|
||||
vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
|
||||
foreach_sock_client_api_msg;
|
||||
#undef _
|
||||
}
|
||||
|
||||
@@ -514,7 +514,9 @@ vl_api_add_del_ip_punt_redirect_v2_t_handler (
|
||||
goto out;
|
||||
|
||||
if (0 != n_paths)
|
||||
vec_validate (rpaths, n_paths - 1);
|
||||
{
|
||||
vec_validate (rpaths, n_paths - 1);
|
||||
}
|
||||
|
||||
for (ii = 0; ii < n_paths; ii++)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <vnet/ip/ip.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/ip/ip.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* API message ID base */
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include <vnet/ipsec/ipsec.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/ipsec/ipsec.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* API message ID base */
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <vnet/l2/l2.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/l2/l2.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* API message ID base */
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include <vnet/srmpls/sr_mpls.api.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
#define vl_calcsizefun
|
||||
#include <vnet/srmpls/sr_mpls.api.h>
|
||||
#undef vl_calcsizefun
|
||||
|
||||
#define vl_printfun
|
||||
#include <vnet/srmpls/sr_mpls.api.h>
|
||||
#undef vl_printfun
|
||||
@@ -194,7 +198,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
|
||||
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
|
||||
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
|
||||
vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
|
||||
vl_api_##n##_t_calc_size);
|
||||
foreach_vpe_api_msg;
|
||||
#undef _
|
||||
|
||||
@@ -207,7 +212,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
|
||||
vl_api_sr_mpls_policy_add_t_handler, vl_noop_handler,
|
||||
vl_api_sr_mpls_policy_add_t_endian, vl_api_sr_mpls_policy_add_t_print, 256,
|
||||
1, vl_api_sr_mpls_policy_add_t_print_json,
|
||||
vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson);
|
||||
vl_api_sr_mpls_policy_add_t_tojson, vl_api_sr_mpls_policy_add_t_fromjson,
|
||||
vl_api_sr_mpls_policy_add_t_calc_size);
|
||||
|
||||
/*
|
||||
* Manually register the sr policy mod msg, so we trace enough bytes
|
||||
@@ -218,7 +224,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
|
||||
vl_api_sr_mpls_policy_mod_t_handler, vl_noop_handler,
|
||||
vl_api_sr_mpls_policy_mod_t_endian, vl_api_sr_mpls_policy_mod_t_print, 256,
|
||||
1, vl_api_sr_mpls_policy_mod_t_print_json,
|
||||
vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson);
|
||||
vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson,
|
||||
vl_api_sr_mpls_policy_mod_t_calc_size);
|
||||
|
||||
/*
|
||||
* Set up the (msg_name, crc, message-id) table
|
||||
|
||||
Reference in New Issue
Block a user