#include "vat.h" vat_main_t vat_main; void vat_suspend (vlib_main_t * vm, f64 interval) { vlib_process_suspend (vm, interval); } static u8 * format_api_error (u8 * s, va_list * args) { vat_main_t *vam = va_arg (*args, vat_main_t *); i32 error = va_arg (*args, u32); uword *p; p = hash_get (vam->error_string_by_error_number, -error); if (p) s = format (s, "%s", p[0]); else s = format (s, "%d", error); return s; } static void init_error_string_table (vat_main_t * vam) { vam->error_string_by_error_number = hash_create (0, sizeof (uword)); #define _(n,v,s) hash_set (vam->error_string_by_error_number, -v, s); foreach_vnet_api_error; #undef _ hash_set (vam->error_string_by_error_number, 99, "Misc"); } static clib_error_t * api_main_init (vlib_main_t * vm) { vat_main_t *vam = &vat_main; int rv; int vat_plugin_init (vat_main_t * vam); vam->vlib_main = vm; vam->my_client_index = (u32) ~ 0; /* Ensure that vam->inbuf is never NULL */ vec_validate (vam->inbuf, 0); vec_validate (vam->cmd_reply, 0); vec_reset_length (vam->cmd_reply); init_error_string_table (vam); rv = vat_plugin_init (vam); if (rv) clib_warning ("vat_plugin_init returned %d", rv); return 0; } VLIB_INIT_FUNCTION (api_main_init); void vat_plugin_hash_create (void) { vat_main_t *vam = &vat_main; vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword)); vam->function_by_name = hash_create_string (0, sizeof (uword)); vam->help_by_name = hash_create_string (0, sizeof (uword)); } static void maybe_register_api_client (vat_main_t * vam) { vl_api_registration_t **regpp; vl_api_registration_t *regp; svm_region_t *svm; void *oldheap; api_main_t *am = &api_main; if (vam->my_client_index != ~0) return; pool_get (am->vl_clients, regpp); svm = am->vlib_rp; pthread_mutex_lock (&svm->mutex); oldheap = svm_push_data_heap (svm); *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); regp = *regpp; clib_memset (regp, 0, sizeof (*regp)); regp->registration_type = REGISTRATION_TYPE_SHMEM; regp->vl_api_registration_pool_index = regpp - am->vl_clients; regp->vlib_rp = svm; regp->shmem_hdr = am->shmem_hdr; /* Loopback connection */ regp->vl_input_queue = am->shmem_hdr->vl_input_queue; regp->name = format (0, "%s", "vpp-internal"); vec_add1 (regp->name, 0); pthread_mutex_unlock (&svm->mutex); svm_pop_heap (oldheap); vam->my_client_index = vl_msg_api_handle_from_index_and_epoch (regp->vl_api_registration_pool_index, am->shmem_hdr->application_restarts); vam->vl_input_queue = am->shmem_hdr->vl_input_queue; api_sw_interface_dump (vam); } static clib_error_t * api_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { vat_main_t *vam = &vat_main; unformat_input_t _input; uword c; u8 *cmdp, *argsp, *this_cmd; uword *p; u32 arg_len; int rv; int (*fp) (vat_main_t *); api_main_t *am = &api_main; maybe_register_api_client (vam); /* vec_validated in the init routine */ _vec_len (vam->inbuf) = 0; vam->input = &_input; while (((c = unformat_get_input (input)) != '\n') && (c != UNFORMAT_END_OF_INPUT)) vec_add1 (vam->inbuf, c); /* Null-terminate the command */ vec_add1 (vam->inbuf, 0); /* In case no args given */ vec_add1 (vam->inbuf, 0); /* Split input into cmd + args */ this_cmd = cmdp = vam->inbuf; /* Skip leading whitespace */ while (cmdp < (this_cmd + vec_len (this_cmd))) { if (*cmdp == ' ' || *cmdp == '\t' || *cmdp == '\n') { cmdp++; } else break; } argsp = cmdp; /* Advance past the command */ while (argsp < (this_cmd + vec_len (this_cmd))) { if (*argsp != ' ' && *argsp != '\t' && *argsp != '\n' && *argsp != 0) { argsp++; } else break; } /* NULL terminate the command */ *argsp++ = 0; /* No arguments? Ensure that argsp points to a proper (empty) string */ if (argsp == (this_cmd + vec_len (this_cmd) - 1)) argsp[0] = 0; else while (argsp < (this_cmd + vec_len (this_cmd))) { if (*argsp == ' ' || *argsp == '\t' || *argsp == '\n') { argsp++; } else break; } /* Blank input line? */ if (*cmdp == 0) return 0; p = hash_get_mem (vam->function_by_name, cmdp); if (p == 0) { return clib_error_return (0, "'%s': function not found\n", cmdp); } arg_len = strlen ((char *) argsp); unformat_init_string (vam->input, (char *) argsp, arg_len); fp = (void *) p[0]; rv = (*fp) (vam); if (rv < 0) { unformat_free (vam->input); return clib_error_return (0, "%s error: %U\n", cmdp, format_api_error, vam, rv); } if (vam->regenerate_interface_table) { vam->regenerate_interface_table = 0; api_sw_interface_dump (vam); } unformat_free (vam->input); return 0; } /* *INDENT-OFF* */ VLIB_CLI_COMMAND (api_command, static) = { .path = "binary-api", .short_help = "binary-api [help] []", .function = api_command_fn, .is_mp_safe = 1, }; /* *INDENT-ON* */ void api_cli_output (void *notused, const char *fmt, ...) { va_list va; vat_main_t *vam = &vat_main; vlib_main_t *vm = vam->vlib_main; vlib_process_t *cp = vlib_get_current_process (vm); u8 *s; va_start (va, fmt); s = va_format (0, fmt, &va); va_end (va); /* Terminate with \n if not present. */ if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n') vec_add1 (s, '\n'); if ((!cp) || (!cp->output_function)) fformat (stdout, "%v", s); else cp->output_function (cp->output_function_arg, s, vec_len (s)); vec_free (s); } u16 vl_client_get_first_plugin_msg_id (const char *plugin_name) { api_main_t *am = &api_main; vl_api_msg_range_t *rp; uword *p; p = hash_get_mem (am->msg_range_by_name, plugin_name); if (p == 0) return ~0; rp = vec_elt_at_index (am->msg_ranges, p[0]); return (rp->first_msg_id); } uword unformat_sw_if_index (unformat_input_t * input, va_list * args) { void *vam_unused = va_arg (*args, void *); u32 *result = va_arg (*args, u32 *); vnet_main_t *vnm = vnet_get_main (); u32 sw_if_index = ~0; if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) { *result = sw_if_index; return 1; } return 0; } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */