From 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Dec 2016 23:05:39 +0100 Subject: Reorganize source tree to use single autotools instance Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion --- src/vlib/unix/plugin.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 src/vlib/unix/plugin.c (limited to 'src/vlib/unix/plugin.c') diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c new file mode 100644 index 00000000..b3d5be02 --- /dev/null +++ b/src/vlib/unix/plugin.c @@ -0,0 +1,260 @@ +/* + * plugin.c: plugin handling + * + * Copyright (c) 2011 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +plugin_main_t vlib_plugin_main; + +void +vlib_set_get_handoff_structure_cb (void *cb) +{ + plugin_main_t *pm = &vlib_plugin_main; + pm->handoff_structure_get_cb = cb; +} + +static void * +vnet_get_handoff_structure (void) +{ + void *(*fp) (void); + + fp = vlib_plugin_main.handoff_structure_get_cb; + if (fp == 0) + return 0; + else + return (*fp) (); +} + +static int +load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) +{ + void *handle, *register_handle; + clib_error_t *(*fp) (vlib_main_t *, void *, int); + clib_error_t *error; + void *handoff_structure; + + handle = dlopen ((char *) pi->name, RTLD_LAZY); + + /* + * Note: this can happen if the plugin has an undefined symbol reference, + * so print a warning. Otherwise, the poor slob won't know what happened. + * Ask me how I know that... + */ + if (handle == 0) + { + clib_warning ("%s", dlerror ()); + return -1; + } + + pi->handle = handle; + + + register_handle = dlsym (pi->handle, "vlib_plugin_register"); + if (register_handle == 0) + { + dlclose (handle); + clib_warning ("Plugin missing vlib_plugin_register: %s\n", + (char *) pi->name); + return 1; + } + + fp = register_handle; + + handoff_structure = vnet_get_handoff_structure (); + + if (handoff_structure == 0) + error = clib_error_return (0, "handoff structure callback returned 0"); + else + error = (*fp) (pm->vlib_main, handoff_structure, from_early_init); + + if (error) + { + clib_error_report (error); + dlclose (handle); + return 1; + } + + clib_warning ("Loaded plugin: %s", pi->name); + + return 0; +} + +static u8 ** +split_plugin_path (plugin_main_t * pm) +{ + int i; + u8 **rv = 0; + u8 *path = pm->plugin_path; + u8 *this = 0; + + for (i = 0; i < vec_len (pm->plugin_path); i++) + { + if (path[i] != ':') + { + vec_add1 (this, path[i]); + continue; + } + vec_add1 (this, 0); + vec_add1 (rv, this); + this = 0; + } + if (this) + { + vec_add1 (this, 0); + vec_add1 (rv, this); + } + return rv; +} + +int +vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) +{ + DIR *dp; + struct dirent *entry; + struct stat statb; + uword *p; + plugin_info_t *pi; + u8 **plugin_path; + int i; + + plugin_path = split_plugin_path (pm); + + for (i = 0; i < vec_len (plugin_path); i++) + { + dp = opendir ((char *) plugin_path[i]); + + if (dp == 0) + continue; + + while ((entry = readdir (dp))) + { + u8 *plugin_name; + + if (pm->plugin_name_filter) + { + int j; + for (j = 0; j < vec_len (pm->plugin_name_filter); j++) + if (entry->d_name[j] != pm->plugin_name_filter[j]) + goto next; + } + + plugin_name = format (0, "%s/%s%c", plugin_path[i], + entry->d_name, 0); + + /* Only accept .so */ + char *ext = strrchr ((const char *) plugin_name, '.'); + /* unreadable */ + if (!ext || (strcmp (ext, ".so") != 0) || + stat ((char *) plugin_name, &statb) < 0) + { + ignore: + vec_free (plugin_name); + continue; + } + + /* a dir or other things which aren't plugins */ + if (!S_ISREG (statb.st_mode)) + goto ignore; + + p = hash_get_mem (pm->plugin_by_name_hash, plugin_name); + if (p == 0) + { + vec_add2 (pm->plugin_info, pi, 1); + pi->name = plugin_name; + pi->file_info = statb; + + if (load_one_plugin (pm, pi, from_early_init)) + { + vec_free (plugin_name); + _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1; + continue; + } + memset (pi, 0, sizeof (*pi)); + hash_set_mem (pm->plugin_by_name_hash, plugin_name, + pi - pm->plugin_info); + } + next: + ; + } + closedir (dp); + vec_free (plugin_path[i]); + } + vec_free (plugin_path); + return 0; +} + +char *vlib_plugin_path __attribute__ ((weak)); +char *vlib_plugin_path = ""; +char *vlib_plugin_name_filter __attribute__ ((weak)); +char *vlib_plugin_name_filter = 0; + +int +vlib_plugin_early_init (vlib_main_t * vm) +{ + plugin_main_t *pm = &vlib_plugin_main; + + pm->plugin_path = format (0, "%s%c", vlib_plugin_path, 0); + + clib_warning ("plugin path %s", pm->plugin_path); + + if (vlib_plugin_name_filter) + pm->plugin_name_filter = format (0, "%s%c", vlib_plugin_name_filter, 0); + + pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword)); + pm->vlib_main = vm; + + return vlib_load_new_plugins (pm, 1 /* from_early_init */ ); +} + +static clib_error_t * +vlib_plugins_show_cmd_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + plugin_main_t *pm = &vlib_plugin_main; + u8 *s = 0; + u8 *key = 0; + uword *value = 0; + int index = 1; + + s = format (s, " Plugin path is: %s\n", pm->plugin_path); + if (vlib_plugin_name_filter) + s = format (s, " Plugin filter: %s\n", vlib_plugin_name_filter); + + s = format (s, " Plugins loaded: \n"); + hash_foreach_mem (key, value, pm->plugin_by_name_hash, + { + if (key != 0) + s = format (s, " %d.%s\n", index, key); index++;} + ); + + vlib_cli_output (vm, "%v", s); + vec_free (s); + return 0; +} + +VLIB_CLI_COMMAND (plugins_show_cmd, static) = +{ +.path = "show plugins",.short_help = "show loaded plugins",.function = + vlib_plugins_show_cmd_fn,}; +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From f935e336db1282c1ec67cf703db2d3cfaec32915 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Fri, 6 Jan 2017 14:33:05 +0100 Subject: plugin: add API to get pointer to symbol in different plugin Change-Id: Ic2fbbd8227d5d0c033e5d7b5f43b859a4889d2f3 Signed-off-by: Damjan Marion --- src/vlib/unix/plugin.c | 31 ++++++++++++++++++++++++------- src/vlib/unix/plugin.h | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index b3d5be02..987f7d05 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -40,6 +40,20 @@ vnet_get_handoff_structure (void) return (*fp) (); } +void * +vlib_get_plugin_symbol (char *plugin_name, char *symbol_name) +{ + plugin_main_t *pm = &vlib_plugin_main; + uword *p; + plugin_info_t *pi; + + if ((p = hash_get_mem (pm->plugin_by_name_hash, plugin_name)) == 0) + return 0; + + pi = vec_elt_at_index (pm->plugin_info, p[0]); + return dlsym (pi->handle, symbol_name); +} + static int load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) { @@ -48,7 +62,7 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) clib_error_t *error; void *handoff_structure; - handle = dlopen ((char *) pi->name, RTLD_LAZY); + handle = dlopen ((char *) pi->filename, RTLD_LAZY); /* * Note: this can happen if the plugin has an undefined symbol reference, @@ -144,6 +158,7 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) while ((entry = readdir (dp))) { u8 *plugin_name; + u8 *filename; if (pm->plugin_name_filter) { @@ -153,17 +168,16 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) goto next; } - plugin_name = format (0, "%s/%s%c", plugin_path[i], - entry->d_name, 0); + filename = format (0, "%s/%s%c", plugin_path[i], entry->d_name, 0); /* Only accept .so */ - char *ext = strrchr ((const char *) plugin_name, '.'); + char *ext = strrchr ((const char *) filename, '.'); /* unreadable */ if (!ext || (strcmp (ext, ".so") != 0) || - stat ((char *) plugin_name, &statb) < 0) + stat ((char *) filename, &statb) < 0) { ignore: - vec_free (plugin_name); + vec_free (filename); continue; } @@ -171,20 +185,23 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) if (!S_ISREG (statb.st_mode)) goto ignore; + plugin_name = format (0, "%s%c", entry->d_name, 0); p = hash_get_mem (pm->plugin_by_name_hash, plugin_name); if (p == 0) { vec_add2 (pm->plugin_info, pi, 1); pi->name = plugin_name; + pi->filename = filename; pi->file_info = statb; if (load_one_plugin (pm, pi, from_early_init)) { vec_free (plugin_name); + vec_free (filename); _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1; + memset (pi, 0, sizeof (*pi)); continue; } - memset (pi, 0, sizeof (*pi)); hash_set_mem (pm->plugin_by_name_hash, plugin_name, pi - pm->plugin_info); } diff --git a/src/vlib/unix/plugin.h b/src/vlib/unix/plugin.h index f35c9c5d..1c74cdd2 100644 --- a/src/vlib/unix/plugin.h +++ b/src/vlib/unix/plugin.h @@ -61,6 +61,7 @@ typedef struct { u8 *name; + u8 *filename; struct stat file_info; void *handle; } plugin_info_t; @@ -86,6 +87,7 @@ extern plugin_main_t vlib_plugin_main; int vlib_plugin_early_init (vlib_main_t * vm); int vlib_load_new_plugins (plugin_main_t * pm, int from_early_init); +void *vlib_get_plugin_symbol (char *plugin_name, char *symbol_name); #endif /* __included_plugin_h__ */ -- cgit 1.2.3-korg From fe6bdfd84573cd8813a211f9094ee734f088ce16 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Fri, 20 Jan 2017 19:50:09 -0500 Subject: binary-api debug CLI works with plugins Change-Id: I81f33f5153d5afac94b66b5a8cb91da77463af79 Signed-off-by: Dave Barach --- src/examples/sample-plugin/sample/sample_test.c | 37 +--- src/plugins/acl/acl_test.c | 51 +----- src/plugins/flowperpkt/flowperpkt_test.c | 45 +---- .../export-vxlan-gpe/vxlan_gpe_ioam_export_test.c | 46 +---- src/plugins/ioam/export/ioam_export_test.c | 44 +---- src/plugins/ioam/lib-pot/pot_test.c | 48 +---- src/plugins/ioam/lib-trace/trace_test.c | 48 +---- src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_test.c | 56 +----- src/plugins/lb/lb_test.c | 35 +--- src/plugins/snat/snat_test.c | 57 +----- src/vat/api_format.c | 95 ++++------ src/vat/vat.h | 33 +--- src/vlib/unix/plugin.c | 9 +- src/vlibapi/api_helper_macros.h | 1 - src/vlibapi/vat_helper_macros.h | 76 ++++++++ src/vpp-api-test.am | 3 + src/vpp.am | 6 +- src/vpp/api/api_main.c | 39 ++++ src/vpp/api/plugin.c | 201 +++++++++++++++++++++ src/vpp/api/plugin.h | 61 +++++++ 20 files changed, 476 insertions(+), 515 deletions(-) create mode 100644 src/vlibapi/vat_helper_macros.h create mode 100644 src/vpp/api/plugin.c create mode 100644 src/vpp/api/plugin.h (limited to 'src/vlib/unix/plugin.c') diff --git a/src/examples/sample-plugin/sample/sample_test.c b/src/examples/sample-plugin/sample/sample_test.c index dd1b0215..a47710ee 100644 --- a/src/examples/sample-plugin/sample/sample_test.c +++ b/src/examples/sample-plugin/sample/sample_test.c @@ -23,6 +23,7 @@ #include #include #include +#include uword unformat_sw_if_index (unformat_input_t * input, va_list * args); @@ -87,42 +88,6 @@ foreach_standard_reply_retval_handler; _(SAMPLE_MACSWAP_ENABLE_DISABLE_REPLY, sample_macswap_enable_disable_reply) -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_sample_macswap_enable_disable (vat_main_t * vam) { sample_test_main_t * sm = &sample_test_main; diff --git a/src/plugins/acl/acl_test.c b/src/plugins/acl/acl_test.c index a0e413e1..5cacf716 100644 --- a/src/plugins/acl/acl_test.c +++ b/src/plugins/acl/acl_test.c @@ -25,6 +25,7 @@ #include #include #include +#include uword unformat_sw_if_index (unformat_input_t * input, va_list * args); @@ -259,42 +260,6 @@ _(MACIP_ACL_INTERFACE_ADD_DEL_REPLY, macip_acl_interface_add_del_reply) \ _(MACIP_ACL_INTERFACE_GET_REPLY, macip_acl_interface_get_reply) \ _(ACL_PLUGIN_GET_VERSION_REPLY, acl_plugin_get_version_reply) -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_acl_plugin_get_version (vat_main_t * vam) { acl_test_main_t * sm = &acl_test_main; @@ -520,7 +485,6 @@ static int api_acl_add_replace (vat_main_t * vam) static int api_acl_del (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_acl_del_t * mp; @@ -544,7 +508,6 @@ static int api_acl_del (vat_main_t * vam) static int api_macip_acl_del (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_acl_del_t * mp; @@ -568,7 +531,6 @@ static int api_macip_acl_del (vat_main_t * vam) static int api_acl_interface_add_del (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_acl_interface_add_del_t * mp; @@ -636,7 +598,6 @@ static int api_acl_interface_add_del (vat_main_t * vam) static int api_macip_acl_interface_add_del (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_macip_acl_interface_add_del_t * mp; @@ -687,7 +648,6 @@ static int api_macip_acl_interface_add_del (vat_main_t * vam) static int api_acl_interface_set_acl_list (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_acl_interface_set_acl_list_t * mp; @@ -746,7 +706,6 @@ static int api_acl_interface_set_acl_list (vat_main_t * vam) static int api_acl_interface_list_dump (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; u32 sw_if_index = ~0; @@ -775,7 +734,6 @@ static int api_acl_interface_list_dump (vat_main_t * vam) static int api_acl_dump (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; u32 acl_index = ~0; @@ -802,7 +760,6 @@ static int api_acl_dump (vat_main_t * vam) static int api_macip_acl_dump (vat_main_t * vam) { - acl_test_main_t * sm = &acl_test_main; unformat_input_t * i = vam->input; f64 timeout; u32 acl_index = ~0; @@ -978,8 +935,8 @@ _(macip_acl_interface_add_del, " | sw_if_index [add|del] acl msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~0) - vat_api_hookup (vam); + acl_vat_api_hookup (vam); vec_free(name); diff --git a/src/plugins/flowperpkt/flowperpkt_test.c b/src/plugins/flowperpkt/flowperpkt_test.c index 716818ff..9211ebe3 100644 --- a/src/plugins/flowperpkt/flowperpkt_test.c +++ b/src/plugins/flowperpkt/flowperpkt_test.c @@ -19,6 +19,7 @@ #include #include #include +#include /** * @file vpp_api_test plugin @@ -88,47 +89,9 @@ foreach_standard_reply_retval_handler; _(FLOWPERPKT_TX_INTERFACE_ADD_DEL_REPLY, \ flowperpkt_tx_interface_add_del_reply) - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_flowperpkt_tx_interface_add_del (vat_main_t * vam) { - flowperpkt_test_main_t *sm = &flowperpkt_test_main; unformat_input_t *i = vam->input; f64 timeout; int enable_disable = 1; @@ -177,8 +140,8 @@ api_flowperpkt_tx_interface_add_del (vat_main_t * vam) #define foreach_vpe_api_msg \ _(flowperpkt_tx_interface_add_del, " [disable]") -void -vat_api_hookup (vat_main_t * vam) +static void +flowperpkt_vat_api_hookup (vat_main_t * vam) { flowperpkt_test_main_t *sm = &flowperpkt_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -218,7 +181,7 @@ vat_plugin_register (vat_main_t * vam) /* Don't attempt to hook up API messages if the data plane plugin is AWOL */ if (sm->msg_id_base != (u16) ~ 0) - vat_api_hookup (vam); + flowperpkt_vat_api_hookup (vam); vec_free (name); diff --git a/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_test.c b/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_test.c index 494263d9..5b641cc7 100644 --- a/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_test.c +++ b/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_test.c @@ -23,7 +23,7 @@ #include #include #include - +#include /* Declare message IDs */ #include @@ -86,47 +86,9 @@ foreach_standard_reply_retval_handler; #define foreach_vpe_api_reply_msg \ _(VXLAN_GPE_IOAM_EXPORT_ENABLE_DISABLE_REPLY, vxlan_gpe_ioam_export_enable_disable_reply) - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_vxlan_gpe_ioam_export_enable_disable (vat_main_t * vam) { - export_test_main_t *sm = &export_test_main; unformat_input_t *i = vam->input; f64 timeout; int is_disable = 0; @@ -160,8 +122,8 @@ api_vxlan_gpe_ioam_export_enable_disable (vat_main_t * vam) #define foreach_vpe_api_msg \ _(vxlan_gpe_ioam_export_enable_disable, " [disable]") -void -vat_api_hookup (vat_main_t * vam) +static void +vxlan_gpe_ioam_vat_api_hookup (vat_main_t * vam) { export_test_main_t *sm = &export_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -199,7 +161,7 @@ vat_plugin_register (vat_main_t * vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~ 0) - vat_api_hookup (vam); + vxlan_gpe_ioam_vat_api_hookup (vam); vec_free (name); diff --git a/src/plugins/ioam/export/ioam_export_test.c b/src/plugins/ioam/export/ioam_export_test.c index f991fc0c..a4ec80d0 100644 --- a/src/plugins/ioam/export/ioam_export_test.c +++ b/src/plugins/ioam/export/ioam_export_test.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Declare message IDs */ @@ -87,46 +88,9 @@ foreach_standard_reply_retval_handler; _(IOAM_EXPORT_IP6_ENABLE_DISABLE_REPLY, ioam_export_ip6_enable_disable_reply) -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_ioam_export_ip6_enable_disable (vat_main_t * vam) { - export_test_main_t *sm = &export_test_main; unformat_input_t *i = vam->input; f64 timeout; int is_disable = 0; @@ -159,8 +123,8 @@ api_ioam_export_ip6_enable_disable (vat_main_t * vam) #define foreach_vpe_api_msg \ _(ioam_export_ip6_enable_disable, " [disable]") -void -vat_api_hookup (vat_main_t * vam) +static void +ioam_export_vat_api_hookup (vat_main_t * vam) { export_test_main_t *sm = &export_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -198,7 +162,7 @@ vat_plugin_register (vat_main_t * vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~ 0) - vat_api_hookup (vam); + ioam_export_vat_api_hookup (vam); vec_free (name); diff --git a/src/plugins/ioam/lib-pot/pot_test.c b/src/plugins/ioam/lib-pot/pot_test.c index 2e870238..9f9d0c99 100644 --- a/src/plugins/ioam/lib-pot/pot_test.c +++ b/src/plugins/ioam/lib-pot/pot_test.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Declare message IDs */ #include @@ -118,48 +119,9 @@ _(POT_PROFILE_ACTIVATE_REPLY, pot_profile_activate_reply) \ _(POT_PROFILE_DEL_REPLY, pot_profile_del_reply) \ _(POT_PROFILE_SHOW_CONFIG_DETAILS, pot_profile_show_config_details) - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - - static int api_pot_profile_add (vat_main_t *vam) { #define MAX_BITS 64 - pot_test_main_t * sm = &pot_test_main; unformat_input_t *input = vam->input; vl_api_pot_profile_add_t *mp; u8 *name = NULL; @@ -234,7 +196,6 @@ OUT: static int api_pot_profile_activate (vat_main_t *vam) { #define MAX_BITS 64 - pot_test_main_t * sm = &pot_test_main; unformat_input_t *input = vam->input; vl_api_pot_profile_activate_t *mp; u8 *name = NULL; @@ -275,7 +236,6 @@ OUT: static int api_pot_profile_del (vat_main_t *vam) { - pot_test_main_t * sm = &pot_test_main; vl_api_pot_profile_del_t *mp; f64 timeout; @@ -287,7 +247,6 @@ static int api_pot_profile_del (vat_main_t *vam) static int api_pot_profile_show_config_dump (vat_main_t *vam) { - pot_test_main_t * sm = &pot_test_main; unformat_input_t *input = vam->input; vl_api_pot_profile_show_config_dump_t *mp; f64 timeout; @@ -320,7 +279,8 @@ _(pot_profile_activate, "name id [0-1] ") \ _(pot_profile_del, "[id ]") \ _(pot_profile_show_config_dump, "id [0-1]") -void vat_api_hookup (vat_main_t *vam) +static void +pot_vat_api_hookup (vat_main_t *vam) { pot_test_main_t * sm = &pot_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -357,7 +317,7 @@ clib_error_t * vat_plugin_register (vat_main_t *vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~0) - vat_api_hookup (vam); + pot_vat_api_hookup (vam); vec_free(name); diff --git a/src/plugins/ioam/lib-trace/trace_test.c b/src/plugins/ioam/lib-trace/trace_test.c index 111dd461..f4f1d4d5 100644 --- a/src/plugins/ioam/lib-trace/trace_test.c +++ b/src/plugins/ioam/lib-trace/trace_test.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Declare message IDs */ #include @@ -115,48 +116,9 @@ _(TRACE_PROFILE_ADD_REPLY, trace_profile_add_reply) \ _(TRACE_PROFILE_DEL_REPLY, trace_profile_del_reply) \ _(TRACE_PROFILE_SHOW_CONFIG_REPLY, trace_profile_show_config_reply) - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - - static int api_trace_profile_add (vat_main_t * vam) { - trace_test_main_t *sm = &trace_test_main; unformat_input_t *input = vam->input; vl_api_trace_profile_add_t *mp; u8 trace_type = 0; @@ -204,7 +166,6 @@ api_trace_profile_add (vat_main_t * vam) static int api_trace_profile_del (vat_main_t * vam) { - trace_test_main_t *sm = &trace_test_main; vl_api_trace_profile_del_t *mp; f64 timeout; @@ -217,7 +178,6 @@ api_trace_profile_del (vat_main_t * vam) static int api_trace_profile_show_config (vat_main_t * vam) { - trace_test_main_t *sm = &trace_test_main; vl_api_trace_profile_show_config_t *mp; f64 timeout; M (TRACE_PROFILE_SHOW_CONFIG, trace_profile_show_config); @@ -237,8 +197,8 @@ _(trace_profile_del, "[id ]") \ _(trace_profile_show_config, "[id ]") -void -vat_api_hookup (vat_main_t * vam) +static void +ioam_trace_vat_api_hookup (vat_main_t * vam) { trace_test_main_t *sm = &trace_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -276,7 +236,7 @@ vat_plugin_register (vat_main_t * vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~ 0) - vat_api_hookup (vam); + ioam_trace_vat_api_hookup (vam); vec_free (name); diff --git a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_test.c b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_test.c index b5fee724..7c4088ee 100644 --- a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_test.c +++ b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_test.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Declare message IDs */ #include @@ -96,49 +97,9 @@ _(VXLAN_GPE_IOAM_VNI_DISABLE_REPLY, vxlan_gpe_ioam_vni_disable_reply) \ _(VXLAN_GPE_IOAM_TRANSIT_ENABLE_REPLY, vxlan_gpe_ioam_transit_enable_reply) \ _(VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY, vxlan_gpe_ioam_transit_disable_reply) \ - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - - static int api_vxlan_gpe_ioam_enable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; - unformat_input_t *input = vam->input; vl_api_vxlan_gpe_ioam_enable_t *mp; f64 timeout; @@ -179,7 +140,6 @@ api_vxlan_gpe_ioam_enable (vat_main_t * vam) static int api_vxlan_gpe_ioam_disable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; vl_api_vxlan_gpe_ioam_disable_t *mp; f64 timeout; @@ -192,8 +152,6 @@ api_vxlan_gpe_ioam_disable (vat_main_t * vam) static int api_vxlan_gpe_ioam_vni_enable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; - unformat_input_t *line_input = vam->input; vl_api_vxlan_gpe_ioam_vni_enable_t *mp; ip4_address_t local4, remote4; @@ -289,8 +247,6 @@ api_vxlan_gpe_ioam_vni_enable (vat_main_t * vam) static int api_vxlan_gpe_ioam_vni_disable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; - unformat_input_t *line_input = vam->input; vl_api_vxlan_gpe_ioam_vni_disable_t *mp; ip4_address_t local4, remote4; @@ -386,8 +342,6 @@ api_vxlan_gpe_ioam_vni_disable (vat_main_t * vam) static int api_vxlan_gpe_ioam_transit_enable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; - unformat_input_t *line_input = vam->input; vl_api_vxlan_gpe_ioam_transit_enable_t *mp; ip4_address_t local4; @@ -458,8 +412,6 @@ api_vxlan_gpe_ioam_transit_enable (vat_main_t * vam) static int api_vxlan_gpe_ioam_transit_disable (vat_main_t * vam) { - vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; - unformat_input_t *line_input = vam->input; vl_api_vxlan_gpe_ioam_transit_disable_t *mp; ip4_address_t local4; @@ -545,8 +497,8 @@ _(vxlan_gpe_ioam_transit_disable, ""\ "dst-ip [outer-fib-index ]") \ -void -vat_api_hookup (vat_main_t * vam) +static void +vxlan_gpe_vat_api_hookup (vat_main_t * vam) { vxlan_gpe_test_main_t *sm = &vxlan_gpe_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -584,7 +536,7 @@ vat_plugin_register (vat_main_t * vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~ 0) - vat_api_hookup (vam); + vxlan_gpe_vat_api_hookup (vam); vec_free (name); diff --git a/src/plugins/lb/lb_test.c b/src/plugins/lb/lb_test.c index 8c2eaa91..7e3519a8 100644 --- a/src/plugins/lb/lb_test.c +++ b/src/plugins/lb/lb_test.c @@ -19,6 +19,7 @@ #include #include #include +#include //TODO: Move that to vat/plugin_api.c ////////////////////////// @@ -127,35 +128,8 @@ foreach_standard_reply_retval_handler; _(LB_ADD_DEL_VIP_REPLY, lb_add_del_vip_reply) \ _(LB_ADD_DEL_AS_REPLY, lb_add_del_as_reply) -/* M: construct, but don't yet send a message */ -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memcpy (mp, &mps, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + lbtm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_lb_conf (vat_main_t * vam) { - lb_test_main_t *lbtm = &lb_test_main; unformat_input_t *i = vam->input; f64 timeout; vl_api_lb_conf_t mps, *mp; @@ -177,7 +151,6 @@ static int api_lb_conf (vat_main_t * vam) static int api_lb_add_del_vip (vat_main_t * vam) { - lb_test_main_t *lbtm = &lb_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_lb_add_del_vip_t mps, *mp; @@ -215,7 +188,6 @@ static int api_lb_add_del_vip (vat_main_t * vam) static int api_lb_add_del_as (vat_main_t * vam) { - lb_test_main_t *lbtm = &lb_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_lb_add_del_as_t mps, *mp; @@ -246,7 +218,8 @@ _(lb_conf, " [gre4|gre6] [del]") \ _(lb_add_del_as, "
[del]") -void vat_api_hookup (vat_main_t *vam) +static void +lb_vat_api_hookup (vat_main_t *vam) { lb_test_main_t * lbtm = &lb_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -285,7 +258,7 @@ clib_error_t * vat_plugin_register (vat_main_t *vam) lbtm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (lbtm->msg_id_base != (u16) ~0) - vat_api_hookup (vam); + lb_vat_api_hookup (vam); vec_free(name); diff --git a/src/plugins/snat/snat_test.c b/src/plugins/snat/snat_test.c index 013d7d9b..b601d7d9 100644 --- a/src/plugins/snat/snat_test.c +++ b/src/plugins/snat/snat_test.c @@ -21,6 +21,7 @@ #include #include #include +#include uword unformat_sw_if_index (unformat_input_t * input, va_list * args); @@ -103,44 +104,8 @@ _(SNAT_INTERFACE_ADDR_DETAILS, snat_interface_addr_details) \ _(SNAT_IPFIX_ENABLE_DISABLE_REPLY, \ snat_ipfix_enable_disable_reply) -/* M: construct, but don't yet send a message */ -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - static int api_snat_add_address_range (vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; ip4_address_t start_addr, end_addr; @@ -200,7 +165,6 @@ static int api_snat_add_address_range (vat_main_t * vam) static int api_snat_interface_add_del_feature (vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_snat_interface_add_del_feature_t * mp; @@ -246,7 +210,6 @@ static int api_snat_interface_add_del_feature (vat_main_t * vam) static int api_snat_add_static_mapping(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_snat_add_static_mapping_t * mp; @@ -338,7 +301,6 @@ static void vl_api_snat_static_mapping_details_t_handler static int api_snat_static_mapping_dump(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_static_mapping_dump_t * mp; @@ -398,7 +360,6 @@ static void vl_api_snat_show_config_reply_t_handler static int api_snat_show_config(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_show_config_t * mp; @@ -425,7 +386,6 @@ static void vl_api_snat_address_details_t_handler static int api_snat_address_dump(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_address_dump_t * mp; @@ -460,7 +420,6 @@ static void vl_api_snat_interface_details_t_handler static int api_snat_interface_dump(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_interface_dump_t * mp; @@ -485,7 +444,6 @@ static int api_snat_interface_dump(vat_main_t * vam) static int api_snat_set_workers (vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_snat_set_workers_t * mp; @@ -523,7 +481,6 @@ static void vl_api_snat_worker_details_t_handler static int api_snat_worker_dump(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_worker_dump_t * mp; @@ -548,7 +505,6 @@ static int api_snat_worker_dump(vat_main_t * vam) static int api_snat_ipfix_enable_disable (vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_snat_add_del_interface_addr_t * mp; @@ -597,7 +553,6 @@ static void vl_api_snat_interface_addr_details_t_handler static int api_snat_interface_addr_dump(vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; f64 timeout; vl_api_snat_interface_addr_dump_t * mp; @@ -622,7 +577,6 @@ static int api_snat_interface_addr_dump(vat_main_t * vam) static int api_snat_add_del_interface_addr (vat_main_t * vam) { - snat_test_main_t * sm = &snat_test_main; unformat_input_t * i = vam->input; f64 timeout; vl_api_snat_ipfix_enable_disable_t * mp; @@ -677,7 +631,8 @@ _(snat_interface_addr_dump, "") \ _(snat_ipfix_enable_disable, "[domain ] [src_port ] " \ "[disable]") -void vat_api_hookup (vat_main_t *vam) +static void +snat_vat_api_hookup (vat_main_t *vam) { snat_test_main_t * sm __attribute__((unused)) = &snat_test_main; /* Hook up handlers for replies from the data plane plug-in */ @@ -693,7 +648,9 @@ void vat_api_hookup (vat_main_t *vam) #undef _ /* API messages we can send */ -#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); +#define _(n,h) \ + hash_set_mem (vam->function_by_name, #n, api_##n); \ + clib_warning ("vam %llx add '%s' handler %llx", vam, #n, api_##n); foreach_vpe_api_msg; #undef _ @@ -715,7 +672,7 @@ clib_error_t * vat_plugin_register (vat_main_t *vam) sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); if (sm->msg_id_base != (u16) ~0) - vat_api_hookup (vam); + snat_vat_api_hookup (vam); vec_free(name); diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 1babaf40..653cf79f 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -70,6 +70,46 @@ #include #undef vl_printfun +#include + +f64 +vat_time_now (vat_main_t * vam) +{ +#if VPP_API_TEST_BUILTIN + return vlib_time_now (vam->vlib_main); +#else + return clib_time_now (&vam->clib_time); +#endif +} + +void +errmsg (char *fmt, ...) +{ + vat_main_t *vam = &vat_main; + va_list va; + u8 *s; + + va_start (va, fmt); + s = va_format (0, fmt, &va); + va_end (va); + + vec_add1 (s, 0); + +#if VPP_API_TEST_BUILTIN + vlib_cli_output (vam->vlib_main, (char *) s); +#else + { + if (vam->ifp != stdin) + fformat (vam->ofp, "%s(%d): \n", vam->current_file, + vam->input_line_number); + fformat (vam->ofp, (char *) s); + fflush (vam->ofp); + } +#endif + + vec_free (s); +} + static uword api_unformat_sw_if_index (unformat_input_t * input, va_list * args) { @@ -88,8 +128,6 @@ api_unformat_sw_if_index (unformat_input_t * input, va_list * args) return 1; } -void vat_suspend (vlib_main_t * vm, f64 interval); - #if VPP_API_TEST_BUILTIN == 0 /* Parse an IP4 address %d.%d.%d.%d. */ uword @@ -3867,59 +3905,6 @@ _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY, \ sw_interface_set_dpdk_hqos_tctbl_reply) #endif -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc_as_if_client(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc_as_if_client(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T); \ - mp->client_index = vam->my_client_index; \ -} while(0); - - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - vat_suspend (vam->vlib_main, 1e-3); \ - } \ - return -99; \ -} while(0); - -/* W2: wait for results, with timeout */ -#define W2(body) \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - (body); \ - return (vam->retval); \ - } \ - vat_suspend (vam->vlib_main, 1e-3); \ - } \ - return -99; \ -} while(0); - typedef struct { u8 *name; diff --git a/src/vat/vat.h b/src/vat/vat.h index 64be2f7f..3d7d96ae 100644 --- a/src/vat/vat.h +++ b/src/vat/vat.h @@ -190,36 +190,11 @@ typedef struct vlib_main_t *vlib_main; } vat_main_t; -vat_main_t vat_main; - -static inline f64 -vat_time_now (vat_main_t * vam) -{ -#if VPP_API_TEST_BUILTIN - return vlib_time_now (vam->vlib_main); -#else - return clib_time_now (&vam->clib_time); -#endif -} - -#if VPP_API_TEST_BUILTIN -#define errmsg(fmt,args...) \ -do { \ - vat_main_t *__vam = &vat_main; \ - vlib_cli_output (__vam->vlib_main, fmt, ##args); \ - } while(0); -#else -#define errmsg(fmt,args...) \ -do { \ - vat_main_t *__vam = &vat_main; \ - if(__vam->ifp != stdin) \ - fformat(__vam->ofp,"%s(%d): \n", __vam->current_file, \ - __vam->input_line_number); \ - fformat(__vam->ofp, fmt "\n", ##args); \ - fflush(__vam->ofp); \ -} while(0); -#endif +extern vat_main_t vat_main; +void vat_suspend (vlib_main_t * vm, f64 interval); +f64 vat_time_now (vat_main_t * vam); +void errmsg (char *fmt, ...); void vat_api_hookup (vat_main_t * vam); int api_sw_interface_dump (vat_main_t * vam); void do_one_file (vat_main_t * vam); diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index 987f7d05..40399090 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -264,10 +264,15 @@ vlib_plugins_show_cmd_fn (vlib_main_t * vm, return 0; } +/* *INDENT-OFF* */ VLIB_CLI_COMMAND (plugins_show_cmd, static) = { -.path = "show plugins",.short_help = "show loaded plugins",.function = - vlib_plugins_show_cmd_fn,}; + .path = "show plugins", + .short_help = "show loaded plugins", + .function = vlib_plugins_show_cmd_fn, +}; +/* *INDENT-ON* */ + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 16f34cfc..7f94e446 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -17,7 +17,6 @@ *------------------------------------------------------------------ */ - #ifndef __api_helper_macros_h__ #define __api_helper_macros_h__ diff --git a/src/vlibapi/vat_helper_macros.h b/src/vlibapi/vat_helper_macros.h new file mode 100644 index 00000000..7199364a --- /dev/null +++ b/src/vlibapi/vat_helper_macros.h @@ -0,0 +1,76 @@ +/* + *------------------------------------------------------------------ + * vat_helper_macros.h - collect api client helper macros in one place + * + * Copyright (c) 2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ +#ifndef __vat_helper_macros_h__ +#define __vat_helper_macros_h__ + +/* M: construct, but don't yet send a message */ + +#define M(T,t) \ +do { \ + vam->result_ready = 0; \ + mp = vl_msg_api_alloc_as_if_client(sizeof(*mp)); \ + memset (mp, 0, sizeof (*mp)); \ + mp->_vl_msg_id = ntohs (VL_API_##T); \ + mp->client_index = vam->my_client_index; \ +} while(0); + +#define M2(T,t,n) \ +do { \ + vam->result_ready = 0; \ + mp = vl_msg_api_alloc_as_if_client(sizeof(*mp)+(n)); \ + memset (mp, 0, sizeof (*mp)); \ + mp->_vl_msg_id = ntohs (VL_API_##T); \ + mp->client_index = vam->my_client_index; \ +} while(0); + + +/* S: send a message */ +#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) + +/* W: wait for results, with timeout */ +#define W \ +do { \ + timeout = vat_time_now (vam) + 1.0; \ + \ + while (vat_time_now (vam) < timeout) { \ + if (vam->result_ready == 1) { \ + return (vam->retval); \ + } \ + vat_suspend (vam->vlib_main, 1e-5); \ + } \ + return -99; \ +} while(0); + +/* W2: wait for results, with timeout */ +#define W2(body) \ +do { \ + timeout = vat_time_now (vam) + 1.0; \ + \ + while (vat_time_now (vam) < timeout) { \ + if (vam->result_ready == 1) { \ + (body); \ + return (vam->retval); \ + } \ + vat_suspend (vam->vlib_main, 1e-5); \ + } \ + return -99; \ +} while(0); + + +#endif /* __vat_helper_macros_h__ */ diff --git a/src/vpp-api-test.am b/src/vpp-api-test.am index 32610056..f0d5df62 100644 --- a/src/vpp-api-test.am +++ b/src/vpp-api-test.am @@ -44,7 +44,10 @@ vpp_api_test_LDADD = \ libvnet.la \ -lpthread -lm -lrt -ldl -lcrypto +vpp_api_test_LDFLAGS = -Wl,--export-dynamic + vpp_json_test_LDADD = libvppinfra.la -lm +vpp_json_test_LDFLAGS = -Wl,--export-dynamic nobase_include_HEADERS += \ vat/vat.h \ diff --git a/src/vpp.am b/src/vpp.am index 425f1e32..0b605ec5 100644 --- a/src/vpp.am +++ b/src/vpp.am @@ -28,7 +28,9 @@ bin_vpp_SOURCES += \ if WITH_APICLI bin_vpp_SOURCES += \ vpp/api/api_format.c \ - vpp/api/api_main.c + vpp/api/api_main.c \ + vpp/api/plugin.c \ + vpp/api/plugin.h endif # comment out to disable stats upload to gmond @@ -78,6 +80,8 @@ bin_vpp_LDADD = \ libvppinfra.la \ -lrt -lm -lpthread -ldl +bin_vpp_LDFLAGS = -Wl,--export-dynamic + if ENABLE_TESTS noinst_PROGRAMS += bin/test_client diff --git a/src/vpp/api/api_main.c b/src/vpp/api/api_main.c index fd6998f4..7bf7e8b7 100644 --- a/src/vpp/api/api_main.c +++ b/src/vpp/api/api_main.c @@ -42,11 +42,17 @@ 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; init_error_string_table (vam); vat_api_hookup (vam); + clib_warning ("vam %llx", vam); + rv = vat_plugin_init (vam); + if (rv) + clib_warning ("vat_plugin_init returned %d", rv); return 0; } @@ -183,6 +189,39 @@ api_cli_output (void *notused, const char *fmt, ...) vec_free (s); } +u16 +vl_client_get_first_plugin_msg_id (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) +{ + u32 *result = va_arg (*args, u32 *); + vnet_main_t *vnm = vnet_get_main (); + u32 sw_if_index = ~0; + u8 *if_name; + uword *p; + + 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 * diff --git a/src/vpp/api/plugin.c b/src/vpp/api/plugin.c new file mode 100644 index 00000000..c1cc928c --- /dev/null +++ b/src/vpp/api/plugin.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * plugin.c: plugin handling + */ + +#include +#include +#include +#include + +plugin_main_t vat_plugin_main; + +static int +load_one_plugin (plugin_main_t * pm, plugin_info_t * pi) +{ + void *handle, *register_handle; + clib_error_t *(*fp) (vat_main_t *); + clib_error_t *error; + + handle = dlopen ((char *) pi->name, RTLD_LAZY); + + /* + * Note: this can happen if the plugin has an undefined symbol reference, + * so print a warning. Otherwise, the poor slob won't know what happened. + * Ask me how I know that... + */ + if (handle == 0) + { + clib_warning ("%s", dlerror ()); + return -1; + } + + pi->handle = handle; + + register_handle = dlsym (pi->handle, "vat_plugin_register"); + if (register_handle == 0) + return 0; + + fp = register_handle; + + error = (*fp) (pm->vat_main); + + if (error) + { + clib_error_report (error); + dlclose (handle); + return 1; + } + + clib_warning ("Loaded plugin: %s", pi->name); + + return 0; +} + +static u8 ** +split_plugin_path (plugin_main_t * pm) +{ + int i; + u8 **rv = 0; + u8 *path = pm->plugin_path; + u8 *this = 0; + + for (i = 0; i < vec_len (pm->plugin_path); i++) + { + if (path[i] != ':') + { + vec_add1 (this, path[i]); + continue; + } + vec_add1 (this, 0); + vec_add1 (rv, this); + this = 0; + } + if (this) + { + vec_add1 (this, 0); + vec_add1 (rv, this); + } + return rv; +} + +int +vat_load_new_plugins (plugin_main_t * pm) +{ + DIR *dp; + struct dirent *entry; + struct stat statb; + uword *p; + plugin_info_t *pi; + u8 **plugin_path; + int i; + + plugin_path = split_plugin_path (pm); + + for (i = 0; i < vec_len (plugin_path); i++) + { + dp = opendir ((char *) plugin_path[i]); + + if (dp == 0) + continue; + + while ((entry = readdir (dp))) + { + u8 *plugin_name; + + if (pm->plugin_name_filter) + { + int j; + for (j = 0; j < vec_len (pm->plugin_name_filter); j++) + if (entry->d_name[j] != pm->plugin_name_filter[j]) + goto next; + } + + plugin_name = format (0, "%s/%s%c", plugin_path[i], + entry->d_name, 0); + + /* unreadable */ + if (stat ((char *) plugin_name, &statb) < 0) + { + ignore: + vec_free (plugin_name); + continue; + } + + /* a dir or other things which aren't plugins */ + if (!S_ISREG (statb.st_mode)) + goto ignore; + + p = hash_get_mem (pm->plugin_by_name_hash, plugin_name); + if (p == 0) + { + vec_add2 (pm->plugin_info, pi, 1); + pi->name = plugin_name; + pi->file_info = statb; + + if (load_one_plugin (pm, pi)) + { + vec_free (plugin_name); + _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1; + continue; + } + memset (pi, 0, sizeof (*pi)); + hash_set_mem (pm->plugin_by_name_hash, plugin_name, + pi - pm->plugin_info); + } + next: + ; + } + closedir (dp); + vec_free (plugin_path[i]); + } + vec_free (plugin_path); + return 0; +} + +#define QUOTE_(x) #x +#define QUOTE(x) QUOTE_(x) + +/* + * Load plugins from /usr/lib/vpp_api_test_plugins by default + */ +char *vat_plugin_path = "/usr/lib/vpp_api_test_plugins"; + +char *vat_plugin_name_filter = 0; + +int +vat_plugin_init (vat_main_t * vam) +{ + plugin_main_t *pm = &vat_plugin_main; + + + pm->plugin_path = format (0, "%s%c", vat_plugin_path, 0); + if (vat_plugin_name_filter) + pm->plugin_name_filter = format (0, "%s%c", vat_plugin_name_filter, 0); + + pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword)); + pm->vat_main = vam; + + return vat_load_new_plugins (pm); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vpp/api/plugin.h b/src/vpp/api/plugin.h new file mode 100644 index 00000000..559ec52f --- /dev/null +++ b/src/vpp/api/plugin.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * plugin.h: plugin handling + */ + +#ifndef __included_plugin_h__ +#define __included_plugin_h__ + +#include +#include +#include + +typedef struct +{ + u8 *name; + struct stat file_info; + void *handle; +} plugin_info_t; + +typedef struct +{ + /* loaded plugin info */ + plugin_info_t *plugin_info; + uword *plugin_by_name_hash; + + /* path and name filter */ + u8 *plugin_path; + u8 *plugin_name_filter; + + /* convenience */ + vat_main_t *vat_main; + +} plugin_main_t; + +plugin_main_t vat_plugin_main; + +int vat_plugin_init (vat_main_t * vam); +int vat_load_new_plugins (plugin_main_t * pm); + +#endif + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From 3b46cba8f4e909bc363403c6c92215159abb2f11 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 23 Jan 2017 21:13:45 +0100 Subject: Plugin infrastructure improvements This patch replaces requirement for vlib_plugin_register function in the plugin so file and introduces new macro: VLIB_PLUGIN_REGISTER () = { .version = "version string", .version_required = "requred version", .default_disabled = 1, .early_init = "early_init_function_name", }; Plugin will nor be loaded if .default_disabled is set to 1 unless explicitely enabled in startup.conf. If .verstion_required is set, plugin will not be loaded if there is version mismatch between plugin and vpp. This can be bypassed by setting "skip-version-check" for specific plugin. If .early-init string is present, plugin loader will try to resolve this specific symbol in the plugin namespace and make a function call. Following startup.conf configuration is added: plugins { path /path/to/plugin/directory plugin ila_plugin.so { enable skip-version-check } plugin acl_plugin.so { disable } } Change-Id: I706c691dd34d94ffe9e02b59831af8859a95f061 Signed-off-by: Damjan Marion --- src/plugins/acl/acl.c | 29 +-- src/plugins/acl/acl.h | 2 - src/plugins/acl/l2sess.c | 13 -- src/plugins/acl/l2sess.h | 1 - src/plugins/flowperpkt/flowperpkt.c | 32 +-- src/plugins/ila/ila.c | 14 +- src/plugins/ioam/encap/ip6_ioam_trace.c | 18 +- src/plugins/lb/lb.c | 15 +- src/plugins/sixrd/sixrd.c | 23 +-- src/plugins/snat/snat.c | 27 +-- src/plugins/snat/snat.h | 1 - src/vlib/unix/main.c | 8 + src/vlib/unix/plugin.c | 339 ++++++++++++++++++++++++++------ src/vlib/unix/plugin.h | 31 ++- src/vnet/plugin/plugin.h | 9 +- src/vpp/vnet/main.c | 15 +- 16 files changed, 367 insertions(+), 210 deletions(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index f4db2013..85c9113b 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -128,29 +129,11 @@ _(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \ _(MACIP_ACL_DUMP, macip_acl_dump) \ _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ - -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - acl_main_t *am = &acl_main; - clib_error_t *error = 0; - - am->vlib_main = vm; - am->vnet_main = h->vnet_main; - am->ethernet_main = h->ethernet_main; - - l2sess_vlib_plugin_register(vm, h, from_early_init); - - return error; -} - +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ static void vl_api_acl_plugin_get_version_t_handler (vl_api_acl_plugin_get_version_t * mp) diff --git a/src/plugins/acl/acl.h b/src/plugins/acl/acl.h index afc9b289..62046788 100644 --- a/src/plugins/acl/acl.h +++ b/src/plugins/acl/acl.h @@ -17,7 +17,6 @@ #include #include -#include #include @@ -139,7 +138,6 @@ typedef struct { /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; - ethernet_main_t * ethernet_main; } acl_main_t; extern acl_main_t acl_main; diff --git a/src/plugins/acl/l2sess.c b/src/plugins/acl/l2sess.c index cc9bde44..b0385be1 100644 --- a/src/plugins/acl/l2sess.c +++ b/src/plugins/acl/l2sess.c @@ -30,19 +30,6 @@ #include #include -void -l2sess_vlib_plugin_register (vlib_main_t * vm, void* hh, - int from_early_init) -{ - l2sess_main_t *sm = &l2sess_main; - vnet_plugin_handoff_t * h = hh; - memset (sm, 0, sizeof (*sm)); - - sm->vlib_main = vm; - sm->vnet_main = h->vnet_main; - sm->ethernet_main = h->ethernet_main; -} - void l2sess_init_next_features_input (vlib_main_t * vm, l2sess_main_t * sm) { diff --git a/src/plugins/acl/l2sess.h b/src/plugins/acl/l2sess.h index db899917..888b5301 100644 --- a/src/plugins/acl/l2sess.h +++ b/src/plugins/acl/l2sess.h @@ -132,7 +132,6 @@ foreach_l2sess_node /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; - ethernet_main_t * ethernet_main; /* Counter(s) */ u64 counter_attempted_delete_free_session; diff --git a/src/plugins/flowperpkt/flowperpkt.c b/src/plugins/flowperpkt/flowperpkt.c index cc351599..6b292eef 100644 --- a/src/plugins/flowperpkt/flowperpkt.c +++ b/src/plugins/flowperpkt/flowperpkt.c @@ -24,6 +24,7 @@ */ #include +#include #include #include @@ -479,30 +480,11 @@ static void *vl_api_flowperpkt_tx_interface_add_del_t_print #define foreach_flowperpkt_plugin_api_msg \ _(FLOWPERPKT_TX_INTERFACE_ADD_DEL, flowperpkt_tx_interface_add_del) -/** - * @brief plugin-api required function - * @param vm vlib_main_t * vlib main data structure pointer - * @param h vlib_plugin_handoff_t * handoff structure - * @param from_early_init int notused - * - * Notes: - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - flowperpkt_main_t *fm = &flowperpkt_main; - clib_error_t *error = 0; - - fm->vlib_main = vm; - fm->vnet_main = h->vnet_main; - - return error; -} +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ static clib_error_t * flowperpkt_tx_interface_add_del_feature_command_fn (vlib_main_t * vm, @@ -627,6 +609,8 @@ flowperpkt_init (vlib_main_t * vm) u32 num_threads; u8 *name; + fm->vnet_main = vnet_get_main (); + /* Construct the API name */ name = format (0, "flowperpkt_%08x%c", api_version, 0); diff --git a/src/plugins/ila/ila.c b/src/plugins/ila/ila.c index 336f4cf5..e0f3907f 100644 --- a/src/plugins/ila/ila.c +++ b/src/plugins/ila/ila.c @@ -18,6 +18,7 @@ #include #include #include +#include static ila_main_t ila_main; @@ -821,14 +822,11 @@ ila_interface (u32 sw_if_index, u8 disable) return 0; } -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - clib_error_t *error = 0; - - return error; -} +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ u8 *format_ila_dpo (u8 * s, va_list * va) { diff --git a/src/plugins/ioam/encap/ip6_ioam_trace.c b/src/plugins/ioam/encap/ip6_ioam_trace.c index 3a6758cd..a836dfe8 100644 --- a/src/plugins/ioam/encap/ip6_ioam_trace.c +++ b/src/plugins/ioam/encap/ip6_ioam_trace.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -349,18 +350,11 @@ VLIB_CLI_COMMAND (ip6_show_ioam_trace_cmd, static) = { }; /* *INDENT-ON* */ -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - return 0; -} +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ static clib_error_t * ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm) diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index 1d9b9870..dc3f5be1 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -15,6 +15,7 @@ #include #include +#include #include //GC runs at most once every so many seconds @@ -730,15 +731,11 @@ int lb_vip_del(u32 vip_index) return 0; } -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, - vnet_plugin_handoff_t * h, - int from_early_init) -{ - clib_error_t *error = 0; - return error; -} - +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ u8 *format_lb_dpo (u8 * s, va_list * va) { diff --git a/src/plugins/sixrd/sixrd.c b/src/plugins/sixrd/sixrd.c index 66e631a2..71fc181f 100644 --- a/src/plugins/sixrd/sixrd.c +++ b/src/plugins/sixrd/sixrd.c @@ -19,6 +19,7 @@ #include #include #include +#include /* * This code supports the following sixrd modes: @@ -340,27 +341,19 @@ VLIB_CLI_COMMAND(show_sixrd_stats_command, static) = { .function = show_sixrd_stats_command_fn, }; -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ + +static clib_error_t * sixrd_init (vlib_main_t * vm) { - clib_error_t * error = 0; sixrd_main_t *mm = &sixrd_main; mm->vnet_main = vnet_get_main(); mm->vlib_main = vm; - return error; -} - -static clib_error_t * sixrd_init (vlib_main_t * vm) -{ sixrd_dpo_module_init (); return (NULL); diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index 0fcd6ce8..750cc925 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -28,6 +28,7 @@ #include #include #include +#include snat_main_t snat_main; @@ -129,27 +130,11 @@ VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { .runs_before = VNET_FEATURES ("ip4-lookup"), }; - -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ - -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - snat_main_t * sm = &snat_main; - clib_error_t * error = 0; - - sm->vlib_main = vm; - sm->vnet_main = h->vnet_main; - sm->ethernet_main = h->ethernet_main; - - return error; -} +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, +}; +/* *INDENT-ON* */ /*$$$$$ move to an installed header file */ #if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */ diff --git a/src/plugins/snat/snat.h b/src/plugins/snat/snat.h index 32dc9f9e..39cbd3f8 100644 --- a/src/plugins/snat/snat.h +++ b/src/plugins/snat/snat.h @@ -233,7 +233,6 @@ typedef struct { vnet_main_t * vnet_main; ip4_main_t * ip4_main; ip_lookup_main_t * ip4_lookup_main; - ethernet_main_t * ethernet_main; api_main_t * api_main; } snat_main_t; diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c index 562778e0..a04d9f9c 100644 --- a/src/vlib/unix/main.c +++ b/src/vlib/unix/main.c @@ -503,6 +503,14 @@ vlib_unix_main (int argc, char *argv[]) vm->heap_base = clib_mem_get_heap (); ASSERT (vm->heap_base); + unformat_init_command_line (&input, (char **) vm->argv); + if ((e = vlib_plugin_config (vm, &input))) + { + clib_error_report (e); + return 1; + } + unformat_free (&input); + i = vlib_plugin_early_init (vm); if (i) return i; diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index 40399090..4aba95c8 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -16,29 +16,16 @@ */ #include +#include #include #include plugin_main_t vlib_plugin_main; -void -vlib_set_get_handoff_structure_cb (void *cb) -{ - plugin_main_t *pm = &vlib_plugin_main; - pm->handoff_structure_get_cb = cb; -} - -static void * -vnet_get_handoff_structure (void) -{ - void *(*fp) (void); - - fp = vlib_plugin_main.handoff_structure_get_cb; - if (fp == 0) - return 0; - else - return (*fp) (); -} +char *vlib_plugin_path __attribute__ ((weak)); +char *vlib_plugin_path = ""; +char *vlib_plugin_app_version __attribute__ ((weak)); +char *vlib_plugin_app_version = ""; void * vlib_get_plugin_symbol (char *plugin_name, char *symbol_name) @@ -54,13 +41,99 @@ vlib_get_plugin_symbol (char *plugin_name, char *symbol_name) return dlsym (pi->handle, symbol_name); } +static char * +str_array_to_vec (char *array, int len) +{ + char c, *r = 0; + int n = 0; + + do + { + c = array[n]; + vec_add1 (r, c); + } + while (c && ++n < len); + + if (c) + vec_add1 (r, 0); + + return r; +} + static int load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) { - void *handle, *register_handle; - clib_error_t *(*fp) (vlib_main_t *, void *, int); + void *handle; clib_error_t *error; - void *handoff_structure; + elf_main_t em = { 0 }; + elf_section_t *section; + u8 *data; + char *version_required; + vlib_plugin_registration_t *reg; + plugin_config_t *pc = 0; + uword *p; + + if (elf_read_file (&em, (char *) pi->filename)) + return -1; + + error = elf_get_section_by_name (&em, ".vlib_plugin_registration", + §ion); + if (error) + { + clib_warning ("Not a plugin: %s\n", (char *) pi->name); + return -1; + } + + data = elf_get_section_contents (&em, section->index, 1); + reg = (vlib_plugin_registration_t *) data; + + if (vec_len (data) != sizeof (*reg)) + { + clib_warning ("vlib_plugin_registration size mismatch in plugin %s\n", + (char *) pi->name); + goto error; + } + + p = hash_get_mem (pm->config_index_by_name, pi->name); + if (p) + { + pc = vec_elt_at_index (pm->configs, p[0]); + if (pc->is_disabled) + { + clib_warning ("Plugin disabled: %s", pi->name); + goto error; + } + if (reg->default_disabled && pc->is_enabled == 0) + { + clib_warning ("Plugin disabled: %s (default)", pi->name); + goto error; + } + } + else if (reg->default_disabled) + { + clib_warning ("Plugin disabled: %s (default)", pi->name); + goto error; + } + + version_required = str_array_to_vec ((char *) ®->version_required, + sizeof (reg->version_required)); + + if ((strlen (version_required) > 0) && + (strncmp (vlib_plugin_app_version, version_required, + strlen (version_required)))) + { + clib_warning ("Plugin %s version mismatch: %s != %s", + pi->name, vlib_plugin_app_version, reg->version_required); + if (!(pc && pc->skip_version_check == 1)) + { + vec_free (version_required); + goto error; + } + } + + vec_free (version_required); + vec_free (data); + elf_main_free (&em); handle = dlopen ((char *) pi->filename, RTLD_LAZY); @@ -77,35 +150,47 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) pi->handle = handle; + reg = dlsym (pi->handle, "vlib_plugin_registration"); - register_handle = dlsym (pi->handle, "vlib_plugin_register"); - if (register_handle == 0) + if (reg == 0) { - dlclose (handle); - clib_warning ("Plugin missing vlib_plugin_register: %s\n", - (char *) pi->name); - return 1; + /* This should never happen unless somebody chagnes registration macro */ + clib_warning ("Missing plugin registration in plugin '%s'", pi->name); + os_exit (1); } - fp = register_handle; - - handoff_structure = vnet_get_handoff_structure (); + pi->reg = reg; + pi->version = str_array_to_vec ((char *) ®->version, + sizeof (reg->version)); - if (handoff_structure == 0) - error = clib_error_return (0, "handoff structure callback returned 0"); - else - error = (*fp) (pm->vlib_main, handoff_structure, from_early_init); - - if (error) + if (reg && reg->early_init) { - clib_error_report (error); - dlclose (handle); - return 1; + clib_error_t *(*ei) (vlib_main_t *); + void *h; + + h = dlsym (pi->handle, reg->early_init); + if (h) + { + ei = h; + error = (*ei) (pm->vlib_main); + if (error) + { + clib_error_report (error); + os_exit (1); + } + } + else + clib_warning ("Plugin %s: early init function %s set but not found", + (char *) pi->name, reg->early_init); } clib_warning ("Loaded plugin: %s", pi->name); return 0; +error: + vec_free (data); + elf_main_free (&em); + return -1; } static u8 ** @@ -215,23 +300,16 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) return 0; } -char *vlib_plugin_path __attribute__ ((weak)); -char *vlib_plugin_path = ""; -char *vlib_plugin_name_filter __attribute__ ((weak)); -char *vlib_plugin_name_filter = 0; - int vlib_plugin_early_init (vlib_main_t * vm) { plugin_main_t *pm = &vlib_plugin_main; - pm->plugin_path = format (0, "%s%c", vlib_plugin_path, 0); + if (pm->plugin_path == 0) + pm->plugin_path = format (0, "%s%c", vlib_plugin_path, 0); clib_warning ("plugin path %s", pm->plugin_path); - if (vlib_plugin_name_filter) - pm->plugin_name_filter = format (0, "%s%c", vlib_plugin_name_filter, 0); - pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword)); pm->vlib_main = vm; @@ -245,19 +323,24 @@ vlib_plugins_show_cmd_fn (vlib_main_t * vm, plugin_main_t *pm = &vlib_plugin_main; u8 *s = 0; u8 *key = 0; - uword *value = 0; + uword value = 0; int index = 1; + plugin_info_t *pi; - s = format (s, " Plugin path is: %s\n", pm->plugin_path); - if (vlib_plugin_name_filter) - s = format (s, " Plugin filter: %s\n", vlib_plugin_name_filter); + s = format (s, " Plugin path is: %s\n\n", pm->plugin_path); + s = format (s, " %-41s%s\n", "Plugin", "Version"); - s = format (s, " Plugins loaded: \n"); + /* *INDENT-OFF* */ hash_foreach_mem (key, value, pm->plugin_by_name_hash, - { - if (key != 0) - s = format (s, " %d.%s\n", index, key); index++;} - ); + { + if (key != 0) + { + pi = vec_elt_at_index (pm->plugin_info, value); + s = format (s, "%3d. %-40s %s\n", index, key, pi->version); + index++; + } + }); + /* *INDENT-ON* */ vlib_cli_output (vm, "%v", s); vec_free (s); @@ -273,6 +356,148 @@ VLIB_CLI_COMMAND (plugins_show_cmd, static) = }; /* *INDENT-ON* */ +static clib_error_t * +config_one_plugin (vlib_main_t * vm, char *name, unformat_input_t * input) +{ + plugin_main_t *pm = &vlib_plugin_main; + plugin_config_t *pc; + clib_error_t *error = 0; + uword *p; + int is_enable = 0; + int is_disable = 0; + int skip_version_check = 0; + + if (pm->config_index_by_name == 0) + pm->config_index_by_name = hash_create_string (0, sizeof (uword)); + + p = hash_get_mem (pm->config_index_by_name, name); + + if (p) + { + error = clib_error_return (0, "plugin '%s' already configured", name); + goto done; + } + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + is_enable = 1; + else if (unformat (input, "disable")) + is_disable = 1; + else if (unformat (input, "skip-version-check")) + skip_version_check = 1; + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + goto done; + } + } + + if (is_enable && is_disable) + { + error = clib_error_return (0, "please specify either enable or disable" + " for plugin '%s'", name); + goto done; + } + + vec_add2 (pm->configs, pc, 1); + hash_set_mem (pm->config_index_by_name, name, pc - pm->configs); + pc->is_enabled = is_enable; + pc->is_disabled = is_disable; + pc->skip_version_check = skip_version_check; + pc->name = name; + +done: + return error; +} + +clib_error_t * +vlib_plugin_config (vlib_main_t * vm, unformat_input_t * input) +{ + plugin_main_t *pm = &vlib_plugin_main; + clib_error_t *error = 0; + unformat_input_t in; + + unformat_init (&in, 0, 0); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + u8 *s, *v; + if (unformat (input, "%s %v", &s, &v)) + { + if (strncmp ((const char *) s, "plugins", 8) == 0) + { + if (vec_len (in.buffer) > 0) + vec_add1 (in.buffer, ' '); + vec_add (in.buffer, v, vec_len (v)); + } + } + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + goto done; + } + + vec_free (v); + vec_free (s); + } +done: + input = ∈ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + unformat_input_t sub_input; + u8 *s = 0; + if (unformat (input, "path %s", &s)) + pm->plugin_path = s; + else if (unformat (input, "plugin %s %U", &s, + unformat_vlib_cli_sub_input, &sub_input)) + { + error = config_one_plugin (vm, (char *) s, &sub_input); + unformat_free (&sub_input); + if (error) + goto done2; + } + else + { + error = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + { + vec_free (s); + goto done2; + } + } + } + +done2: + unformat_free (&in); + return error; +} + +/* discard whole 'plugins' section, as it is already consumed prior to + plugin load */ +static clib_error_t * +plugins_config (vlib_main_t * vm, unformat_input_t * input) +{ + u8 *junk; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%s", &junk)) + { + vec_free (junk); + return 0; + } + else + return clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + } + return 0; +} + +VLIB_CONFIG_FUNCTION (plugins_config, "plugins"); + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlib/unix/plugin.h b/src/vlib/unix/plugin.h index 1c74cdd2..01fec356 100644 --- a/src/vlib/unix/plugin.h +++ b/src/vlib/unix/plugin.h @@ -56,7 +56,14 @@ * vlib_load_new_plugins(). */ - +/* *INDENT-OFF* */ +typedef CLIB_PACKED(struct { + u8 default_disabled; + const char version[32]; + const char version_required[32]; + const char *early_init; +}) vlib_plugin_registration_t; +/* *INDENT-ON* */ typedef struct { @@ -64,8 +71,20 @@ typedef struct u8 *filename; struct stat file_info; void *handle; + + /* plugin registration */ + vlib_plugin_registration_t *reg; + char *version; } plugin_info_t; +typedef struct +{ + char *name; + u8 is_disabled; + u8 is_enabled; + u8 skip_version_check; +} plugin_config_t; + typedef struct { /* loaded plugin info */ @@ -76,8 +95,9 @@ typedef struct u8 *plugin_path; u8 *plugin_name_filter; - /* handoff structure get callback */ - void *handoff_structure_get_cb; + /* plugin configs and hash by name */ + plugin_config_t *configs; + uword *config_index_by_name; /* usual */ vlib_main_t *vlib_main; @@ -85,10 +105,15 @@ typedef struct extern plugin_main_t vlib_plugin_main; +clib_error_t *vlib_plugin_config (vlib_main_t * vm, unformat_input_t * input); int vlib_plugin_early_init (vlib_main_t * vm); int vlib_load_new_plugins (plugin_main_t * pm, int from_early_init); void *vlib_get_plugin_symbol (char *plugin_name, char *symbol_name); +#define VLIB_PLUGIN_REGISTER() \ + vlib_plugin_registration_t vlib_plugin_registration \ + __attribute__((__section__(".vlib_plugin_registration"))) + #endif /* __included_plugin_h__ */ /* diff --git a/src/vnet/plugin/plugin.h b/src/vnet/plugin/plugin.h index a14a5932..6e1a3264 100644 --- a/src/vnet/plugin/plugin.h +++ b/src/vnet/plugin/plugin.h @@ -20,13 +20,6 @@ #include #include #include - -/* Pointers to Genuine Vnet data structures handed to plugin .dll's */ -typedef struct { - vnet_main_t * vnet_main; - ethernet_main_t * ethernet_main; -} vnet_plugin_handoff_t; - -void * vnet_get_handoff_structure (void); +#include #endif /* included_vnet_plugin_h */ diff --git a/src/vpp/vnet/main.c b/src/vpp/vnet/main.c index a252b846..4a96ca94 100644 --- a/src/vpp/vnet/main.c +++ b/src/vpp/vnet/main.c @@ -18,7 +18,7 @@ #include #include #include - +#include #include @@ -39,16 +39,7 @@ vpe_main_init (vlib_main_t * vm) * Load plugins from /usr/lib/vpp_plugins by default */ char *vlib_plugin_path = "/usr/lib/vpp_plugins"; - -void * -vnet_get_handoff_structure (void) -{ - static vnet_plugin_handoff_t _rv, *rv = &_rv; - - rv->vnet_main = vnet_get_main (); - rv->ethernet_main = ðernet_main; - return (void *) rv; -} +char *vlib_plugin_app_version = VPP_BUILD_VER; int main (int argc, char *argv[]) @@ -59,7 +50,6 @@ main (int argc, char *argv[]) uword main_heap_size = (1ULL << 30); u8 *sizep; u32 size; - void vlib_set_get_handoff_structure_cb (void *cb); #if __x86_64__ CLIB_UNUSED (const char *msg) @@ -206,7 +196,6 @@ defaulted: #if DPDK == 0 unix_physmem_init (vm, 0 /* fail_if_physical_memory_not_present */ ); #endif - vlib_set_get_handoff_structure_cb (&vnet_get_handoff_structure); return vlib_unix_main (argc, argv); } else -- cgit 1.2.3-korg From e4ad8cce6cf6e5d50b0ec101a4f5ab5d510ad374 Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Tue, 7 Feb 2017 11:22:33 +0100 Subject: VPP-630: Null pointer dereferences in vlib/unix/plugin.c Change-Id: Iafb071c684a43e21925e3a43019cd86372347898 Signed-off-by: Ole Troan --- src/vlib/unix/plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index 4aba95c8..15a2bcbb 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -163,7 +163,7 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) pi->version = str_array_to_vec ((char *) ®->version, sizeof (reg->version)); - if (reg && reg->early_init) + if (reg->early_init) { clib_error_t *(*ei) (vlib_main_t *); void *h; -- cgit 1.2.3-korg From a83bc30d064e70a4e20d2728e14e0b59667b17c5 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Sat, 25 Feb 2017 16:38:12 -0500 Subject: Load plugins in alphabetical order API traces contain absolute message numbers. Loading plugins in directory (vs. alphabetical) order makes trace replay fragile. Change-Id: I46b3a3b6a9843a383d42269fca0cf5a789486eaf Signed-off-by: Dave Barach --- src/vlib/unix/plugin.c | 64 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 9 deletions(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index 15a2bcbb..e9846e3b 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -220,6 +220,15 @@ split_plugin_path (plugin_main_t * pm) return rv; } +static int +plugin_name_sort_cmp (void *a1, void *a2) +{ + plugin_info_t *p1 = a1; + plugin_info_t *p2 = a2; + + return strcmp ((char *) p1->name, (char *) p2->name); +} + int vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) { @@ -229,6 +238,7 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) uword *p; plugin_info_t *pi; u8 **plugin_path; + u32 *load_fail_indices = 0; int i; plugin_path = split_plugin_path (pm); @@ -271,22 +281,15 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) goto ignore; plugin_name = format (0, "%s%c", entry->d_name, 0); + /* Have we seen this plugin already? */ p = hash_get_mem (pm->plugin_by_name_hash, plugin_name); if (p == 0) { + /* No, add it to the plugin vector */ vec_add2 (pm->plugin_info, pi, 1); pi->name = plugin_name; pi->filename = filename; pi->file_info = statb; - - if (load_one_plugin (pm, pi, from_early_init)) - { - vec_free (plugin_name); - vec_free (filename); - _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1; - memset (pi, 0, sizeof (*pi)); - continue; - } hash_set_mem (pm->plugin_by_name_hash, plugin_name, pi - pm->plugin_info); } @@ -297,6 +300,49 @@ vlib_load_new_plugins (plugin_main_t * pm, int from_early_init) vec_free (plugin_path[i]); } vec_free (plugin_path); + + + /* + * Sort the plugins by name. This is important. + * API traces contain absolute message numbers. + * Loading plugins in directory (vs. alphabetical) order + * makes trace replay incredibly fragile. + */ + vec_sort_with_function (pm->plugin_info, plugin_name_sort_cmp); + + /* + * Attempt to load the plugins + */ + for (i = 0; i < vec_len (pm->plugin_info); i++) + { + pi = vec_elt_at_index (pm->plugin_info, i); + + if (load_one_plugin (pm, pi, from_early_init)) + { + /* Make a note of any which fail to load */ + vec_add1 (load_fail_indices, i); + hash_unset_mem (pm->plugin_by_name_hash, pi->name); + vec_free (pi->name); + vec_free (pi->filename); + } + } + + /* Remove plugin info vector elements corresponding to load failures */ + if (vec_len (load_fail_indices) > 0) + { + for (i = vec_len (load_fail_indices) - 1; i >= 0; i--) + vec_delete (pm->plugin_info, 1, load_fail_indices[i]); + vec_free (load_fail_indices); + } + + /* Recreate the plugin name hash */ + for (i = 0; i < vec_len (pm->plugin_info); i++) + { + pi = vec_elt_at_index (pm->plugin_info, i); + hash_unset_mem (pm->plugin_by_name_hash, pi->name); + hash_set_mem (pm->plugin_by_name_hash, pi->name, pi - pm->plugin_info); + } + return 0; } -- cgit 1.2.3-korg From 1bfb0ddace3ebb9010275e4bdd847c8c493ff4b3 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Wed, 22 Mar 2017 11:08:39 +0100 Subject: vlib: add description field in plugin registration Change-Id: I88b322a5d602f3d6d3310e971479180a89430e0e Signed-off-by: Damjan Marion --- src/examples/sample-plugin/sample/sample.c | 1 + src/plugins/acl/acl.c | 1 + src/plugins/dpdk/main.c | 1 + src/plugins/flowperpkt/flowperpkt.c | 1 + src/plugins/ila/ila.c | 1 + src/plugins/ioam/encap/ip6_ioam_trace.c | 1 + src/plugins/ixge/ixge.c | 1 + src/plugins/lb/lb.c | 1 + src/plugins/sixrd/sixrd.c | 3 ++- src/plugins/snat/snat.c | 1 + src/vlib/unix/plugin.c | 14 +++++++++----- src/vlib/unix/plugin.h | 1 + 12 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/examples/sample-plugin/sample/sample.c b/src/examples/sample-plugin/sample/sample.c index 01852746..2f8ac4c9 100644 --- a/src/examples/sample-plugin/sample/sample.c +++ b/src/examples/sample-plugin/sample/sample.c @@ -61,6 +61,7 @@ _(SAMPLE_MACSWAP_ENABLE_DISABLE, sample_macswap_enable_disable) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = SAMPLE_PLUGIN_BUILD_VER, + .description = "Sample of VPP Plugin", }; /* *INDENT-ON* */ diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index 476fbc33..4a4dd434 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -80,6 +80,7 @@ _(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Access Control Lists", }; /* *INDENT-ON* */ diff --git a/src/plugins/dpdk/main.c b/src/plugins/dpdk/main.c index 8073a50a..7ee2a785 100644 --- a/src/plugins/dpdk/main.c +++ b/src/plugins/dpdk/main.c @@ -91,5 +91,6 @@ VLIB_INIT_FUNCTION (dpdk_main_init); /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Data Plane Development Kit (DPDK)", }; /* *INDENT-ON* */ diff --git a/src/plugins/flowperpkt/flowperpkt.c b/src/plugins/flowperpkt/flowperpkt.c index 587972f7..3e5fc8b0 100644 --- a/src/plugins/flowperpkt/flowperpkt.c +++ b/src/plugins/flowperpkt/flowperpkt.c @@ -448,6 +448,7 @@ _(FLOWPERPKT_TX_INTERFACE_ADD_DEL, flowperpkt_tx_interface_add_del) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Flow per Packet", }; /* *INDENT-ON* */ diff --git a/src/plugins/ila/ila.c b/src/plugins/ila/ila.c index 52c7ea55..edbf3017 100644 --- a/src/plugins/ila/ila.c +++ b/src/plugins/ila/ila.c @@ -825,6 +825,7 @@ ila_interface (u32 sw_if_index, u8 disable) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Identifier-locator addressing for IPv6", }; /* *INDENT-ON* */ diff --git a/src/plugins/ioam/encap/ip6_ioam_trace.c b/src/plugins/ioam/encap/ip6_ioam_trace.c index 57d3ec5d..299ee88f 100644 --- a/src/plugins/ioam/encap/ip6_ioam_trace.c +++ b/src/plugins/ioam/encap/ip6_ioam_trace.c @@ -411,6 +411,7 @@ VLIB_CLI_COMMAND (ip6_show_ioam_trace_cmd, static) = { /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Inbound OAM", }; /* *INDENT-ON* */ diff --git a/src/plugins/ixge/ixge.c b/src/plugins/ixge/ixge.c index 4eebc457..f3c5cc09 100644 --- a/src/plugins/ixge/ixge.c +++ b/src/plugins/ixge/ixge.c @@ -2935,6 +2935,7 @@ ixge_set_next_node (ixge_rx_next_t next, char *name) VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, .default_disabled = 1, + .description = "Intel 82599 Family Native Driver (experimental)", }; /* *INDENT-ON* */ diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index dc3f5be1..add81236 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -734,6 +734,7 @@ int lb_vip_del(u32 vip_index) /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Load Balancer", }; /* *INDENT-ON* */ diff --git a/src/plugins/sixrd/sixrd.c b/src/plugins/sixrd/sixrd.c index 67a9a3ad..98387525 100644 --- a/src/plugins/sixrd/sixrd.c +++ b/src/plugins/sixrd/sixrd.c @@ -356,8 +356,9 @@ VLIB_CLI_COMMAND(show_sixrd_stats_command, static) = { }; /* *INDENT-OFF* */ -VLIB_PLUGIN_REGISTER () = { +VLIB_PLUGIN_REGISTER () ={ .version = VPP_BUILD_VER, + .description = "IPv6 Rapid Deployment on IPv4 Infrastructure (RFC5969)", }; /* *INDENT-ON* */ diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index d42303f6..70b6a6e2 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -107,6 +107,7 @@ VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Network Address Translation", }; /* *INDENT-ON* */ diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index e9846e3b..9b341cc8 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -105,13 +105,13 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) } if (reg->default_disabled && pc->is_enabled == 0) { - clib_warning ("Plugin disabled: %s (default)", pi->name); + clib_warning ("Plugin disabled (default): %s", pi->name); goto error; } } else if (reg->default_disabled) { - clib_warning ("Plugin disabled: %s (default)", pi->name); + clib_warning ("Plugin disabled (default): %s", pi->name); goto error; } @@ -184,7 +184,10 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) (char *) pi->name, reg->early_init); } - clib_warning ("Loaded plugin: %s", pi->name); + if (reg->description) + clib_warning ("Loaded plugin: %s (%s)", pi->name, reg->description); + else + clib_warning ("Loaded plugin: %s", pi->name); return 0; error: @@ -374,7 +377,7 @@ vlib_plugins_show_cmd_fn (vlib_main_t * vm, plugin_info_t *pi; s = format (s, " Plugin path is: %s\n\n", pm->plugin_path); - s = format (s, " %-41s%s\n", "Plugin", "Version"); + s = format (s, " %-41s%-33s%s\n", "Plugin", "Version", "Description"); /* *INDENT-OFF* */ hash_foreach_mem (key, value, pm->plugin_by_name_hash, @@ -382,7 +385,8 @@ vlib_plugins_show_cmd_fn (vlib_main_t * vm, if (key != 0) { pi = vec_elt_at_index (pm->plugin_info, value); - s = format (s, "%3d. %-40s %s\n", index, key, pi->version); + s = format (s, "%3d. %-40s %-32s %s\n", index, key, pi->version, + pi->reg->description ? pi->reg->description : ""); index++; } }); diff --git a/src/vlib/unix/plugin.h b/src/vlib/unix/plugin.h index 01fec356..d9801ec4 100644 --- a/src/vlib/unix/plugin.h +++ b/src/vlib/unix/plugin.h @@ -62,6 +62,7 @@ typedef CLIB_PACKED(struct { const char version[32]; const char version_required[32]; const char *early_init; + const char *description; }) vlib_plugin_registration_t; /* *INDENT-ON* */ -- cgit 1.2.3-korg From c9fc77c510e042cf9379b427b63dd3f17a23a584 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Tue, 25 Apr 2017 21:07:52 +0200 Subject: Exit if plugin load attempt fail This happens mainly if plugin contains unresolved symbol. Such situation typically leads on crash a bit later so it is better to exit immediatelly and display meaningful error message. Change-Id: I4abd9a9089a4863400bf609e8d3fd7cebab92913 Signed-off-by: Damjan Marion --- src/vlib/unix/plugin.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/vlib/unix/plugin.c') diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c index 9b341cc8..c2741aaa 100644 --- a/src/vlib/unix/plugin.c +++ b/src/vlib/unix/plugin.c @@ -137,15 +137,11 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init) handle = dlopen ((char *) pi->filename, RTLD_LAZY); - /* - * Note: this can happen if the plugin has an undefined symbol reference, - * so print a warning. Otherwise, the poor slob won't know what happened. - * Ask me how I know that... - */ if (handle == 0) { clib_warning ("%s", dlerror ()); - return -1; + clib_warning ("Failed to load plugin '%s'", pi->name); + os_exit (1); } pi->handle = handle; -- cgit 1.2.3-korg