diff options
Diffstat (limited to 'src/vlibmemory/memory_api.c')
-rw-r--r-- | src/vlibmemory/memory_api.c | 147 |
1 files changed, 144 insertions, 3 deletions
diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c index 6c066a152f4..a16110f2fa1 100644 --- a/src/vlibmemory/memory_api.c +++ b/src/vlibmemory/memory_api.c @@ -674,6 +674,147 @@ vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now) } } +void (*vl_mem_api_fuzz_hook) (u16, void *); + +/* This is only to be called from a vlib/vnet app */ +static void +vl_mem_api_handler_with_vm_node (api_main_t *am, svm_region_t *vlib_rp, + void *the_msg, vlib_main_t *vm, + vlib_node_runtime_t *node, u8 is_private) +{ + u16 id = clib_net_to_host_u16 (*((u16 *) the_msg)); + u8 *(*handler) (void *, void *, void *); + u8 *(*print_fp) (void *, void *); + svm_region_t *old_vlib_rp; + void *save_shmem_hdr; + int is_mp_safe = 1; + + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + ELOG_TYPE_DECLARE (e) = { + .format = "api-msg: %s", + .format_args = "T4", + }; + struct + { + u32 c; + } * ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names) && am->msg_names[id]) + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + } + + if (id < vec_len (am->msg_handlers) && am->msg_handlers[id]) + { + handler = (void *) am->msg_handlers[id]; + + if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled)) + vl_msg_api_trace (am, am->rx_trace, the_msg); + + if (PREDICT_FALSE (am->msg_print_flag)) + { + fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]); + print_fp = (void *) am->msg_print_handlers[id]; + if (print_fp == 0) + { + fformat (stdout, " [no registered print fn for msg %d]\n", id); + } + else + { + (*print_fp) (the_msg, vm); + } + } + is_mp_safe = am->is_mp_safe[id]; + + if (!is_mp_safe) + { + vl_msg_api_barrier_trace_context (am->msg_names[id]); + vl_msg_api_barrier_sync (); + } + if (is_private) + { + old_vlib_rp = am->vlib_rp; + save_shmem_hdr = am->shmem_hdr; + am->vlib_rp = vlib_rp; + am->shmem_hdr = (void *) vlib_rp->user_ctx; + } + + if (PREDICT_FALSE (vl_mem_api_fuzz_hook != 0)) + (*vl_mem_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); + } + if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) + clib_call_callbacks (am->perf_counter_cbs, am, id, 0 /* before */); + + (*handler) (the_msg, vm, node); + + if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0)) + clib_call_callbacks (am->perf_counter_cbs, am, id, 1 /* after */); + if (is_private) + { + am->vlib_rp = old_vlib_rp; + am->shmem_hdr = save_shmem_hdr; + } + if (!is_mp_safe) + vl_msg_api_barrier_release (); + } + else + { + clib_warning ("no handler for msg id %d", id); + } + + /* + * Special-case, so we can e.g. bounce messages off the vnet + * main thread without copying them... + */ + if (id >= vec_len (am->message_bounce) || !(am->message_bounce[id])) + { + if (is_private) + { + old_vlib_rp = am->vlib_rp; + save_shmem_hdr = am->shmem_hdr; + am->vlib_rp = vlib_rp; + am->shmem_hdr = (void *) vlib_rp->user_ctx; + } + vl_msg_api_free (the_msg); + if (is_private) + { + am->vlib_rp = old_vlib_rp; + am->shmem_hdr = save_shmem_hdr; + } + } + + if (PREDICT_FALSE (am->elog_trace_api_messages)) + { + ELOG_TYPE_DECLARE (e) = { .format = "api-msg-done(%s): %s", + .format_args = "t4T4", + .n_enum_strings = 2, + .enum_strings = { + "barrier", + "mp-safe", + } }; + + struct + { + u32 barrier; + u32 c; + } * ed; + ed = ELOG_DATA (am->elog_main, e); + if (id < vec_len (am->msg_names) && am->msg_names[id]) + ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]); + else + ed->c = elog_string (am->elog_main, "BOGUS"); + ed->barrier = is_mp_safe; + } +} + static inline int void_mem_api_handle_msg_i (api_main_t * am, svm_region_t * vlib_rp, vlib_main_t * vm, vlib_node_runtime_t * node, @@ -687,7 +828,7 @@ void_mem_api_handle_msg_i (api_main_t * am, svm_region_t * vlib_rp, if (!svm_queue_sub2 (q, (u8 *) & mp)) { VL_MSG_API_UNPOISON ((void *) mp); - vl_msg_api_handler_with_vm_node (am, vlib_rp, (void *) mp, vm, node, + vl_mem_api_handler_with_vm_node (am, vlib_rp, (void *) mp, vm, node, is_private); return 0; } @@ -737,8 +878,8 @@ vl_mem_api_handle_rpc (vlib_main_t * vm, vlib_node_runtime_t * node) for (i = 0; i < vec_len (vm->processing_rpc_requests); i++) { mp = vm->processing_rpc_requests[i]; - vl_msg_api_handler_with_vm_node (am, am->vlib_rp, (void *) mp, vm, - node, 0 /* is_private */ ); + vl_mem_api_handler_with_vm_node (am, am->vlib_rp, (void *) mp, vm, + node, 0 /* is_private */); } vl_msg_api_barrier_release (); } |