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/vlibapi/api_helper_macros.h | 243 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 src/vlibapi/api_helper_macros.h (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h new file mode 100644 index 00000000..16f34cfc --- /dev/null +++ b/src/vlibapi/api_helper_macros.h @@ -0,0 +1,243 @@ +/* + *------------------------------------------------------------------ + * api_helper_macros.h - message handler helper macros + * + * 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 __api_helper_macros_h__ +#define __api_helper_macros_h__ + +#define f64_endian(a) +#define f64_print(a,b) + +#define REPLY_MACRO(t) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +#define REPLY_MACRO2(t, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +#define REPLY_MACRO3(t, n, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +#define REPLY_MACRO4(t, n, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + u8 is_error = 0; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc_or_null (sizeof (*rmp) + n); \ + if (!rmp) \ + { \ + /* if there isn't enough memory, try to allocate */ \ + /* some at least for returning an error */ \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + if (!rmp) \ + return; \ + \ + memset (rmp, 0, sizeof (*rmp)); \ + rv = VNET_API_ERROR_TABLE_TOO_BIG; \ + is_error = 1; \ + } \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + if (!is_error) \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +/* "trust, but verify" */ + +#define VALIDATE_SW_IF_INDEX(mp) \ + do { u32 __sw_if_index = ntohl(mp->sw_if_index); \ + vnet_main_t *__vnm = vnet_get_main(); \ + if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ + __sw_if_index)) { \ + rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ + goto bad_sw_if_index; \ + } \ +} while(0); + +#define BAD_SW_IF_INDEX_LABEL \ +do { \ +bad_sw_if_index: \ + ; \ +} while (0); + +#define VALIDATE_RX_SW_IF_INDEX(mp) \ + do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \ + vnet_main_t *__vnm = vnet_get_main(); \ + if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ + __rx_sw_if_index)) { \ + rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ + goto bad_rx_sw_if_index; \ + } \ +} while(0); + +#define BAD_RX_SW_IF_INDEX_LABEL \ +do { \ +bad_rx_sw_if_index: \ + ; \ +} while (0); + +#define VALIDATE_TX_SW_IF_INDEX(mp) \ + do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \ + vnet_main_t *__vnm = vnet_get_main(); \ + if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ + __tx_sw_if_index)) { \ + rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ + goto bad_tx_sw_if_index; \ + } \ +} while(0); + +#define BAD_TX_SW_IF_INDEX_LABEL \ +do { \ +bad_tx_sw_if_index: \ + ; \ +} while (0); + +#define pub_sub_handler(lca,UCA) \ +static void vl_api_want_##lca##_t_handler ( \ + vl_api_want_##lca##_t *mp) \ +{ \ + vpe_api_main_t *vam = &vpe_api_main; \ + vpe_client_registration_t *rp; \ + vl_api_want_##lca##_reply_t *rmp; \ + uword *p; \ + i32 rv = 0; \ + \ + p = hash_get (vam->lca##_registration_hash, mp->client_index); \ + if (p) { \ + if (mp->enable_disable) { \ + clib_warning ("pid %d: already enabled...", mp->pid); \ + rv = VNET_API_ERROR_INVALID_REGISTRATION; \ + goto reply; \ + } else { \ + rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \ + pool_put (vam->lca##_registrations, rp); \ + hash_unset (vam->lca##_registration_hash, \ + mp->client_index); \ + goto reply; \ + } \ + } \ + if (mp->enable_disable == 0) { \ + clib_warning ("pid %d: already disabled...", mp->pid); \ + rv = VNET_API_ERROR_INVALID_REGISTRATION; \ + goto reply; \ + } \ + pool_get (vam->lca##_registrations, rp); \ + rp->client_index = mp->client_index; \ + rp->client_pid = mp->pid; \ + hash_set (vam->lca##_registration_hash, rp->client_index, \ + rp - vam->lca##_registrations); \ + \ +reply: \ + REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \ +} + +#define foreach_registration_hash \ +_(interface_events) \ +_(to_netconf_server) \ +_(from_netconf_server) \ +_(to_netconf_client) \ +_(from_netconf_client) \ +_(oam_events) \ +_(bfd_events) + +/* WARNING: replicated in vpp/stats.h */ +typedef struct +{ + u32 client_index; /* in memclnt registration pool */ + u32 client_pid; +} vpe_client_registration_t; + +struct _vl_api_ip4_arp_event; +struct _vl_api_ip6_nd_event; + +typedef struct +{ +#define _(a) uword *a##_registration_hash; \ + vpe_client_registration_t * a##_registrations; + foreach_registration_hash +#undef _ + /* notifications happen really early in the game */ + u8 link_state_process_up; + + /* ip4 arp event registration pool */ + struct _vl_api_ip4_arp_event *arp_events; + + /* ip6 nd event registration pool */ + struct _vl_api_ip6_nd_event *nd_events; + + /* convenience */ + vlib_main_t *vlib_main; + vnet_main_t *vnet_main; +} vpe_api_main_t; + +extern vpe_api_main_t vpe_api_main; + +#endif /* __api_helper_macros_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- 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/vlibapi/api_helper_macros.h') 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 1c82cd4f491ff83127fbacfb6b09b9492eff1b62 Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Tue, 14 Mar 2017 14:39:51 +0200 Subject: API:support hidden sw interfaces validate interfaces - added check for hidden interfaces interface dump - dont send hidden interfaces set_unnumbered - test for hidden vl_api_create_vlan_subif_t_handler, vl_api_create_subif_t_handler - fixed potential memory leak some other minor refactors to make code clearer and shorter Change-Id: Icce6b724336b7d1536fbd07a74bf7abe4916d2c0 Signed-off-by: Eyal Bari --- src/vlibapi/api_helper_macros.h | 18 ++++++------ src/vnet/interface_api.c | 65 +++++++++++++++++------------------------ src/vpp/api/api.c | 63 +++++++++++++++------------------------ 3 files changed, 60 insertions(+), 86 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 7f94e446..4e281342 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -103,11 +103,15 @@ do { \ /* "trust, but verify" */ +static inline uword +vnet_sw_if_index_is_api_valid (u32 sw_if_index) +{ + return vnet_sw_interface_is_api_valid (vnet_get_main (), sw_if_index); +} + #define VALIDATE_SW_IF_INDEX(mp) \ do { u32 __sw_if_index = ntohl(mp->sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __sw_if_index)) { \ + if (!vnet_sw_if_index_is_api_valid(__sw_if_index)) { \ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ goto bad_sw_if_index; \ } \ @@ -121,9 +125,7 @@ bad_sw_if_index: \ #define VALIDATE_RX_SW_IF_INDEX(mp) \ do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __rx_sw_if_index)) { \ + if (!vnet_sw_if_index_is_api_valid(__rx_sw_if_index)) { \ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ goto bad_rx_sw_if_index; \ } \ @@ -137,9 +139,7 @@ bad_rx_sw_if_index: \ #define VALIDATE_TX_SW_IF_INDEX(mp) \ do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __tx_sw_if_index)) { \ + if (!vnet_sw_if_index_is_api_valid(__tx_sw_if_index)) { \ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ goto bad_tx_sw_if_index; \ } \ diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 2b6ff0c5..28b09b55 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -133,14 +133,10 @@ send_sw_interface_details (vpe_api_main_t * am, vnet_sw_interface_t * swif, u8 * interface_name, u32 context) { - vl_api_sw_interface_details_t *mp; - vnet_main_t *vnm = vnet_get_main (); - vnet_hw_interface_t *hi; - u8 *tag; + vnet_hw_interface_t *hi = + vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index); - hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index); - - mp = vl_msg_api_alloc (sizeof (*mp)); + vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_DETAILS); mp->sw_if_index = ntohl (swif->sw_if_index); @@ -224,7 +220,7 @@ send_sw_interface_details (vpe_api_main_t * am, mp->i_sid = i_sid; } - tag = vnet_get_sw_interface_tag (vnm, swif->sw_if_index); + u8 *tag = vnet_get_sw_interface_tag (vnet_get_main (), swif->sw_if_index); if (tag) strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); @@ -237,39 +233,38 @@ vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp) vpe_api_main_t *am = &vpe_api_main; vnet_sw_interface_t *swif; vnet_interface_main_t *im = &am->vnet_main->interface_main; - u8 *filter_string = 0, *name_string = 0; - unix_shared_memory_queue_t *q; - char *strcasestr (char *, char *); /* lnx hdr file botch */ - - q = vl_api_client_index_to_input_queue (mp->client_index); + unix_shared_memory_queue_t *q = + vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; + u8 *filter = 0, *name = 0; if (mp->name_filter_valid) { mp->name_filter[ARRAY_LEN (mp->name_filter) - 1] = 0; - filter_string = format (0, "%s%c", mp->name_filter, 0); + filter = format (0, "%s%c", mp->name_filter, 0); } + char *strcasestr (char *, char *); /* lnx hdr file botch */ /* *INDENT-OFF* */ pool_foreach (swif, im->sw_interfaces, ({ - name_string = format (name_string, "%U%c", - format_vnet_sw_interface_name, - am->vnet_main, swif, 0); + if (!vnet_swif_is_api_visible (swif)) + continue; + vec_reset_length(name); + name = format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main, + swif, 0); - if (mp->name_filter_valid == 0 || - strcasestr((char *) name_string, (char *) filter_string)) { + if (filter && !strcasestr((char *) name, (char *) filter)) + continue; - send_sw_interface_details (am, q, swif, name_string, mp->context); - } - _vec_len (name_string) = 0; + send_sw_interface_details (am, q, swif, name, mp->context); })); /* *INDENT-ON* */ - vec_free (name_string); - vec_free (filter_string); + vec_free (name); + vec_free (filter); } static void @@ -435,49 +430,43 @@ static void vl_api_sw_interface_set_unnumbered_t_handler { vl_api_sw_interface_set_unnumbered_reply_t *rmp; int rv = 0; - vnet_sw_interface_t *si; vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index, unnumbered_sw_if_index; - - sw_if_index = ntohl (mp->sw_if_index); - unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index); + u32 sw_if_index = ntohl (mp->sw_if_index); + u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index); /* * The API message field names are backwards from * the underlying data structure names. * It's not worth changing them now. */ - if (pool_is_free_index (vnm->interface_main.sw_interfaces, - unnumbered_sw_if_index)) + if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index)) { rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; goto done; } /* Only check the "use loop0" field when setting the binding */ - if (mp->is_add && - pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) + if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index)) { rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2; goto done; } - si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index); + vnet_sw_interface_t *si = + vnet_get_sw_interface (vnm, unnumbered_sw_if_index); if (mp->is_add) { si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED; si->unnumbered_sw_if_index = sw_if_index; - ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 1); - ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 1); } else { si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED); si->unnumbered_sw_if_index = (u32) ~ 0; - ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 0); - ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 0); } + ip4_sw_interface_enable_disable (unnumbered_sw_if_index, mp->is_add); + ip6_sw_interface_enable_disable (unnumbered_sw_if_index, mp->is_add); done: REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY); diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index 673ffe56..d8301fa6 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -477,7 +477,6 @@ vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) uword *p; vnet_interface_main_t *im = &vnm->interface_main; u64 sup_and_sub_key; - u64 *kp; unix_shared_memory_queue_t *q; clib_error_t *error; @@ -507,9 +506,6 @@ vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) goto out; } - kp = clib_mem_alloc (sizeof (*kp)); - *kp = sup_and_sub_key; - memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; template.sup_sw_if_index = hi->sw_if_index; @@ -526,6 +522,10 @@ vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) rv = VNET_API_ERROR_INVALID_REGISTRATION; goto out; } + + u64 *kp = clib_mem_alloc (sizeof (*kp)); + *kp = sup_and_sub_key; + hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index); hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index); @@ -537,10 +537,10 @@ out: return; rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY); + rmp->_vl_msg_id = htons (VL_API_CREATE_VLAN_SUBIF_REPLY); rmp->context = mp->context; - rmp->retval = ntohl (rv); - rmp->sw_if_index = ntohl (sw_if_index); + rmp->retval = htonl (rv); + rmp->sw_if_index = htonl (sw_if_index); vl_msg_api_send_shmem (q, (u8 *) & rmp); } @@ -558,7 +558,6 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) uword *p; vnet_interface_main_t *im = &vnm->interface_main; u64 sup_and_sub_key; - u64 *kp; clib_error_t *error; VALIDATE_SW_IF_INDEX (mp); @@ -587,9 +586,6 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) goto out; } - kp = clib_mem_alloc (sizeof (*kp)); - *kp = sup_and_sub_key; - memset (&template, 0, sizeof (template)); template.type = VNET_SW_INTERFACE_TYPE_SUB; template.sup_sw_if_index = sw_if_index; @@ -613,6 +609,9 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) goto out; } + u64 *kp = clib_mem_alloc (sizeof (*kp)); + *kp = sup_and_sub_key; + hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index); hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index); @@ -669,20 +668,11 @@ static void int rv = 0; vnet_main_t *vnm = vnet_get_main (); vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp; - vnet_sw_interface_t *si; - u32 sw_if_index; VALIDATE_SW_IF_INDEX (mp); - sw_if_index = ntohl (mp->sw_if_index); - - if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) - { - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; - goto out; - } - - si = vnet_get_sw_interface (vnm, sw_if_index); + vnet_sw_interface_t *si = + vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index)); ASSERT (si); @@ -1223,13 +1213,12 @@ static void vl_api_classify_set_interface_ip_table_t_handler vlib_main_t *vm = vlib_get_main (); vl_api_classify_set_interface_ip_table_reply_t *rmp; int rv; - u32 table_index, sw_if_index; - - table_index = ntohl (mp->table_index); - sw_if_index = ntohl (mp->sw_if_index); VALIDATE_SW_IF_INDEX (mp); + u32 table_index = ntohl (mp->table_index); + u32 sw_if_index = ntohl (mp->sw_if_index); + if (mp->is_ipv6) rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index); else @@ -1658,15 +1647,14 @@ static void vl_api_input_acl_set_interface_t_handler vlib_main_t *vm = vlib_get_main (); vl_api_input_acl_set_interface_reply_t *rmp; int rv; - u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index; - - ip4_table_index = ntohl (mp->ip4_table_index); - ip6_table_index = ntohl (mp->ip6_table_index); - l2_table_index = ntohl (mp->l2_table_index); - sw_if_index = ntohl (mp->sw_if_index); VALIDATE_SW_IF_INDEX (mp); + u32 ip4_table_index = ntohl (mp->ip4_table_index); + u32 ip6_table_index = ntohl (mp->ip6_table_index); + u32 l2_table_index = ntohl (mp->l2_table_index); + u32 sw_if_index = ntohl (mp->sw_if_index); + rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index, ip6_table_index, l2_table_index, mp->is_add); @@ -2013,25 +2001,22 @@ vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp) { vl_api_feature_enable_disable_reply_t *rmp; int rv = 0; - u8 *arc_name, *feature_name; VALIDATE_SW_IF_INDEX (mp); - arc_name = format (0, "%s%c", mp->arc_name, 0); - feature_name = format (0, "%s%c", mp->feature_name, 0); + u8 *arc_name = format (0, "%s%c", mp->arc_name, 0); + u8 *feature_name = format (0, "%s%c", mp->feature_name, 0); - vnet_feature_registration_t *reg; - reg = + vnet_feature_registration_t *reg = vnet_get_feature_reg ((const char *) arc_name, (const char *) feature_name); if (reg == 0) rv = VNET_API_ERROR_INVALID_VALUE; else { - u32 sw_if_index; + u32 sw_if_index = ntohl (mp->sw_if_index); clib_error_t *error = 0; - sw_if_index = ntohl (mp->sw_if_index); if (reg->enable_disable_cb) error = reg->enable_disable_cb (sw_if_index, mp->enable); if (!error) -- cgit 1.2.3-korg From 0856b97b494ea54f3daa6e0c31a2f882bf23a551 Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Wed, 15 Mar 2017 14:54:19 +0200 Subject: API: define optional base_id for REPLY_MACRO's this enables sharing the api_helper_macros.h implementation Change-Id: Ie3fc89f3b4b5a47fcfd4b5776db90e249c55dbc3 Signed-off-by: Eyal Bari --- src/plugins/snat/snat.c | 105 ++-------------------------------------- src/vlibapi/api_helper_macros.h | 12 +++-- 2 files changed, 11 insertions(+), 106 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index b9da67f5..57274bbe 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,9 @@ snat_main_t snat_main; #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define REPLY_MSG_ID_BASE (sm->msg_id_base) +#include + /* Get the API version number */ #define vl_api_version(n,v) static u32 api_version=(v); #include @@ -60,45 +62,6 @@ snat_main_t snat_main; vec_free (s); \ return handle; -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -#define REPLY_MACRO2(t, body) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - - /* Hook up input features */ VNET_FEATURE_INIT (ip4_snat_in2out, static) = { .arc_name = "ip4-unicast", @@ -147,68 +110,6 @@ VLIB_PLUGIN_REGISTER () = { }; /* *INDENT-ON* */ -/*$$$$$ move to an installed header file */ -#if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */ - -#define VALIDATE_SW_IF_INDEX(mp) \ - do { u32 __sw_if_index = ntohl(mp->sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __sw_if_index)) { \ - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ - goto bad_sw_if_index; \ - } \ -} while(0); - -#define BAD_SW_IF_INDEX_LABEL \ -do { \ -bad_sw_if_index: \ - ; \ -} while (0); - -#define VALIDATE_RX_SW_IF_INDEX(mp) \ - do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __rx_sw_if_index)) { \ - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ - goto bad_rx_sw_if_index; \ - } \ -} while(0); - -#define BAD_RX_SW_IF_INDEX_LABEL \ -do { \ -bad_rx_sw_if_index: \ - ; \ -} while (0); - -#define VALIDATE_TX_SW_IF_INDEX(mp) \ - do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __tx_sw_if_index)) { \ - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ - goto bad_tx_sw_if_index; \ - } \ -} while(0); - -#define BAD_TX_SW_IF_INDEX_LABEL \ -do { \ -bad_tx_sw_if_index: \ - ; \ -} while (0); - -#else - -#define VALIDATE_SW_IF_INDEX(mp) -#define BAD_SW_IF_INDEX_LABEL -#define VALIDATE_RX_SW_IF_INDEX(mp) -#define BAD_RX_SW_IF_INDEX_LABEL -#define VALIDATE_TX_SW_IF_INDEX(mp) -#define BAD_TX_SW_IF_INDEX_LABEL - -#endif /* CLIB_DEBUG > 0 */ - /** * @brief Add/del NAT address to FIB. * diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 4e281342..aacea7c1 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -23,6 +23,10 @@ #define f64_endian(a) #define f64_print(a,b) +#ifndef REPLY_MSG_ID_BASE +#define REPLY_MSG_ID_BASE 0 +#endif + #define REPLY_MACRO(t) \ do { \ unix_shared_memory_queue_t * q; \ @@ -32,7 +36,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)); \ + rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ \ @@ -48,7 +52,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)); \ + rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ @@ -64,7 +68,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \ - rmp->_vl_msg_id = ntohs((t)); \ + rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ @@ -93,7 +97,7 @@ do { \ rv = VNET_API_ERROR_TABLE_TOO_BIG; \ is_error = 1; \ } \ - rmp->_vl_msg_id = ntohs((t)); \ + rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ if (!is_error) \ -- cgit 1.2.3-korg From b614d08368cc0b04e01c5222d4c11a88845394e5 Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Thu, 16 Mar 2017 10:02:57 +0200 Subject: API:replaced all REPLY_MACRO's with api_helper_macros.h Change-Id: I08ab1fd0abdd1db4aff11a38c9c0134b01368e11 Signed-off-by: Eyal Bari --- src/examples/sample-plugin/sample/sample.c | 25 +------ src/plugins/acl/acl.c | 83 ++++------------------ src/plugins/flowperpkt/flowperpkt.c | 41 +---------- .../ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c | 27 +------ src/plugins/ioam/export/ioam_export.c | 26 +------ src/plugins/ioam/ip6/ioam_cache.c | 26 +------ src/plugins/ioam/lib-pot/pot_api.c | 41 +---------- src/plugins/ioam/udp-ping/udp_ping_api.c | 41 +---------- src/plugins/lb/api.c | 27 ++----- src/plugins/snat/snat.c | 2 +- src/vlibapi/api_helper_macros.h | 8 +-- 11 files changed, 39 insertions(+), 308 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/examples/sample-plugin/sample/sample.c b/src/examples/sample-plugin/sample/sample.c index 7588dbc0..01852746 100644 --- a/src/examples/sample-plugin/sample/sample.c +++ b/src/examples/sample-plugin/sample/sample.c @@ -50,29 +50,8 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include /* List of message types that this plugin understands */ diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index b6af7380..0d06531d 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -57,61 +57,8 @@ acl_main_t acl_main; -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -#define REPLY_MACRO2(t, body) \ -do { \ - unix_shared_memory_queue_t * q; \ - rv = vl_msg_api_pd_handler (mp, rv); \ - q = vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+am->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -#define REPLY_MACRO3(t, n, body) \ -do { \ - unix_shared_memory_queue_t * q; \ - rv = vl_msg_api_pd_handler (mp, rv); \ - q = vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \ - rmp->_vl_msg_id = ntohs((t)+am->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - +#define REPLY_MSG_ID_BASE am->msg_id_base +#include /* List of message types that this plugin understands */ @@ -1409,7 +1356,7 @@ vl_api_acl_add_replace_t_handler (vl_api_acl_add_replace_t * mp) static void vl_api_acl_del_t_handler (vl_api_acl_del_t * mp) { - acl_main_t *sm = &acl_main; + acl_main_t *am = &acl_main; vl_api_acl_del_reply_t *rmp; int rv; @@ -1421,8 +1368,8 @@ vl_api_acl_del_t_handler (vl_api_acl_del_t * mp) static void vl_api_acl_interface_add_del_t_handler (vl_api_acl_interface_add_del_t * mp) { - acl_main_t *sm = &acl_main; - vnet_interface_main_t *im = &sm->vnet_main->interface_main; + acl_main_t *am = &acl_main; + vnet_interface_main_t *im = &am->vnet_main->interface_main; u32 sw_if_index = ntohl (mp->sw_if_index); vl_api_acl_interface_add_del_reply_t *rmp; int rv = -1; @@ -1441,11 +1388,11 @@ static void vl_api_acl_interface_set_acl_list_t_handler (vl_api_acl_interface_set_acl_list_t * mp) { - acl_main_t *sm = &acl_main; + acl_main_t *am = &acl_main; vl_api_acl_interface_set_acl_list_reply_t *rmp; int rv = 0; int i; - vnet_interface_main_t *im = &sm->vnet_main->interface_main; + vnet_interface_main_t *im = &am->vnet_main->interface_main; u32 sw_if_index = ntohl (mp->sw_if_index); if (pool_is_free_index(im->sw_interfaces, sw_if_index)) @@ -1667,7 +1614,7 @@ vl_api_macip_acl_add_t_handler (vl_api_macip_acl_add_t * mp) static void vl_api_macip_acl_del_t_handler (vl_api_macip_acl_del_t * mp) { - acl_main_t *sm = &acl_main; + acl_main_t *am = &acl_main; vl_api_macip_acl_del_reply_t *rmp; int rv; @@ -1680,10 +1627,10 @@ static void vl_api_macip_acl_interface_add_del_t_handler (vl_api_macip_acl_interface_add_del_t * mp) { - acl_main_t *sm = &acl_main; + acl_main_t *am = &acl_main; vl_api_macip_acl_interface_add_del_reply_t *rmp; int rv = -1; - vnet_interface_main_t *im = &sm->vnet_main->interface_main; + vnet_interface_main_t *im = &am->vnet_main->interface_main; u32 sw_if_index = ntohl (mp->sw_if_index); if (pool_is_free_index(im->sw_interfaces, sw_if_index)) @@ -1819,9 +1766,9 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t * static clib_error_t * acl_plugin_api_hookup (vlib_main_t * vm) { - acl_main_t *sm = &acl_main; + acl_main_t *am = &acl_main; #define _(N,n) \ - vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ + vl_msg_api_set_handlers((VL_API_##N + am->msg_id_base), \ #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ @@ -1839,10 +1786,10 @@ acl_plugin_api_hookup (vlib_main_t * vm) #undef vl_msg_name_crc_list static void -setup_message_id_table (acl_main_t * sm, api_main_t * am) +setup_message_id_table (acl_main_t * am, api_main_t * apim) { #define _(id,n,crc) \ - vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + sm->msg_id_base); + vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + am->msg_id_base); foreach_vl_msg_name_crc_acl; #undef _ } @@ -1852,11 +1799,11 @@ register_match_action_nexts (u32 next_in_ip4, u32 next_in_ip6, u32 next_out_ip4, u32 next_out_ip6) { acl_main_t *am = &acl_main; - u32 act = am->n_match_actions; if (am->n_match_actions == 255) { return ~0; } + u32 act = am->n_match_actions; am->n_match_actions++; am->acl_in_ip4_match_next[act] = next_in_ip4; am->acl_in_ip6_match_next[act] = next_in_ip6; diff --git a/src/plugins/flowperpkt/flowperpkt.c b/src/plugins/flowperpkt/flowperpkt.c index 6b292eef..587972f7 100644 --- a/src/plugins/flowperpkt/flowperpkt.c +++ b/src/plugins/flowperpkt/flowperpkt.c @@ -58,6 +58,9 @@ flowperpkt_main_t flowperpkt_main; #include #undef vl_api_version +#define REPLY_MSG_ID_BASE fm->msg_id_base +#include + /* Define the per-interface configurable features */ /* *INDENT-OFF* */ VNET_FEATURE_INIT (flow_perpacket_ipv4, static) = @@ -75,28 +78,6 @@ VNET_FEATURE_INIT (flow_perpacket_l2, static) = }; /* *INDENT-ON* */ -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+fm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - /* Macro to finish up custom dump fns */ #define FINISH \ vec_add1 (s, 0); \ @@ -104,22 +85,6 @@ do { \ vec_free (s); \ return handle; -#define VALIDATE_SW_IF_INDEX(mp) \ - do { u32 __sw_if_index = ntohl(mp->sw_if_index); \ - vnet_main_t *__vnm = vnet_get_main(); \ - if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \ - __sw_if_index)) { \ - rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \ - goto bad_sw_if_index; \ - } \ -} while(0); - -#define BAD_SW_IF_INDEX_LABEL \ -do { \ -bad_sw_if_index: \ - ; \ -} while (0); - /** * @brief Create an IPFIX template packet rewrite string * @param frm flow_report_main_t * diff --git a/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c b/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c index f05b5303..b703b8d0 100644 --- a/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c +++ b/src/plugins/ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c @@ -53,33 +53,10 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include /* List of message types that this plugin understands */ - - #define foreach_vxlan_gpe_ioam_export_plugin_api_msg \ _(VXLAN_GPE_IOAM_EXPORT_ENABLE_DISABLE, vxlan_gpe_ioam_export_enable_disable) diff --git a/src/plugins/ioam/export/ioam_export.c b/src/plugins/ioam/export/ioam_export.c index eeeb9738..46ac3d4a 100644 --- a/src/plugins/ioam/export/ioam_export.c +++ b/src/plugins/ioam/export/ioam_export.c @@ -52,32 +52,10 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include /* List of message types that this plugin understands */ - #define foreach_ioam_export_plugin_api_msg \ _(IOAM_EXPORT_IP6_ENABLE_DISABLE, ioam_export_ip6_enable_disable) diff --git a/src/plugins/ioam/ip6/ioam_cache.c b/src/plugins/ioam/ip6/ioam_cache.c index 9e90ff9a..a4079e84 100644 --- a/src/plugins/ioam/ip6/ioam_cache.c +++ b/src/plugins/ioam/ip6/ioam_cache.c @@ -53,32 +53,10 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+cm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - +#define REPLY_MSG_ID_BASE cm->msg_id_base +#include /* List of message types that this plugin understands */ - #define foreach_ioam_cache_plugin_api_msg \ _(IOAM_CACHE_IP6_ENABLE_DISABLE, ioam_cache_ip6_enable_disable) diff --git a/src/plugins/ioam/lib-pot/pot_api.c b/src/plugins/ioam/lib-pot/pot_api.c index 04c2aaa5..cc1b7b76 100644 --- a/src/plugins/ioam/lib-pot/pot_api.c +++ b/src/plugins/ioam/lib-pot/pot_api.c @@ -51,47 +51,10 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -#define REPLY_MACRO2(t, body) \ -do { \ - unix_shared_memory_queue_t * q; \ - rv = vl_msg_api_pd_handler (mp, rv); \ - q = vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include /* List of message types that this plugin understands */ - #define foreach_pot_plugin_api_msg \ _(POT_PROFILE_ADD, pot_profile_add) \ _(POT_PROFILE_ACTIVATE, pot_profile_activate) \ diff --git a/src/plugins/ioam/udp-ping/udp_ping_api.c b/src/plugins/ioam/udp-ping/udp_ping_api.c index 8cb8cc96..6e5ef61e 100644 --- a/src/plugins/ioam/udp-ping/udp_ping_api.c +++ b/src/plugins/ioam/udp-ping/udp_ping_api.c @@ -51,47 +51,10 @@ #include #undef vl_api_version -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ - do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ - } while(0); - -#define REPLY_MACRO2(t, body) \ - do { \ - unix_shared_memory_queue_t * q; \ - rv = vl_msg_api_pd_handler (mp, rv); \ - q = vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ - } while(0); +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include /* List of message types that this module understands */ - #define foreach_udp_ping_api_msg \ _(UDP_PING_ADD_DEL_REQ, udp_ping_add_del_req) \ _(UDP_PING_EXPORT_REQ, udp_ping_export_req) \ diff --git a/src/plugins/lb/api.c b/src/plugins/lb/api.c index 06c53fa1..9e3bcd65 100644 --- a/src/plugins/lb/api.c +++ b/src/plugins/lb/api.c @@ -51,6 +51,10 @@ typedef enum { #include #undef vl_msg_name_crc_list + +#define REPLY_MSG_ID_BASE lbm->msg_id_base +#include + static void setup_message_id_table (lb_main_t * lbm, api_main_t * am) { @@ -67,29 +71,6 @@ setup_message_id_table (lb_main_t * lbm, api_main_t * am) vec_free (s); \ return handle; -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+lbm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - static void vl_api_lb_conf_t_handler (vl_api_lb_conf_t * mp) diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c index 57274bbe..d42303f6 100644 --- a/src/plugins/snat/snat.c +++ b/src/plugins/snat/snat.c @@ -47,7 +47,7 @@ snat_main_t snat_main; #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define REPLY_MSG_ID_BASE (sm->msg_id_base) +#define REPLY_MSG_ID_BASE sm->msg_id_base #include /* Get the API version number */ diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index aacea7c1..a492c3f4 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -36,7 +36,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ + rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ \ @@ -52,7 +52,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ + rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ @@ -68,7 +68,7 @@ do { \ return; \ \ rmp = vl_msg_api_alloc (sizeof (*rmp) + n); \ - rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ + rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ @@ -97,7 +97,7 @@ do { \ rv = VNET_API_ERROR_TABLE_TOO_BIG; \ is_error = 1; \ } \ - rmp->_vl_msg_id = htons((t)+REPLY_MSG_ID_BASE); \ + rmp->_vl_msg_id = htons((t)+(REPLY_MSG_ID_BASE)); \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ if (!is_error) \ -- cgit 1.2.3-korg From 9793477a28c45e4eb5bba3f2050fe415e57e8ad8 Mon Sep 17 00:00:00 2001 From: John Lo Date: Thu, 18 May 2017 22:26:47 -0400 Subject: Enforce Bridge Domain ID range to match 24-bit VNI range Enforce bridge domain ID range to allow a maximum value of 16M which matches the range of 24-bit VNI used for virtual overlay network ID. Fix "show bridge-domain" output to allow full 16M BD ID range to be displayed using 8-digit spaces. Change-Id: I80d9c76ea7c001bcccd3c19df1f3e55d2970f01c Signed-off-by: John Lo --- src/vlibapi/api_helper_macros.h | 14 ++++++++++++++ src/vnet/api_errno.h | 5 +++-- src/vnet/l2/l2_bd.c | 17 +++++++++++------ src/vnet/l2/l2_bd.h | 4 +++- src/vnet/l2/l2_input.c | 6 ++++++ src/vnet/lisp-gpe/interface.c | 6 ++++++ src/vpp/api/api.c | 2 ++ 7 files changed, 45 insertions(+), 9 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index a492c3f4..2e29d4d7 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -155,6 +155,20 @@ bad_tx_sw_if_index: \ ; \ } while (0); +#define VALIDATE_BD_ID(mp) \ + do { u32 __rx_bd_id = ntohl(mp->bd_id); \ + if (__rx_bd_id > L2_BD_ID_MAX) { \ + rv = VNET_API_ERROR_BD_ID_EXCEED_MAX; \ + goto bad_bd_id; \ + } \ +} while(0); + +#define BAD_BD_ID_LABEL \ +do { \ +bad_bd_id: \ + ; \ +} while (0); + #define pub_sub_handler(lca,UCA) \ static void vl_api_want_##lca##_t_handler ( \ vl_api_want_##lca##_t *mp) \ diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h index e694fbf1..b22bb3a8 100644 --- a/src/vnet/api_errno.h +++ b/src/vnet/api_errno.h @@ -110,8 +110,9 @@ _(SVM_SEGMENT_CREATE_FAIL, -117, "svm segment create fail") \ _(APPLICATION_NOT_ATTACHED, -118, "application not attached") \ _(BD_ALREADY_EXISTS, -119, "Bridge domain already exists") \ _(BD_IN_USE, -120, "Bridge domain has member interfaces") \ -_(BD_NOT_MODIFIABLE, -121, "Default bridge domain 0 can be neither deleted nor modified") \ -_(UNSUPPORTED, -122, "Unsupported") +_(BD_NOT_MODIFIABLE, -121, "Bridge domain 0 can't be deleted/modified") \ +_(BD_ID_EXCEED_MAX, -122, "Bridge domain ID exceed 16M limit") \ +_(UNSUPPORTED, -123, "Unsupported") typedef enum { diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index 351e6987..f68b6638 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -984,10 +984,10 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { printed = 1; vlib_cli_output (vm, - "%=5s %=7s %=4s %=9s %=9s %=9s %=9s %=9s %=9s %=9s", - "ID", "Index", "BSN", "Age(min)", "Learning", - "U-Forwrd", "UU-Flood", "Flooding", "ARP-Term", - "BVI-Intf"); + "%=8s %=7s %=4s %=9s %=9s %=9s %=9s %=9s %=9s %=9s", + "BD-ID", "Index", "BSN", "Age(min)", + "Learning", "U-Forwrd", "UU-Flood", "Flooding", + "ARP-Term", "BVI-Intf"); } if (bd_config->mac_age) @@ -995,7 +995,7 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) else as = format (as, "off"); vlib_cli_output (vm, - "%=5d %=7d %=4d %=9v %=9s %=9s %=9s %=9s %=9s %=9U", + "%=8d %=7d %=4d %=9v %=9s %=9s %=9s %=9s %=9s %=9U", bd_config->bd_id, bd_index, bd_config->seq_num, as, bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ? "on" : "off", @@ -1123,6 +1123,8 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a) { if (bd_index != ~0) return VNET_API_ERROR_BD_ALREADY_EXISTS; + if (a->bd_id > L2_BD_ID_MAX) + return VNET_API_ERROR_BD_ID_EXCEED_MAX; bd_index = bd_add_bd_index (bdm, a->bd_id); u32 enable_flags = 0, disable_flags = 0; @@ -1262,11 +1264,14 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, error = clib_error_return (0, "bridge domain in use - remove members"); goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - error = clib_error_return (0, "bridge domain id does not exist"); + error = clib_error_return (0, "bridge domain ID does not exist"); goto done; case VNET_API_ERROR_BD_NOT_MODIFIABLE: error = clib_error_return (0, "bridge domain 0 can not be modified"); goto done; + case VNET_API_ERROR_BD_ID_EXCEED_MAX: + error = clib_error_return (0, "bridge domain ID exceed 16M limit"); + goto done; default: error = clib_error_return (0, "bd_add_del returned %d", rv); goto done; diff --git a/src/vnet/l2/l2_bd.h b/src/vnet/l2/l2_bd.h index e502d497..93ed1a85 100644 --- a/src/vnet/l2/l2_bd.h +++ b/src/vnet/l2/l2_bd.h @@ -49,7 +49,6 @@ typedef struct u16 spare; } l2_flood_member_t; - /* Per-bridge domain configuration */ typedef struct @@ -91,6 +90,9 @@ typedef struct } l2_bridge_domain_t; +/* Limit Bridge Domain ID to 24 bits to match 24-bit VNI range */ +#define L2_BD_ID_MAX ((1<<24)-1) + typedef struct { u32 bd_id; diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index 41a93f56..aca23fe0 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -791,6 +791,12 @@ int_l2_bridge (vlib_main_t * vm, goto done; } + if (bd_id > L2_BD_ID_MAX) + { + error = clib_error_return (0, "bridge domain ID exceed 16M limit", + format_unformat_error, input); + goto done; + } bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); /* optional bvi */ diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index ff750563..94703abc 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -653,6 +653,12 @@ lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) uword *hip, *si; u16 bd_index; + if (bd_id > L2_BD_ID_MAX) + { + clib_warning ("bridge domain ID %d exceed 16M limit", bd_id); + return ~0; + } + bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index 16d51225..7e4c341e 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -419,6 +419,7 @@ static void if (mp->enable) { + VALIDATE_BD_ID (mp); u32 bd_id = ntohl (mp->bd_id); u32 bd_index = bd_find_or_add_bd_index (bdm, bd_id); u32 bvi = mp->bvi; @@ -432,6 +433,7 @@ static void } BAD_RX_SW_IF_INDEX_LABEL; + BAD_BD_ID_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY); } -- cgit 1.2.3-korg From 8a19f12a0cfe6d611f6e266931af691fb69a74ad Mon Sep 17 00:00:00 2001 From: "Keith Burns (alagalah)" Date: Sun, 6 Aug 2017 08:26:29 -0700 Subject: Allow individual stats API and introduce stats.api - want_interface_simple_stats - want_interface_combined_stats - want_ip4|6_fib|nbr_stats Change-Id: I4e97461def508958b3e429c3fe8859b36fef2d18 Signed-off-by: Keith Burns (alagalah) --- .gitignore | 1 + src/uri.am | 4 +- src/vlibapi/api_helper_macros.h | 1 - src/vpp.am | 12 +- src/vpp/api/api.c | 59 -- src/vpp/api/vpe.api | 112 +--- src/vpp/api/vpe_all_api_h.h | 3 + src/vpp/stats/stats.api | 222 +++++++ src/vpp/stats/stats.c | 1265 ++++++++++++++++++++++++++------------- src/vpp/stats/stats.h | 45 +- 10 files changed, 1132 insertions(+), 592 deletions(-) create mode 100644 src/vpp/stats/stats.api (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/.gitignore b/.gitignore index 10aab98c..dabb31e8 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ test-driver *.iml .bootstrap.ok .settings +.autotools # stop autotools ignore # OSX and some IDE diff --git a/src/uri.am b/src/uri.am index ae6feb6f..660f897d 100644 --- a/src/uri.am +++ b/src/uri.am @@ -1,4 +1,4 @@ -# Copyright (c) 2016 Cisco and/or its affiliates. +# Copyright (c) 2017 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: @@ -58,7 +58,7 @@ vcl_test_server_SOURCES = uri/vcl_test_server.c vcl_test_server_LDADD = libvppcom.la vcl_test_client_SOURCES = uri/vcl_test_client.c -vcl_test_client_LDADD = libvppcom.la +vcl_test_client_LDADD = libvppcom.la sock_test_server_SOURCES = uri/sock_test_server.c sock_test_client_SOURCES = uri/sock_test_client.c diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 2e29d4d7..b8a9978a 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -217,7 +217,6 @@ _(from_netconf_client) \ _(oam_events) \ _(bfd_events) -/* WARNING: replicated in vpp/stats.h */ typedef struct { u32 client_index; /* in memclnt registration pool */ diff --git a/src/vpp.am b/src/vpp.am index 10a4e311..9a07cefe 100644 --- a/src/vpp.am +++ b/src/vpp.am @@ -42,9 +42,11 @@ bin_vpp_CFLAGS = @APICLI@ nobase_include_HEADERS += \ vpp/api/vpe_all_api_h.h \ vpp/api/vpe_msg_enum.h \ + vpp/stats/stats.api.h \ vpp/api/vpe.api.h API_FILES += vpp/api/vpe.api +API_FILES += vpp/stats/stats.api BUILT_SOURCES += .version @@ -116,13 +118,13 @@ endif noinst_PROGRAMS += bin/summary_stats_client bin_summary_stats_client_SOURCES = \ - vpp/api/summary_stats_client.c + vpp/api/summary_stats_client.c bin_summary_stats_client_LDADD = \ - libvlibmemoryclient.la \ - libsvm.la \ - libvppinfra.la \ - -lpthread -lm -lrt + libvlibmemoryclient.la \ + libsvm.la \ + libvppinfra.la \ + -lpthread -lm -lrt bin_PROGRAMS += bin/vpp_get_metrics diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index e8bc22ae..f9c3129c 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -110,7 +110,6 @@ _(CREATE_VLAN_SUBIF, create_vlan_subif) \ _(CREATE_SUBIF, create_subif) \ _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ -_(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) \ _(RESET_FIB, reset_fib) \ _(CREATE_LOOPBACK, create_loopback) \ _(CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \ @@ -745,64 +744,6 @@ vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp) REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY); } -static void -vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp) -{ - stats_main_t *sm = &stats_main; - vnet_interface_main_t *im = sm->interface_main; - vl_api_vnet_get_summary_stats_reply_t *rmp; - vlib_combined_counter_main_t *cm; - vlib_counter_t v; - int i, which; - u64 total_pkts[VLIB_N_RX_TX]; - u64 total_bytes[VLIB_N_RX_TX]; - - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); - - if (!q) - return; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_VNET_GET_SUMMARY_STATS_REPLY); - rmp->context = mp->context; - rmp->retval = 0; - - memset (total_pkts, 0, sizeof (total_pkts)); - memset (total_bytes, 0, sizeof (total_bytes)); - - vnet_interface_counter_lock (im); - - vec_foreach (cm, im->combined_sw_if_counters) - { - which = cm - im->combined_sw_if_counters; - - for (i = 0; i < vlib_combined_counter_n_counters (cm); i++) - { - vlib_get_combined_counter (cm, i, &v); - total_pkts[which] += v.packets; - total_bytes[which] += v.bytes; - } - } - vnet_interface_counter_unlock (im); - - rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]); - rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]); - rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]); - rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]); - rmp->vector_rate = - clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main)); - - vl_msg_api_send_shmem (q, (u8 *) & rmp); -} - -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - ip4_address_t address; - u32 address_length: 6; - u32 index:26; -}) ip4_route_t; -/* *INDENT-ON* */ static int ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp) diff --git a/src/vpp/api/vpe.api b/src/vpp/api/vpe.api index eda95ce5..d68beae1 100644 --- a/src/vpp/api/vpe.api +++ b/src/vpp/api/vpe.api @@ -47,6 +47,7 @@ * DHCP APIs: see ... /src/vnet/dhcp/{dhcpk.api, dhcp_api.c} * COP APIs: see ... /src/vnet/cop/{cop.api, cop_api.c} * POLICER APIs: see ... /src/vnet/policer/{policer.api, policer_api.c} + * STATS APIs: see .../src/vpp/stats/{stats.api, stats.c} */ /** \brief Create a new subinterface with the given vlan id @@ -136,117 +137,6 @@ autoreply define reset_vrf u32 vrf_id; }; -/** \brief Want Stats, register for stats updates - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param enable_disable - 1 = enable stats, 0 = disable - @param pid - pid of process requesting stats updates -*/ -autoreply define want_stats -{ - u32 client_index; - u32 context; - u32 enable_disable; - u32 pid; -}; - -typeonly manual_print manual_endian define ip4_fib_counter -{ - u32 address; - u8 address_length; - u64 packets; - u64 bytes; -}; - -manual_print manual_endian define vnet_ip4_fib_counters -{ - u32 vrf_id; - u32 count; - vl_api_ip4_fib_counter_t c[count]; -}; - -typeonly manual_print manual_endian define ip4_nbr_counter -{ - u32 address; - u8 link_type; - u64 packets; - u64 bytes; -}; - -/** - * @brief Per-neighbour (i.e. per-adjacency) coutners - * @param count The size of the array of counters - * @param sw_if_index The interface the adjacency is on - * @param begin Flag to indicate this is the first set of stats for this - * interface. If this flag is not set the it is a continuation of - * stats for this interface - * @param c counters - */ -manual_print manual_endian define vnet_ip4_nbr_counters -{ - u32 count; - u32 sw_if_index; - u8 begin; - vl_api_ip4_nbr_counter_t c[count]; -}; - -typeonly manual_print manual_endian define ip6_fib_counter -{ - u64 address[2]; - u8 address_length; - u64 packets; - u64 bytes; -}; - -manual_print manual_endian define vnet_ip6_fib_counters -{ - u32 vrf_id; - u32 count; - vl_api_ip6_fib_counter_t c[count]; -}; - -typeonly manual_print manual_endian define ip6_nbr_counter -{ - u64 address[2]; - u8 link_type; - u64 packets; - u64 bytes; -}; - -manual_print manual_endian define vnet_ip6_nbr_counters -{ - u32 count; - u32 sw_if_index; - u8 begin; - vl_api_ip6_nbr_counter_t c[count]; -}; - -/** \brief Request for a single block of summary stats - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -define vnet_get_summary_stats -{ - u32 client_index; - u32 context; -}; - -/** \brief Reply for vnet_get_summary_stats request - @param context - sender context, to match reply w/ request - @param retval - return code for request - @param total_pkts - - @param total_bytes - - @param vector_rate - -*/ -define vnet_get_summary_stats_reply -{ - u32 context; - i32 retval; - u64 total_pkts[2]; - u64 total_bytes[2]; - f64 vector_rate; -}; - /** \brief OAM event structure @param dst_address[] - @param state diff --git a/src/vpp/api/vpe_all_api_h.h b/src/vpp/api/vpe_all_api_h.h index 397cd807..d35a0535 100644 --- a/src/vpp/api/vpe_all_api_h.h +++ b/src/vpp/api/vpe_all_api_h.h @@ -28,6 +28,9 @@ /* Include the current layer (third) vpp API definition layer */ #include +/* Include stats APIs */ +#include + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vpp/stats/stats.api b/src/vpp/stats/stats.api new file mode 100644 index 00000000..7f745859 --- /dev/null +++ b/src/vpp/stats/stats.api @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2015-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. + */ + +/** \file + + This file defines the stats API +*/ + + +/** \brief Want Stats, enable/disable ALL stats updates + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want Interface Simple Stats, register for detailed interface stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_interface_simple_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want Interface Combined Stats, register for continuous stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_interface_combined_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want IP4 FIB Stats, register for continuous stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_ip4_fib_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want IP6 FIB Stats, register for continuous stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_ip6_fib_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want IP4 NBR Stats, register for continuous stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_ip4_nbr_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +/** \brief Want IP6 NBR Stats, register for continuous stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param enable_disable - 1 = enable stats, 0 = disable + @param pid - pid of process requesting stats updates +*/ +autoreply define want_ip6_nbr_stats +{ + u32 client_index; + u32 context; + u32 enable_disable; + u32 pid; +}; + +typeonly manual_print manual_endian define ip4_fib_counter +{ + u32 address; + u8 address_length; + u64 packets; + u64 bytes; +}; + +manual_print manual_endian define vnet_ip4_fib_counters +{ + u32 vrf_id; + u32 count; + vl_api_ip4_fib_counter_t c[count]; +}; + +typeonly manual_print manual_endian define ip4_nbr_counter +{ + u32 address; + u8 link_type; + u64 packets; + u64 bytes; +}; + +/** + * @brief Per-neighbour (i.e. per-adjacency) coutners + * @param count The size of the array of counters + * @param sw_if_index The interface the adjacency is on + * @param begin Flag to indicate this is the first set of stats for this + * interface. If this flag is not set the it is a continuation of + * stats for this interface + * @param c counters + */ +manual_print manual_endian define vnet_ip4_nbr_counters +{ + u32 count; + u32 sw_if_index; + u8 begin; + vl_api_ip4_nbr_counter_t c[count]; +}; + +typeonly manual_print manual_endian define ip6_fib_counter +{ + u64 address[2]; + u8 address_length; + u64 packets; + u64 bytes; +}; + +manual_print manual_endian define vnet_ip6_fib_counters +{ + u32 vrf_id; + u32 count; + vl_api_ip6_fib_counter_t c[count]; +}; + +typeonly manual_print manual_endian define ip6_nbr_counter +{ + u64 address[2]; + u8 link_type; + u64 packets; + u64 bytes; +}; + +manual_print manual_endian define vnet_ip6_nbr_counters +{ + u32 count; + u32 sw_if_index; + u8 begin; + vl_api_ip6_nbr_counter_t c[count]; +}; + + +/** \brief Request for a single block of summary stats + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define vnet_get_summary_stats +{ + u32 client_index; + u32 context; +}; + +/** \brief Reply for vnet_get_summary_stats request + @param context - sender context, to match reply w/ request + @param retval - return code for request + @param total_pkts - + @param total_bytes - + @param vector_rate - +*/ +define vnet_get_summary_stats_reply +{ + u32 context; + i32 retval; + u64 total_pkts[2]; + u64 total_bytes[2]; + f64 vector_rate; +}; + +/* + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vpp/stats/stats.c b/src/vpp/stats/stats.c index b0fac73d..c78a8aef 100644 --- a/src/vpp/stats/stats.c +++ b/src/vpp/stats/stats.c @@ -14,10 +14,8 @@ */ #include #include -#include -#include -#include #include +#include #include #define STATS_DEBUG 0 @@ -48,11 +46,19 @@ stats_main_t stats_main; #define foreach_stats_msg \ _(WANT_STATS, want_stats) \ _(VNET_INTERFACE_SIMPLE_COUNTERS, vnet_interface_simple_counters) \ +_(WANT_INTERFACE_SIMPLE_STATS, want_interface_simple_stats) \ _(VNET_INTERFACE_COMBINED_COUNTERS, vnet_interface_combined_counters) \ +_(WANT_INTERFACE_COMBINED_STATS, want_interface_combined_stats) \ _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \ +_(WANT_IP4_FIB_STATS, want_ip4_fib_stats) \ _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \ +_(WANT_IP6_FIB_STATS, want_ip6_fib_stats) \ _(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \ -_(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) +_(WANT_IP4_NBR_STATS, want_ip4_nbr_stats) \ +_(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) \ +_(WANT_IP6_NBR_STATS, want_ip6_nbr_stats) \ +_(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) + /* These constants ensure msg sizes <= 1024, aka ring allocation */ #define SIMPLE_COUNTER_BATCH_SIZE 126 @@ -64,6 +70,110 @@ _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5) /* ns/us us/ms */ +u8 * +format_vnet_interface_combined_counters (u8 * s, va_list * args) +{ + stats_main_t *sm = &stats_main; + vl_api_vnet_interface_combined_counters_t *mp = + va_arg (*args, vl_api_vnet_interface_combined_counters_t *); + + char *counter_name; + u32 count, sw_if_index; + int i; + count = ntohl (mp->count); + sw_if_index = ntohl (mp->first_sw_if_index); + + vlib_counter_t *vp; + u64 packets, bytes; + vp = (vlib_counter_t *) mp->data; + + switch (mp->vnet_counter_type) + { + case VNET_INTERFACE_COUNTER_RX: + counter_name = "rx"; + break; + case VNET_INTERFACE_COUNTER_TX: + counter_name = "tx"; + break; + default: + counter_name = "bogus"; + break; + } + for (i = 0; i < count; i++) + { + packets = clib_mem_unaligned (&vp->packets, u64); + packets = clib_net_to_host_u64 (packets); + bytes = clib_mem_unaligned (&vp->bytes, u64); + bytes = clib_net_to_host_u64 (bytes); + vp++; + s = format (s, "%U.%s.packets %lld\n", + format_vnet_sw_if_index_name, + sm->vnet_main, sw_if_index, counter_name, packets); + s = format (s, "%U.%s.bytes %lld\n", + format_vnet_sw_if_index_name, + sm->vnet_main, sw_if_index, counter_name, bytes); + sw_if_index++; + } + return s; +} + +u8 * +format_vnet_interface_simple_counters (u8 * s, va_list * args) +{ + stats_main_t *sm = &stats_main; + vl_api_vnet_interface_simple_counters_t *mp = + va_arg (*args, vl_api_vnet_interface_simple_counters_t *); + char *counter_name; + u32 count, sw_if_index; + count = ntohl (mp->count); + sw_if_index = ntohl (mp->first_sw_if_index); + u64 *vp, v; + vp = (u64 *) mp->data; + int i; + + switch (mp->vnet_counter_type) + { + case VNET_INTERFACE_COUNTER_DROP: + counter_name = "drop"; + break; + case VNET_INTERFACE_COUNTER_PUNT: + counter_name = "punt"; + break; + case VNET_INTERFACE_COUNTER_IP4: + counter_name = "ip4"; + break; + case VNET_INTERFACE_COUNTER_IP6: + counter_name = "ip6"; + break; + case VNET_INTERFACE_COUNTER_RX_NO_BUF: + counter_name = "rx-no-buff"; + break; + case VNET_INTERFACE_COUNTER_RX_MISS: + counter_name = "rx-miss"; + break; + case VNET_INTERFACE_COUNTER_RX_ERROR: + counter_name = "rx-error (fifo-full)"; + break; + case VNET_INTERFACE_COUNTER_TX_ERROR: + counter_name = "tx-error (fifo-full)"; + break; + default: + counter_name = "bogus"; + break; + } + for (i = 0; i < count; i++) + { + v = clib_mem_unaligned (vp, u64); + v = clib_net_to_host_u64 (v); + vp++; + s = format (s, "%U.%s %lld\n", format_vnet_sw_if_index_name, + sm->vnet_main, sw_if_index, counter_name, v); + sw_if_index++; + } + + return s; +} + void dslock (stats_main_t * sm, int release_hint, int tag) { @@ -231,14 +341,6 @@ do_combined_interface_counters (stats_main_t * sm) vnet_interface_counter_unlock (im); } -/* from .../vnet/vnet/ip/lookup.c. Yuck */ -typedef CLIB_PACKED (struct - { - ip4_address_t address; -u32 address_length: 6; -u32 index: 26; - }) ip4_route_t; - static void ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec) { @@ -573,167 +675,177 @@ do_ip4_fibs (stats_main_t * sm) api_main_t *am = sm->api_main; vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue; - static ip4_route_t *routes; ip4_route_t *r; fib_table_t *fib; ip4_fib_t *v4_fib; - static uword *results; + do_ip46_fibs_t *do_fibs; vl_api_vnet_ip4_fib_counters_t *mp = 0; u32 items_this_message; vl_api_ip4_fib_counter_t *ctrp = 0; u32 start_at_fib_index = 0; - int i; + int i, j, k; + + do_fibs = &sm->do_ip46_fibs; again: + vec_reset_length (do_fibs->fibs); /* *INDENT-OFF* */ pool_foreach (fib, im4->fibs, - ({ - /* We may have bailed out due to control-plane activity */ - while ((fib - im4->fibs) < start_at_fib_index) - continue; + ({vec_add1(do_fibs->fibs,fib);})); - v4_fib = pool_elt_at_index (im4->v4_fibs, fib->ft_index); + /* *INDENT-ON* */ - if (mp == 0) - { - items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip4_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->ft_table_id); - ctrp = (vl_api_ip4_fib_counter_t *) mp->c; - } - else - { - /* happens if the last FIB was empty... */ - ASSERT (mp->count == 0); - mp->vrf_id = ntohl (fib->ft_table_id); - } + for (j = 0; j < vec_len (do_fibs->fibs); j++) + { + fib = do_fibs->fibs[j]; + /* We may have bailed out due to control-plane activity */ + while ((fib - im4->fibs) < start_at_fib_index) + continue; - dslock (sm, 0 /* release hint */ , 1 /* tag */ ); + v4_fib = pool_elt_at_index (im4->v4_fibs, fib->ft_index); - vec_reset_length (routes); - vec_reset_length (results); + if (mp == 0) + { + items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip4_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + } + else + { + /* happens if the last FIB was empty... */ + ASSERT (mp->count == 0); + mp->vrf_id = ntohl (fib->ft_table_id); + } - for (i = 0; i < ARRAY_LEN (v4_fib->fib_entry_by_dst_address); i++) - { - uword *hash = v4_fib->fib_entry_by_dst_address[i]; - hash_pair_t *p; - ip4_route_t x; - - x.address_length = i; - - hash_foreach_pair (p, hash, - ({ - x.address.data_u32 = p->key; - x.index = p->value[0]; - - vec_add1 (routes, x); - if (sm->data_structure_lock->release_hint) - { - start_at_fib_index = fib - im4->fibs; - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */, - STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip4_fib_counter_t *)mp->c; - goto again; - } - })); - } + dslock (sm, 0 /* release hint */ , 1 /* tag */ ); - vec_foreach (r, routes) - { - vlib_counter_t c; - const dpo_id_t *dpo_id; - - dpo_id = fib_entry_contribute_ip_forwarding(r->index); - vlib_get_combined_counter (&load_balance_main.lbm_to_counters, - (u32)dpo_id->dpoi_index, &c); - /* - * If it has actually - * seen at least one packet, send it. - */ - if (c.packets > 0) - { + vec_reset_length (do_fibs->ip4routes); + vec_reset_length (do_fibs->results); - /* already in net byte order */ - ctrp->address = r->address.as_u32; - ctrp->address_length = r->address_length; - ctrp->packets = clib_host_to_net_u64 (c.packets); - ctrp->bytes = clib_host_to_net_u64 (c.bytes); - mp->count++; - ctrp++; + for (i = 0; i < ARRAY_LEN (v4_fib->fib_entry_by_dst_address); i++) + { + uword *hash = v4_fib->fib_entry_by_dst_address[i]; + hash_pair_t *p; + ip4_route_t x; + + vec_reset_length (do_fibs->pvec); + + x.address_length = i; + + hash_foreach_pair (p, hash, ( + { + vec_add1 (do_fibs->pvec, p);} + )); + for (k = 0; k < vec_len (do_fibs->pvec); k++) + { + p = do_fibs->pvec[k]; + x.address.data_u32 = p->key; + x.index = p->value[0]; + + vec_add1 (do_fibs->ip4routes, x); + if (sm->data_structure_lock->release_hint) + { + start_at_fib_index = fib - im4->fibs; + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + goto again; + } + } + } - if (mp->count == items_this_message) - { - mp->count = htonl (items_this_message); - /* - * If the main thread's input queue is stuffed, - * drop the data structure lock (which the main thread - * may want), and take a pause. - */ - unix_shared_memory_queue_lock (q); - if (unix_shared_memory_queue_is_full (q)) - { - dsunlock (sm); - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - mp = 0; - ip46_fib_stats_delay (sm, 0 /* sec */ , - STATS_RELEASE_DELAY_NS); - goto again; - } - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - - items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip4_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->ft_table_id); - ctrp = (vl_api_ip4_fib_counter_t *) mp->c; - } - } /* for each (mp or single) adj */ - if (sm->data_structure_lock->release_hint) - { - start_at_fib_index = fib - im4->fibs; - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip4_fib_counter_t *) mp->c; - goto again; - } + vec_foreach (r, do_fibs->ip4routes) + { + vlib_counter_t c; + const dpo_id_t *dpo_id; + u32 index; + + dpo_id = fib_entry_contribute_ip_forwarding (r->index); + index = (u32) dpo_id->dpoi_index; + + vlib_get_combined_counter (&load_balance_main.lbm_to_counters, + index, &c); + /* + * If it has actually + * seen at least one packet, send it. + */ + if (c.packets > 0) + { + + /* already in net byte order */ + ctrp->address = r->address.as_u32; + ctrp->address_length = r->address_length; + ctrp->packets = clib_host_to_net_u64 (c.packets); + ctrp->bytes = clib_host_to_net_u64 (c.bytes); + mp->count++; + ctrp++; + + if (mp->count == items_this_message) + { + mp->count = htonl (items_this_message); + /* + * If the main thread's input queue is stuffed, + * drop the data structure lock (which the main thread + * may want), and take a pause. + */ + unix_shared_memory_queue_lock (q); + if (unix_shared_memory_queue_is_full (q)) + { + dsunlock (sm); + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + mp = 0; + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + goto again; + } + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + + items_this_message = IP4_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip4_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + } + } /* for each (mp or single) adj */ + if (sm->data_structure_lock->release_hint) + { + start_at_fib_index = fib - im4->fibs; + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip4_fib_counter_t *) mp->c; + goto again; + } } /* vec_foreach (routes) */ - dsunlock (sm); + dsunlock (sm); - /* Flush any data from this fib */ - if (mp->count) - { - mp->count = htonl (mp->count); - vl_msg_api_send_shmem (q, (u8 *) & mp); - mp = 0; - } - })); - /* *INDENT-ON* */ + /* Flush any data from this fib */ + if (mp->count) + { + mp->count = htonl (mp->count); + vl_msg_api_send_shmem (q, (u8 *) & mp); + mp = 0; + } + } /* If e.g. the last FIB had no reportable routes, free the buffer */ if (mp) vl_msg_api_free (mp); } -typedef struct -{ - ip6_address_t address; - u32 address_length; - u32 index; -} ip6_route_t; - typedef struct { u32 fib_index; @@ -769,137 +881,144 @@ do_ip6_fibs (stats_main_t * sm) api_main_t *am = sm->api_main; vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue; - static ip6_route_t *routes; ip6_route_t *r; fib_table_t *fib; - static uword *results; + do_ip46_fibs_t *do_fibs; vl_api_vnet_ip6_fib_counters_t *mp = 0; u32 items_this_message; vl_api_ip6_fib_counter_t *ctrp = 0; u32 start_at_fib_index = 0; BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash; add_routes_in_fib_arg_t _a, *a = &_a; + int i; + do_fibs = &sm->do_ip46_fibs; again: + vec_reset_length (do_fibs->fibs); /* *INDENT-OFF* */ pool_foreach (fib, im6->fibs, - ({ - /* We may have bailed out due to control-plane activity */ - while ((fib - im6->fibs) < start_at_fib_index) - continue; - - if (mp == 0) - { - items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip6_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->ft_table_id); - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - } + ({vec_add1(do_fibs->fibs,fib);})); + /* *INDENT-ON* */ - dslock (sm, 0 /* release hint */ , 1 /* tag */ ); - vec_reset_length (routes); - vec_reset_length (results); + for (i = 0; i < vec_len (do_fibs->fibs); i++) + { + fib = do_fibs->fibs[i]; + /* We may have bailed out due to control-plane activity */ + while ((fib - im6->fibs) < start_at_fib_index) + continue; - a->fib_index = fib - im6->fibs; - a->routep = &routes; - a->sm = sm; + if (mp == 0) + { + items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip6_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + } - if (clib_setjmp (&sm->jmp_buf, 0) == 0) - { - start_at_fib_index = fib - im6->fibs; - BV (clib_bihash_foreach_key_value_pair) (h, add_routes_in_fib, a); - } - else - { - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */ , - STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - goto again; - } + dslock (sm, 0 /* release hint */ , 1 /* tag */ ); - vec_foreach (r, routes) - { - vlib_counter_t c; - - vlib_get_combined_counter (&load_balance_main.lbm_to_counters, - r->index, &c); - /* - * If it has actually - * seen at least one packet, send it. - */ - if (c.packets > 0) - { - /* already in net byte order */ - ctrp->address[0] = r->address.as_u64[0]; - ctrp->address[1] = r->address.as_u64[1]; - ctrp->address_length = (u8) r->address_length; - ctrp->packets = clib_host_to_net_u64 (c.packets); - ctrp->bytes = clib_host_to_net_u64 (c.bytes); - mp->count++; - ctrp++; - - if (mp->count == items_this_message) - { - mp->count = htonl (items_this_message); - /* - * If the main thread's input queue is stuffed, - * drop the data structure lock (which the main thread - * may want), and take a pause. - */ - unix_shared_memory_queue_lock (q); - if (unix_shared_memory_queue_is_full (q)) - { - dsunlock (sm); - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - mp = 0; - ip46_fib_stats_delay (sm, 0 /* sec */ , - STATS_RELEASE_DELAY_NS); - goto again; - } - vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); - unix_shared_memory_queue_unlock (q); - - items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; - mp = vl_msg_api_alloc_as_if_client - (sizeof (*mp) + - items_this_message * sizeof (vl_api_ip6_fib_counter_t)); - mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); - mp->count = 0; - mp->vrf_id = ntohl (fib->ft_table_id); - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - } - } + vec_reset_length (do_fibs->ip6routes); + vec_reset_length (do_fibs->results); - if (sm->data_structure_lock->release_hint) - { - start_at_fib_index = fib - im6->fibs; - dsunlock (sm); - ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); - mp->count = 0; - ctrp = (vl_api_ip6_fib_counter_t *) mp->c; - goto again; - } - } /* vec_foreach (routes) */ + a->fib_index = fib - im6->fibs; + a->routep = &do_fibs->ip6routes; + a->sm = sm; - dsunlock (sm); + if (clib_setjmp (&sm->jmp_buf, 0) == 0) + { + start_at_fib_index = fib - im6->fibs; + BV (clib_bihash_foreach_key_value_pair) (h, add_routes_in_fib, a); + } + else + { + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + goto again; + } - /* Flush any data from this fib */ - if (mp->count) + vec_foreach (r, do_fibs->ip6routes) { - mp->count = htonl (mp->count); - vl_msg_api_send_shmem (q, (u8 *) & mp); - mp = 0; - } - })); - /* *INDENT-ON* */ + vlib_counter_t c; + + vlib_get_combined_counter (&load_balance_main.lbm_to_counters, + r->index, &c); + /* + * If it has actually + * seen at least one packet, send it. + */ + if (c.packets > 0) + { + /* already in net byte order */ + ctrp->address[0] = r->address.as_u64[0]; + ctrp->address[1] = r->address.as_u64[1]; + ctrp->address_length = (u8) r->address_length; + ctrp->packets = clib_host_to_net_u64 (c.packets); + ctrp->bytes = clib_host_to_net_u64 (c.bytes); + mp->count++; + ctrp++; + + if (mp->count == items_this_message) + { + mp->count = htonl (items_this_message); + /* + * If the main thread's input queue is stuffed, + * drop the data structure lock (which the main thread + * may want), and take a pause. + */ + unix_shared_memory_queue_lock (q); + if (unix_shared_memory_queue_is_full (q)) + { + dsunlock (sm); + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + mp = 0; + ip46_fib_stats_delay (sm, 0 /* sec */ , + STATS_RELEASE_DELAY_NS); + goto again; + } + vl_msg_api_send_shmem_nolock (q, (u8 *) & mp); + unix_shared_memory_queue_unlock (q); + + items_this_message = IP6_FIB_COUNTER_BATCH_SIZE; + mp = vl_msg_api_alloc_as_if_client + (sizeof (*mp) + + items_this_message * sizeof (vl_api_ip6_fib_counter_t)); + mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS); + mp->count = 0; + mp->vrf_id = ntohl (fib->ft_table_id); + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + } + } + + if (sm->data_structure_lock->release_hint) + { + start_at_fib_index = fib - im6->fibs; + dsunlock (sm); + ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS); + mp->count = 0; + ctrp = (vl_api_ip6_fib_counter_t *) mp->c; + goto again; + } + } /* vec_foreach (routes) */ + + dsunlock (sm); + + /* Flush any data from this fib */ + if (mp->count) + { + mp->count = htonl (mp->count); + vl_msg_api_send_shmem (q, (u8 *) & mp); + mp = 0; + } + } /* If e.g. the last FIB had no reportable routes, free the buffer */ if (mp) @@ -946,84 +1065,45 @@ static void vl_api_vnet_interface_simple_counters_t_handler (vl_api_vnet_interface_simple_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_interface_simple_counters_t *mp_copy = NULL; u32 mp_size; - -#if STATS_DEBUG > 0 - char *counter_name; - u32 count, sw_if_index; int i; -#endif mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (u64)); /* *INDENT-OFF* */ + vec_reset_length(sm->regs); pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) - { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) - { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; - } - q_prev = q; - } + vec_add1(sm->regs,reg); })); /* *INDENT-ON* */ - -#if STATS_DEBUG > 0 - count = ntohl (mp->count); - sw_if_index = ntohl (mp->first_sw_if_index); - u64 *vp, v; - vp = (u64 *) mp->data; - - switch (mp->vnet_counter_type) - { - case VNET_INTERFACE_COUNTER_DROP: - counter_name = "drop"; - break; - case VNET_INTERFACE_COUNTER_PUNT: - counter_name = "punt"; - break; - case VNET_INTERFACE_COUNTER_IP4: - counter_name = "ip4"; - break; - case VNET_INTERFACE_COUNTER_IP6: - counter_name = "ip6"; - break; - case VNET_INTERFACE_COUNTER_RX_NO_BUF: - counter_name = "rx-no-buff"; - break; - case VNET_INTERFACE_COUNTER_RX_MISS: - , counter_name = "rx-miss"; - break; - case VNET_INTERFACE_COUNTER_RX_ERROR: - , counter_name = "rx-error (fifo-full)"; - break; - case VNET_INTERFACE_COUNTER_TX_ERROR: - , counter_name = "tx-error (fifo-full)"; - break; - default: - counter_name = "bogus"; - break; - } - for (i = 0; i < count; i++) + for (i = 0; i < vec_len (sm->regs); i++) { - v = clib_mem_unaligned (vp, u64); - v = clib_net_to_host_u64 (v); - vp++; - fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name, - sm->vnet_main, sw_if_index, counter_name, v); - sw_if_index++; + reg = sm->regs[i]; + if (reg->stats_registrations & INTERFACE_SIMPLE_COUNTERS) + { + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) + { + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client (mp_size); + clib_memcpy (mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *) & mp); + mp = mp_copy; + } + q_prev = q; + } + } } +#if STATS_DEBUG > 0 + fformat (stdout, "%U\n", format_vnet_simple_counters, mp); #endif + if (q_prev && (q_prev->cursize < q_prev->maxsize)) { vl_msg_api_send_shmem (q_prev, (u8 *) & mp); @@ -1038,75 +1118,39 @@ static void vl_api_vnet_interface_combined_counters_t_handler (vl_api_vnet_interface_combined_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_interface_combined_counters_t *mp_copy = NULL; u32 mp_size; -#if STATS_DEBUG > 0 - char *counter_name; - u32 count, sw_if_index; - int i; -#endif - mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (vlib_counter_t)); /* *INDENT-OFF* */ pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) - { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) - { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; - } - q_prev = q; - } + if (reg->stats_registrations & INTERFACE_COMBINED_COUNTERS) + { + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) + { + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client(mp_size); + clib_memcpy(mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *)&mp); + mp = mp_copy; + } + q_prev = q; + } + } })); /* *INDENT-ON* */ #if STATS_DEBUG > 0 - count = ntohl (mp->count); - sw_if_index = ntohl (mp->first_sw_if_index); - - vlib_counter_t *vp; - u64 packets, bytes; - vp = (vlib_counter_t *) mp->data; - - switch (mp->vnet_counter_type) - { - case VNET_INTERFACE_COUNTER_RX: - counter_name = "rx"; - break; - case VNET_INTERFACE_COUNTER_TX: - counter_name = "tx"; - break; - default: - counter_name = "bogus"; - break; - } - for (i = 0; i < count; i++) - { - packets = clib_mem_unaligned (&vp->packets, u64); - packets = clib_net_to_host_u64 (packets); - bytes = clib_mem_unaligned (&vp->bytes, u64); - bytes = clib_net_to_host_u64 (bytes); - vp++; - fformat (stdout, "%U.%s.packets %lld\n", - format_vnet_sw_if_index_name, - sm->vnet_main, sw_if_index, counter_name, packets); - fformat (stdout, "%U.%s.bytes %lld\n", - format_vnet_sw_if_index_name, - sm->vnet_main, sw_if_index, counter_name, bytes); - sw_if_index++; - } - + fformat (stdout, "%U\n", format_vnet_combined_counters, mp); #endif + if (q_prev && (q_prev->cursize < q_prev->maxsize)) { vl_msg_api_send_shmem (q_prev, (u8 *) & mp); @@ -1120,7 +1164,7 @@ static void static void vl_api_vnet_ip4_fib_counters_t_handler (vl_api_vnet_ip4_fib_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_ip4_fib_counters_t *mp_copy = NULL; @@ -1132,17 +1176,20 @@ vl_api_vnet_ip4_fib_counters_t_handler (vl_api_vnet_ip4_fib_counters_t * mp) /* *INDENT-OFF* */ pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) + if (reg->stats_registrations & IP4_FIB_COUNTERS) { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client(mp_size); + clib_memcpy(mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *)&mp); + mp = mp_copy; + } + q_prev = q; } - q_prev = q; } })); /* *INDENT-ON* */ @@ -1159,7 +1206,7 @@ vl_api_vnet_ip4_fib_counters_t_handler (vl_api_vnet_ip4_fib_counters_t * mp) static void vl_api_vnet_ip4_nbr_counters_t_handler (vl_api_vnet_ip4_nbr_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_ip4_nbr_counters_t *mp_copy = NULL; @@ -1171,17 +1218,20 @@ vl_api_vnet_ip4_nbr_counters_t_handler (vl_api_vnet_ip4_nbr_counters_t * mp) /* *INDENT-OFF* */ pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) + if (reg->stats_registrations & IP4_NBR_COUNTERS) { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client(mp_size); + clib_memcpy(mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *)&mp); + mp = mp_copy; + } + q_prev = q; } - q_prev = q; } })); /* *INDENT-ON* */ @@ -1198,7 +1248,7 @@ vl_api_vnet_ip4_nbr_counters_t_handler (vl_api_vnet_ip4_nbr_counters_t * mp) static void vl_api_vnet_ip6_fib_counters_t_handler (vl_api_vnet_ip6_fib_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_ip6_fib_counters_t *mp_copy = NULL; @@ -1210,19 +1260,22 @@ vl_api_vnet_ip6_fib_counters_t_handler (vl_api_vnet_ip6_fib_counters_t * mp) /* *INDENT-OFF* */ pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) + if (reg->stats_registrations & IP6_FIB_COUNTERS) { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client(mp_size); + clib_memcpy(mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *)&mp); + mp = mp_copy; + } + q_prev = q; } - q_prev = q; } - })); + })); /* *INDENT-ON* */ if (q_prev && (q_prev->cursize < q_prev->maxsize)) { @@ -1237,7 +1290,7 @@ vl_api_vnet_ip6_fib_counters_t_handler (vl_api_vnet_ip6_fib_counters_t * mp) static void vl_api_vnet_ip6_nbr_counters_t_handler (vl_api_vnet_ip6_nbr_counters_t * mp) { - vpe_client_registration_t *reg; + vpe_client_stats_registration_t *reg; stats_main_t *sm = &stats_main; unix_shared_memory_queue_t *q, *q_prev = NULL; vl_api_vnet_ip6_nbr_counters_t *mp_copy = NULL; @@ -1249,17 +1302,20 @@ vl_api_vnet_ip6_nbr_counters_t_handler (vl_api_vnet_ip6_nbr_counters_t * mp) /* *INDENT-OFF* */ pool_foreach(reg, sm->stats_registrations, ({ - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q) + if (reg->stats_registrations & IP6_NBR_COUNTERS) { - if (q_prev && (q_prev->cursize < q_prev->maxsize)) + q = vl_api_client_index_to_input_queue (reg->client.client_index); + if (q) { - mp_copy = vl_msg_api_alloc_as_if_client(mp_size); - clib_memcpy(mp_copy, mp, mp_size); - vl_msg_api_send_shmem (q_prev, (u8 *)&mp); - mp = mp_copy; + if (q_prev && (q_prev->cursize < q_prev->maxsize)) + { + mp_copy = vl_msg_api_alloc_as_if_client(mp_size); + clib_memcpy(mp_copy, mp, mp_size); + vl_msg_api_send_shmem (q_prev, (u8 *)&mp); + mp = mp_copy; + } + q_prev = q; } - q_prev = q; } })); /* *INDENT-ON* */ @@ -1277,7 +1333,7 @@ static void vl_api_want_stats_t_handler (vl_api_want_stats_t * mp) { stats_main_t *sm = &stats_main; - vpe_client_registration_t *rp; + vpe_client_stats_registration_t *rp; vl_api_want_stats_reply_t *rmp; uword *p; i32 retval = 0; @@ -1307,9 +1363,16 @@ vl_api_want_stats_t_handler (vl_api_want_stats_t * mp) goto reply; } pool_get (sm->stats_registrations, rp); - rp->client_index = mp->client_index; - rp->client_pid = mp->pid; - hash_set (sm->stats_registration_hash, rp->client_index, + rp->client.client_index = mp->client_index; + rp->client.client_pid = mp->pid; + rp->stats_registrations |= INTERFACE_SIMPLE_COUNTERS; + rp->stats_registrations |= INTERFACE_COMBINED_COUNTERS; + rp->stats_registrations |= IP4_FIB_COUNTERS; + rp->stats_registrations |= IP4_NBR_COUNTERS; + rp->stats_registrations |= IP6_FIB_COUNTERS; + rp->stats_registrations |= IP6_NBR_COUNTERS; + + hash_set (sm->stats_registration_hash, rp->client.client_index, rp - sm->stats_registrations); reply: @@ -1331,10 +1394,386 @@ reply: vl_msg_api_send_shmem (q, (u8 *) & rmp); } +static void + vl_api_want_interface_simple_stats_t_handler + (vl_api_want_interface_simple_stats_t * mp) +{ + stats_main_t *sm = &stats_main; + vpe_client_stats_registration_t *rp; + vl_api_want_interface_simple_stats_reply_t *rmp; + uword *p; + i32 retval = 0; + unix_shared_memory_queue_t *q; + + p = hash_get (sm->stats_registration_hash, mp->client_index); + + /* Disable case */ + if (mp->enable_disable == 0) + { + if (!p) // No client to disable + { + clib_warning ("pid %d: already disabled for stats...", mp->pid); + retval = 0; + goto reply; + } + + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + if (!rp->stats_registrations & INTERFACE_SIMPLE_COUNTERS) // Client but doesn't want this. + { + clib_warning + ("pid %d: already disabled for interface simple stats...", + mp->pid); + retval = 0; + goto reply; + } + else + { + rp->stats_registrations &= ~(INTERFACE_SIMPLE_COUNTERS); // Clear flag + if (rp->stats_registrations == 0) // Client isn't listening to anything else + { + pool_put (sm->stats_registrations, rp); + hash_unset (sm->stats_registration_hash, mp->client_index); + } + goto reply; + } + } + /* Enable case */ + /* Get client from pool */ + if (p) + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + + if (!p || !rp) // Doesn't exist, make a new entry + { + pool_get (sm->stats_registrations, rp); + rp->client.client_index = mp->client_index; + rp->client.client_pid = mp->pid; + } + rp->stats_registrations |= INTERFACE_SIMPLE_COUNTERS; + hash_set (sm->stats_registration_hash, rp->client.client_index, + rp - sm->stats_registrations); + +reply: + if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now. + sm->enable_poller = 1; + else + sm->enable_poller = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_SIMPLE_STATS_REPLY); + rmp->context = mp->context; + rmp->retval = retval; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void + vl_api_want_interface_combined_stats_t_handler + (vl_api_want_interface_combined_stats_t * mp) +{ + stats_main_t *sm = &stats_main; + vpe_client_stats_registration_t *rp; + vl_api_want_interface_combined_stats_reply_t *rmp; + uword *p; + i32 retval = 0; + unix_shared_memory_queue_t *q; + + p = hash_get (sm->stats_registration_hash, mp->client_index); + + /* Disable case */ + if (mp->enable_disable == 0) + { + if (!p) // No client to disable + { + clib_warning ("pid %d: already disabled for stats...", mp->pid); + retval = 0; + goto reply; + } + + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + if (!rp->stats_registrations & INTERFACE_COMBINED_COUNTERS) // Client but doesn't want this. + { + clib_warning + ("pid %d: already disabled for interface COMBINED stats...", + mp->pid); + retval = 0; + goto reply; + } + else + { + rp->stats_registrations &= ~(INTERFACE_COMBINED_COUNTERS); // Clear flag + if (rp->stats_registrations == 0) // Client isn't listening to anything else + { + pool_put (sm->stats_registrations, rp); + hash_unset (sm->stats_registration_hash, mp->client_index); + } + goto reply; + } + } + /* Enable case */ + /* Get client from pool */ + if (p) + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + + if (!p || !rp) // Doesn't exist, make a new entry + { + pool_get (sm->stats_registrations, rp); + rp->client.client_index = mp->client_index; + rp->client.client_pid = mp->pid; + } + rp->stats_registrations |= INTERFACE_COMBINED_COUNTERS; + hash_set (sm->stats_registration_hash, rp->client.client_index, + rp - sm->stats_registrations); + +reply: + if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now. + sm->enable_poller = 1; + else + sm->enable_poller = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_COMBINED_STATS_REPLY); + rmp->context = mp->context; + rmp->retval = retval; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void +vl_api_want_ip4_fib_stats_t_handler (vl_api_want_ip4_fib_stats_t * mp) +{ + stats_main_t *sm = &stats_main; + vpe_client_stats_registration_t *rp; + vl_api_want_ip4_fib_stats_reply_t *rmp; + uword *p; + i32 retval = 0; + unix_shared_memory_queue_t *q; + + p = hash_get (sm->stats_registration_hash, mp->client_index); + + /* Disable case */ + /* + $$$ FIXME: need std return codes. Still undecided if enabling already + enabled (and similar for disabled) is really a -'ve error condition or + if 0 is sufficient + */ + if (mp->enable_disable == 0) + { + if (!p) // No client to disable + { + clib_warning ("pid %d: already disabled for stats...", mp->pid); + retval = -3; + goto reply; + } + + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + if (!rp->stats_registrations & IP4_FIB_COUNTERS) // Client but doesn't want this. + { + clib_warning ("pid %d: already disabled for interface ip4 fib...", + mp->pid); + retval = -2; + goto reply; + } + else + { + rp->stats_registrations &= ~(IP4_FIB_COUNTERS); // Clear flag + if (rp->stats_registrations == 0) // Client isn't listening to anything else + { + pool_put (sm->stats_registrations, rp); + hash_unset (sm->stats_registration_hash, mp->client_index); + } + goto reply; + } + } + /* Enable case */ + /* Get client from pool */ + if (p) + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + + if (!p || !rp) // Doesn't exist, make a new entry + { + pool_get (sm->stats_registrations, rp); + rp->client.client_index = mp->client_index; + rp->client.client_pid = mp->pid; + } + rp->stats_registrations |= IP4_FIB_COUNTERS; + hash_set (sm->stats_registration_hash, rp->client.client_index, + rp - sm->stats_registrations); + +reply: + if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now. + sm->enable_poller = 1; + else + sm->enable_poller = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_WANT_IP4_FIB_STATS_REPLY); + rmp->context = mp->context; + rmp->retval = retval; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +static void +vl_api_want_ip6_fib_stats_t_handler (vl_api_want_ip6_fib_stats_t * mp) +{ + stats_main_t *sm = &stats_main; + vpe_client_stats_registration_t *rp; + vl_api_want_ip6_fib_stats_reply_t *rmp; + uword *p; + i32 retval = 0; + unix_shared_memory_queue_t *q; + + p = hash_get (sm->stats_registration_hash, mp->client_index); + + /* Disable case */ + /* + $$$ FIXME: need std return codes. Still undecided if enabling already + enabled (and similar for disabled) is really a -'ve error condition or + if 0 is sufficient + */ + if (mp->enable_disable == 0) + { + if (!p) // No client to disable + { + clib_warning ("pid %d: already disabled for stats...", mp->pid); + retval = -3; + goto reply; + } + + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + if (!rp->stats_registrations & IP6_FIB_COUNTERS) // Client but doesn't want this. + { + clib_warning ("pid %d: already disabled for interface ip6 fib...", + mp->pid); + retval = -2; + goto reply; + } + else + { + rp->stats_registrations &= ~(IP6_FIB_COUNTERS); // Clear flag + if (rp->stats_registrations == 0) // Client isn't listening to anything else + { + pool_put (sm->stats_registrations, rp); + hash_unset (sm->stats_registration_hash, mp->client_index); + } + goto reply; + } + } + /* Enable case */ + /* Get client from pool */ + if (p) + rp = pool_elt_at_index (sm->stats_registrations, p[0]); + + if (!p || !rp) // Doesn't exist, make a new entry + { + pool_get (sm->stats_registrations, rp); + rp->client.client_index = mp->client_index; + rp->client.client_pid = mp->pid; + } + rp->stats_registrations |= IP6_FIB_COUNTERS; + hash_set (sm->stats_registration_hash, rp->client.client_index, + rp - sm->stats_registrations); + +reply: + if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now. + sm->enable_poller = 1; + else + sm->enable_poller = 0; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_WANT_IP6_FIB_STATS_REPLY); + rmp->context = mp->context; + rmp->retval = retval; + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +/* FIXME - NBR stats broken - this will be fixed in subsequent patch */ +static void +vl_api_want_ip4_nbr_stats_t_handler (vl_api_want_ip4_nbr_stats_t * mp) +{ +} + +static void +vl_api_want_ip6_nbr_stats_t_handler (vl_api_want_ip6_nbr_stats_t * mp) +{ +} + +static void +vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp) +{ + stats_main_t *sm = &stats_main; + vnet_interface_main_t *im = sm->interface_main; + vl_api_vnet_get_summary_stats_reply_t *rmp; + vlib_combined_counter_main_t *cm; + vlib_counter_t v; + int i, which; + u64 total_pkts[VLIB_N_RX_TX]; + u64 total_bytes[VLIB_N_RX_TX]; + + unix_shared_memory_queue_t *q = + vl_api_client_index_to_input_queue (mp->client_index); + + if (!q) + return; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_VNET_GET_SUMMARY_STATS_REPLY); + rmp->context = mp->context; + rmp->retval = 0; + + memset (total_pkts, 0, sizeof (total_pkts)); + memset (total_bytes, 0, sizeof (total_bytes)); + + vnet_interface_counter_lock (im); + + vec_foreach (cm, im->combined_sw_if_counters) + { + which = cm - im->combined_sw_if_counters; + + for (i = 0; i < vlib_combined_counter_n_counters (cm); i++) + { + vlib_get_combined_counter (cm, i, &v); + total_pkts[which] += v.packets; + total_bytes[which] += v.bytes; + } + } + vnet_interface_counter_unlock (im); + + rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]); + rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]); + rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]); + rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]); + rmp->vector_rate = + clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main)); + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + int stats_memclnt_delete_callback (u32 client_index) { - vpe_client_registration_t *rp; + vpe_client_stats_registration_t *rp; stats_main_t *sm = &stats_main; uword *p; diff --git a/src/vpp/stats/stats.h b/src/vpp/stats/stats.h index 024dc78e..167b09bd 100644 --- a/src/vpp/stats/stats.h +++ b/src/vpp/stats/stats.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,44 @@ typedef struct int tag; } data_structure_lock_t; +typedef struct +{ + vpe_client_registration_t client; + u8 stats_registrations; +#define INTERFACE_SIMPLE_COUNTERS (1 << 0) +#define INTERFACE_COMBINED_COUNTERS (1 << 1) +#define IP4_FIB_COUNTERS (1 << 2) +#define IP4_NBR_COUNTERS (1 << 3) +#define IP6_FIB_COUNTERS (1 << 4) +#define IP6_NBR_COUNTERS (1 << 5) + +} vpe_client_stats_registration_t; + +/* from .../vnet/vnet/ip/lookup.c. Yuck */ +typedef CLIB_PACKED (struct + { + ip4_address_t address; +u32 address_length: 6; +u32 index: 26; + }) ip4_route_t; + +typedef struct +{ + ip6_address_t address; + u32 address_length; + u32 index; +} ip6_route_t; + + +typedef struct +{ + ip4_route_t *ip4routes; + ip6_route_t *ip6routes; + fib_table_t **fibs; + hash_pair_t **pvec; + uword *results; +} do_ip46_fibs_t; + typedef struct { void *mheap; @@ -45,7 +84,8 @@ typedef struct u32 enable_poller; uword *stats_registration_hash; - vpe_client_registration_t *stats_registrations; + vpe_client_stats_registration_t *stats_registrations; + vpe_client_stats_registration_t **regs; /* control-plane data structure lock */ data_structure_lock_t *data_structure_lock; @@ -53,6 +93,9 @@ typedef struct /* bail out of FIB walk if set */ clib_longjmp_t jmp_buf; + /* Vectors for Distribution funcs: do_ip4_fibs and do_ip6_fibs. */ + do_ip46_fibs_t do_ip46_fibs; + /* convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; -- cgit 1.2.3-korg From 2019748a0ef815852281aae0a603f0e970fa9d91 Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Wed, 13 Sep 2017 12:29:08 +0300 Subject: L2BD,ARP-TERM:fix arp query report mechanism+test previous mechanism was emitting duplicates of last event, when handling multiple arp queries. tests: * arp events sent for graps * duplicate suppression * verify no events when disabled Change-Id: I84adc23980d43b819261eccf02ec056b5cec61df Signed-off-by: Eyal Bari --- src/vlibapi/api_helper_macros.h | 3 +- src/vnet/ethernet/arp.c | 77 ++++++++++++------ src/vnet/ethernet/ethernet.h | 9 +++ src/vpp/api/api.c | 174 +++++++++++++++++++++++++++++++--------- test/test_l2bd_arp_term.py | 82 ++++++++++++++++++- test/vpp_papi_provider.py | 12 ++- 6 files changed, 288 insertions(+), 69 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index b8a9978a..13734896 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -215,7 +215,8 @@ _(from_netconf_server) \ _(to_netconf_client) \ _(from_netconf_client) \ _(oam_events) \ -_(bfd_events) +_(bfd_events) \ +_(wc_ip4_arp_events) typedef struct { diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 957706c1..2f3aa6c7 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -92,6 +92,8 @@ typedef struct /* Proxy arp vector */ ethernet_proxy_arp_t *proxy_arps; + + uword wc_ip4_arp_publisher_node; } ethernet_arp_main_t; static ethernet_arp_main_t ethernet_arp_main; @@ -106,6 +108,7 @@ typedef struct #define ETHERNET_ARP_ARGS_REMOVE (1<<0) #define ETHERNET_ARP_ARGS_FLUSH (1<<1) #define ETHERNET_ARP_ARGS_POPULATE (1<<2) +#define ETHERNET_ARP_ARGS_WC_PUB (1<<3) } vnet_arp_set_ip4_over_ethernet_rpc_args_t; static const u8 vrrp_prefix[] = { 0x00, 0x00, 0x5E, 0x00, 0x01 }; @@ -540,7 +543,7 @@ arp_adj_fib_add (ethernet_arp_ip4_entry_t * e, u32 fib_index) fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ); } -int +static int vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm, vnet_arp_set_ip4_over_ethernet_rpc_args_t * args) @@ -1507,6 +1510,49 @@ vnet_arp_populate_ip4_over_ethernet (vnet_main_t * vnm, return 0; } +/** + * @brief publish wildcard arp event + * @param sw_if_index The interface on which the ARP entires are acted + */ +static int +vnet_arp_wc_publish (u32 sw_if_index, void *a_arg) +{ + ethernet_arp_ip4_over_ethernet_address_t *a = a_arg; + vnet_arp_set_ip4_over_ethernet_rpc_args_t args = { + .flags = ETHERNET_ARP_ARGS_WC_PUB, + .sw_if_index = sw_if_index, + .a = *a + }; + + vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, + (u8 *) & args, sizeof (args)); + return 0; +} + +static void +vnet_arp_wc_publish_internal (vnet_main_t * vnm, + vnet_arp_set_ip4_over_ethernet_rpc_args_t * + args) +{ + vlib_main_t *vm = vlib_get_main (); + ethernet_arp_main_t *am = ðernet_arp_main; + if (am->wc_ip4_arp_publisher_node == (uword) ~ 0) + return; + wc_arp_report_t *r = + vlib_process_signal_event_data (vm, am->wc_ip4_arp_publisher_node, 1, 1, + sizeof *r); + r->ip4 = args->a.ip4.as_u32; + r->sw_if_index = args->sw_if_index; + memcpy (r->mac, args->a.ethernet, sizeof r->mac); +} + +void +wc_arp_set_publisher_node (uword node_index) +{ + ethernet_arp_main_t *am = ðernet_arp_main; + am->wc_ip4_arp_publisher_node = node_index; +} + /* * arp_add_del_interface_address * @@ -1652,6 +1698,7 @@ ethernet_arp_init (vlib_main_t * vm) am->pending_resolutions_by_address = hash_create (0, sizeof (uword)); am->mac_changes_by_address = hash_create (0, sizeof (uword)); + am->wc_ip4_arp_publisher_node = (uword) ~ 0; /* don't trace ARP error packets */ { @@ -1795,6 +1842,8 @@ set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t vnet_arp_flush_ip4_over_ethernet_internal (vm, a); else if (a->flags & ETHERNET_ARP_ARGS_POPULATE) vnet_arp_populate_ip4_over_ethernet_internal (vm, a); + else if (a->flags & ETHERNET_ARP_ARGS_WC_PUB) + vnet_arp_wc_publish_internal (vm, a); else vnet_arp_set_ip4_over_ethernet_internal (vm, a); } @@ -2277,31 +2326,9 @@ arp_term_l2bd (vlib_main_t * vm, /* Check if anyone want ARP request events for L2 BDs */ { - pending_resolution_t *mc; ethernet_arp_main_t *am = ðernet_arp_main; - uword *p = hash_get (am->mac_changes_by_address, 0); - if (p) - { - u32 next_index = p[0]; - while (next_index != (u32) ~ 0) - { - int (*fp) (u32, u8 *, u32, u32); - int rv = 1; - mc = pool_elt_at_index (am->mac_changes, next_index); - fp = mc->data_callback; - /* Call the callback, return 1 to suppress dup events */ - if (fp) - rv = (*fp) (mc->data, - arp0->ip4_over_ethernet[0].ethernet, - sw_if_index0, - arp0->ip4_over_ethernet[0].ip4.as_u32); - /* Signal the resolver process */ - if (rv == 0) - vlib_process_signal_event (vm, mc->node_index, - mc->type_opaque, mc->data); - next_index = mc->next_index; - } - } + if (am->wc_ip4_arp_publisher_node != (uword) ~ 0) + vnet_arp_wc_publish (sw_if_index0, &arp0->ip4_over_ethernet[0]); } /* lookup BD mac_by_ip4 hash table for MAC entry */ diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index 9ca256c9..1a9e9790 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -543,6 +543,8 @@ int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm, uword type_opaque, uword data, int is_add); +void wc_arp_set_publisher_node (uword inode_index); + void ethernet_arp_change_mac (u32 sw_if_index); void ethernet_ndp_change_mac (u32 sw_if_index); @@ -557,6 +559,13 @@ const u8 *ethernet_ip6_mcast_dst_addr (void); extern vlib_node_registration_t ethernet_input_node; +typedef struct +{ + u32 sw_if_index; + u32 ip4; + u8 mac[6]; +} wc_arp_report_t; + #endif /* included_ethernet_h */ /* diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index 044ddb5b..e229a5e3 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -299,17 +299,17 @@ static uword resolver_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { - uword event_type; - uword *event_data = 0; - f64 timeout = 100.0; - int i; + volatile f64 timeout = 100.0; + volatile uword *event_data = 0; while (1) { vlib_process_wait_for_event_or_clock (vm, timeout); - event_type = vlib_process_get_events (vm, &event_data); + uword event_type = + vlib_process_get_events (vm, (uword **) & event_data); + int i; switch (event_type) { case RESOLUTION_PENDING_EVENT: @@ -1352,26 +1352,15 @@ arp_change_data_callback (u32 pool_index, u8 * new_mac, return 1; event = pool_elt_at_index (am->arp_events, pool_index); - /* *INDENT-OFF* */ - if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) + if (eth_mac_equal (event->new_mac, new_mac) && + sw_if_index == ntohl (event->sw_if_index)) { - clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); + return 1; } - else - { /* same mac */ - if (sw_if_index == ntohl(event->sw_if_index) && - (!event->mac_ip || - /* for BD case, also check IP address with 10 sec timeout */ - (address == event->address && - (now - arp_event_last_time) < 10.0))) - return 1; - } - /* *INDENT-ON* */ - arp_event_last_time = now; + clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); event->sw_if_index = htonl (sw_if_index); - if (event->mac_ip) - event->address = address; + arp_event_last_time = now; return 0; } @@ -1391,7 +1380,7 @@ nd_change_data_callback (u32 pool_index, u8 * new_mac, event = pool_elt_at_index (am->nd_events, pool_index); /* *INDENT-OFF* */ - if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac))) + if (memcmp (event->new_mac, new_mac, sizeof (event->new_mac))) { clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); } @@ -1438,13 +1427,123 @@ nd_change_delete_callback (u32 pool_index, u8 * notused) return 0; } +static vlib_node_registration_t wc_ip4_arp_process_node; + +static uword +wc_ip4_arp_process (vlib_main_t * vm, + vlib_node_runtime_t * rt, vlib_frame_t * f) +{ + /* These cross the longjmp boundry (vlib_process_wait_for_event) + * and need to be volatile - to prevent them from being optimized into + * a register - which could change during suspension */ + + volatile wc_arp_report_t prev = { 0 }; + volatile f64 last = vlib_time_now (vm); + + while (1) + { + vlib_process_wait_for_event (vm); + uword event_type; + wc_arp_report_t *event_data = + vlib_process_get_event_data (vm, &event_type); + + f64 now = vlib_time_now (vm); + int i; + for (i = 0; i < vec_len (event_data); i++) + { + /* discard dup event */ + if (prev.ip4 == event_data[i].ip4 && + eth_mac_equal ((u8 *) prev.mac, event_data[i].mac) && + prev.sw_if_index == event_data[i].sw_if_index && + (now - last) < 10.0) + { + continue; + } + prev = event_data[i]; + last = now; + vpe_client_registration_t *reg; + /* *INDENT-OFF* */ + pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations, + ({ + unix_shared_memory_queue_t *q; + q = vl_api_client_index_to_input_queue (reg->client_index); + if (q && q->cursize < q->maxsize) + { + vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event); + memset (event, 0, sizeof *event); + event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT); + event->client_index = reg->client_index; + event->pid = reg->client_pid; + event->mac_ip = 1; + event->address = event_data[i].ip4; + event->sw_if_index = htonl(event_data[i].sw_if_index); + memcpy(event->new_mac, event_data[i].mac, sizeof event->new_mac); + vl_msg_api_send_shmem (q, (u8 *) &event); + } + })); + /* *INDENT-ON* */ + } + vlib_process_put_event_data (vm, event_data); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (wc_ip4_arp_process_node,static) = { + .function = wc_ip4_arp_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "wildcard-ip4-arp-publisher-process", +}; +/* *INDENT-ON* */ + static void vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) { vpe_api_main_t *am = &vpe_api_main; vnet_main_t *vnm = vnet_get_main (); vl_api_want_ip4_arp_events_reply_t *rmp; - int rv; + int rv = 0; + + if (mp->address == 0) + { + uword *p = + hash_get (am->wc_ip4_arp_events_registration_hash, mp->client_index); + vpe_client_registration_t *rp; + if (p) + { + if (mp->enable_disable) + { + clib_warning ("pid %d: already enabled...", mp->pid); + rv = VNET_API_ERROR_INVALID_REGISTRATION; + goto reply; + } + else + { + rp = + pool_elt_at_index (am->wc_ip4_arp_events_registrations, p[0]); + pool_put (am->wc_ip4_arp_events_registrations, rp); + hash_unset (am->wc_ip4_arp_events_registration_hash, + mp->client_index); + if (pool_elts (am->wc_ip4_arp_events_registrations) == 0) + wc_arp_set_publisher_node (~0); + goto reply; + } + } + if (mp->enable_disable == 0) + { + clib_warning ("pid %d: already disabled...", mp->pid); + rv = VNET_API_ERROR_INVALID_REGISTRATION; + goto reply; + } + pool_get (am->wc_ip4_arp_events_registrations, rp); + rp->client_index = mp->client_index; + rp->client_pid = mp->pid; + hash_set (am->wc_ip4_arp_events_registration_hash, rp->client_index, + rp - am->wc_ip4_arp_events_registrations); + wc_arp_set_publisher_node (wc_ip4_arp_process_node.index); + goto reply; + } if (mp->enable_disable) { @@ -1459,12 +1558,12 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) if (rv) { pool_put (am->arp_events, event); - goto out; + goto reply; } memset (event, 0, sizeof (*event)); /* Python API expects events to have no context */ - event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT); + event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT); event->client_index = mp->client_index; event->address = mp->address; event->pid = mp->pid; @@ -1479,7 +1578,7 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) vpe_resolver_process_node.index, IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ ); } -out: +reply: REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY); } @@ -2072,13 +2171,10 @@ vpe_api_init (vlib_main_t * vm) am->vlib_main = vm; am->vnet_main = vnet_get_main (); - am->interface_events_registration_hash = hash_create (0, sizeof (uword)); - am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword)); - am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword)); - am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword)); - am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword)); - am->oam_events_registration_hash = hash_create (0, sizeof (uword)); - am->bfd_events_registration_hash = hash_create (0, sizeof (uword)); +#define _(a) \ + am->a##_registration_hash = hash_create (0, sizeof (uword)); + foreach_registration_hash; +#undef _ vl_set_memory_region_name ("/vpe-api"); vl_enable_disable_memory_api (vm, 1 /* enable it */ ); @@ -2219,10 +2315,7 @@ format_arp_event (u8 * s, va_list * args) vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *); s = format (s, "pid %d: ", ntohl (event->pid)); - if (event->mac_ip) - s = format (s, "bd mac/ip4 binding events"); - else - s = format (s, "resolution for %U", format_ip4_address, &event->address); + s = format (s, "resolution for %U", format_ip4_address, &event->address); return s; } @@ -2259,6 +2352,13 @@ show_ip_arp_nd_events_fn (vlib_main_t * vm, vlib_cli_output (vm, "%U", format_arp_event, arp_event); })); + vpe_client_registration_t *reg; + pool_foreach(reg, am->wc_ip4_arp_events_registrations, + ({ + vlib_cli_output (vm, "pid %d: bd mac/ip4 binding events", + ntohl (reg->client_pid)); + })); + pool_foreach (nd_event, am->nd_events, ({ vlib_cli_output (vm, "%U", format_nd_event, nd_event); diff --git a/test/test_l2bd_arp_term.py b/test/test_l2bd_arp_term.py index 80a7ff84..20885f88 100644 --- a/test/test_l2bd_arp_term.py +++ b/test/test_l2bd_arp_term.py @@ -5,7 +5,7 @@ import unittest import random import copy -from socket import AF_INET6 +from socket import AF_INET, AF_INET6 from scapy.packet import Raw from scapy.layers.l2 import Ether, ARP @@ -117,7 +117,7 @@ class TestL2bdArpTerm(VppTestCase): self.vapi.bridge_domain_add_del(bd_id=bd_id, is_add=is_add) @classmethod - def arp(cls, src_host, host): + def arp_req(cls, src_host, host): return (Ether(dst="ff:ff:ff:ff:ff:ff", src=src_host.mac) / ARP(op="who-has", hwsrc=src_host.bin_mac, @@ -126,7 +126,15 @@ class TestL2bdArpTerm(VppTestCase): @classmethod def arp_reqs(cls, src_host, entries): - return [cls.arp(src_host, e) for e in entries] + return [cls.arp_req(src_host, e) for e in entries] + + @classmethod + def garp_req(cls, host): + return cls.arp_req(host, host) + + @classmethod + def garp_reqs(cls, entries): + return [cls.garp_req(e) for e in entries] def arp_resp_host(self, src_host, arp_resp): ether = arp_resp[Ether] @@ -146,6 +154,20 @@ class TestL2bdArpTerm(VppTestCase): def arp_resp_hosts(self, src_host, pkts): return {self.arp_resp_host(src_host, p) for p in pkts} + def inttoip4(self, ip): + o1 = int(ip / 16777216) % 256 + o2 = int(ip / 65536) % 256 + o3 = int(ip / 256) % 256 + o4 = int(ip) % 256 + return '%(o1)s.%(o2)s.%(o3)s.%(o4)s' % locals() + + def arp_event_host(self, e): + return Host(mac=':'.join(['%02x' % ord(char) for char in e.new_mac]), + ip4=self.inttoip4(e.address)) + + def arp_event_hosts(self, evs): + return {self.arp_event_host(e) for e in evs} + @classmethod def ns_req(cls, src_host, host): nsma = in6_getnsma(inet_pton(AF_INET6, "fd10::ffff")) @@ -347,6 +369,60 @@ class TestL2bdArpTerm(VppTestCase): self.verify_nd(src_host, hosts, updated) self.bd_add_del(1, is_add=0) + def test_l2bd_arp_term_09(self): + """ L2BD arp term - send garps, verify arp event reports + """ + self.vapi.want_ip4_arp_events() + self.bd_add_del(1, is_add=1) + self.set_bd_flags(1, arp_term=True, flood=False, + uu_flood=False, learn=False) + macs = self.mac_list(range(90, 95)) + hosts = self.ip4_hosts(5, 1, macs) + + garps = self.garp_reqs(hosts) + self.bd_swifs(1)[0].add_stream(garps) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + evs = [self.vapi.wait_for_event(1, "ip4_arp_event") + for i in range(len(hosts))] + ev_hosts = self.arp_event_hosts(evs) + self.assertEqual(len(ev_hosts ^ hosts), 0) + + def test_l2bd_arp_term_10(self): + """ L2BD arp term - send duplicate garps, verify suppression + """ + macs = self.mac_list(range(70, 71)) + hosts = self.ip4_hosts(6, 1, macs) + + """ send the packet 5 times expect one event + """ + garps = self.garp_reqs(hosts) * 5 + self.bd_swifs(1)[0].add_stream(garps) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + evs = [self.vapi.wait_for_event(1, "ip4_arp_event") + for i in range(len(hosts))] + ev_hosts = self.arp_event_hosts(evs) + self.assertEqual(len(ev_hosts ^ hosts), 0) + + def test_l2bd_arp_term_11(self): + """ L2BD arp term - disable ip4 arp events,send garps, verify no events + """ + self.vapi.want_ip4_arp_events(enable_disable=0) + macs = self.mac_list(range(90, 95)) + hosts = self.ip4_hosts(5, 1, macs) + + garps = self.garp_reqs(hosts) + self.bd_swifs(1)[0].add_stream(garps) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.sleep(1) + self.assertEqual(len(self.vapi.collect_events()), 0) + self.bd_add_del(1, is_add=0) + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index b63a2658..fcc67849 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -101,11 +101,11 @@ class VppPapiProvider(object): def wait_for_event(self, timeout, name=None): """ Wait for and return next event. """ if name: - self.test_class.logger.debug("Expecting event within %ss", - timeout) - else: self.test_class.logger.debug("Expecting event '%s' within %ss", name, timeout) + else: + self.test_class.logger.debug("Expecting event within %ss", + timeout) if self._events: self.test_class.logger.debug("Not waiting, event already queued") limit = time.time() + timeout @@ -419,6 +419,12 @@ class VppPapiProvider(object): 'ip_address': ip, 'mac_address': mac}) + def want_ip4_arp_events(self, enable_disable=1, address=0): + return self.api(self.papi.want_ip4_arp_events, + {'enable_disable': enable_disable, + 'address': address, + 'pid': os.getpid(), }) + def l2fib_add_del(self, mac, bd_id, sw_if_index, is_add=1, static_mac=0, filter_mac=0, bvi_mac=0): """Create/delete L2 FIB entry. -- cgit 1.2.3-korg From c125eccc10db9c0b9c5d161d3ad20b4fc8c69b26 Mon Sep 17 00:00:00 2001 From: Eyal Bari Date: Wed, 20 Sep 2017 11:29:17 +0300 Subject: IP-MAC,ND:wildcard events,fix sending multiple events wildcard ND events publisher was sending the last event mutiple times Change-Id: I6c30f2de03fa825e79df9005a3cfaaf68ff7ea2f Signed-off-by: Eyal Bari --- src/vlibapi/api_helper_macros.h | 1 + src/vnet/ethernet/arp.c | 12 ++- src/vnet/ethernet/ethernet.h | 2 +- src/vnet/ip/ip6_neighbor.c | 73 +++++++++---- src/vnet/ip/ip6_neighbor.h | 8 ++ src/vpp/api/api.c | 221 ++++++++++++++++++++++++++-------------- test/test_l2bd_arp_term.py | 68 ++++++++++++- test/vpp_papi_provider.py | 6 ++ 8 files changed, 288 insertions(+), 103 deletions(-) (limited to 'src/vlibapi/api_helper_macros.h') diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index 13734896..052cc6e7 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -216,6 +216,7 @@ _(to_netconf_client) \ _(from_netconf_client) \ _(oam_events) \ _(bfd_events) \ +_(wc_ip6_nd_events) \ _(wc_ip4_arp_events) typedef struct diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index 2f3aa6c7..e974d255 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -94,6 +94,7 @@ typedef struct ethernet_proxy_arp_t *proxy_arps; uword wc_ip4_arp_publisher_node; + uword wc_ip4_arp_publisher_et; } ethernet_arp_main_t; static ethernet_arp_main_t ethernet_arp_main; @@ -1536,21 +1537,24 @@ vnet_arp_wc_publish_internal (vnet_main_t * vnm, { vlib_main_t *vm = vlib_get_main (); ethernet_arp_main_t *am = ðernet_arp_main; - if (am->wc_ip4_arp_publisher_node == (uword) ~ 0) + uword ni = am->wc_ip4_arp_publisher_node; + uword et = am->wc_ip4_arp_publisher_et; + + if (ni == (uword) ~ 0) return; wc_arp_report_t *r = - vlib_process_signal_event_data (vm, am->wc_ip4_arp_publisher_node, 1, 1, - sizeof *r); + vlib_process_signal_event_data (vm, ni, et, 1, sizeof *r); r->ip4 = args->a.ip4.as_u32; r->sw_if_index = args->sw_if_index; memcpy (r->mac, args->a.ethernet, sizeof r->mac); } void -wc_arp_set_publisher_node (uword node_index) +wc_arp_set_publisher_node (uword node_index, uword event_type) { ethernet_arp_main_t *am = ðernet_arp_main; am->wc_ip4_arp_publisher_node = node_index; + am->wc_ip4_arp_publisher_et = event_type; } /* diff --git a/src/vnet/ethernet/ethernet.h b/src/vnet/ethernet/ethernet.h index 1a9e9790..a6846b13 100644 --- a/src/vnet/ethernet/ethernet.h +++ b/src/vnet/ethernet/ethernet.h @@ -543,7 +543,7 @@ int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm, uword type_opaque, uword data, int is_add); -void wc_arp_set_publisher_node (uword inode_index); +void wc_arp_set_publisher_node (uword inode_index, uword event_type); void ethernet_arp_change_mac (u32 sw_if_index); void ethernet_ndp_change_mac (u32 sw_if_index); diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 345ebd34..1908a679 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -195,6 +195,9 @@ typedef struct u32 limit_neighbor_cache_size; u32 neighbor_delete_rotor; + /* Wildcard nd report publisher */ + uword wc_ip6_nd_publisher_node; + uword wc_ip6_nd_publisher_et; } ip6_neighbor_main_t; /* ipv6 neighbor discovery - timer/event types */ @@ -216,6 +219,50 @@ typedef union static ip6_neighbor_main_t ip6_neighbor_main; static ip6_address_t ip6a_zero; /* ip6 address 0 */ +static void wc_nd_signal_report (wc_nd_report_t * r); + +/** + * @brief publish wildcard arp event + * @param sw_if_index The interface on which the ARP entires are acted + */ +static int +vnet_nd_wc_publish (u32 sw_if_index, u8 * mac, ip6_address_t * ip6) +{ + wc_nd_report_t r = { + .sw_if_index = sw_if_index, + .ip6 = *ip6, + }; + memcpy (r.mac, mac, sizeof r.mac); + + void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); + vl_api_rpc_call_main_thread (wc_nd_signal_report, (u8 *) & r, sizeof r); + return 0; +} + +static void +wc_nd_signal_report (wc_nd_report_t * r) +{ + vlib_main_t *vm = vlib_get_main (); + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + uword ni = nm->wc_ip6_nd_publisher_node; + uword et = nm->wc_ip6_nd_publisher_et; + + if (ni == (uword) ~ 0) + return; + wc_nd_report_t *q = + vlib_process_signal_event_data (vm, ni, et, 1, sizeof *q); + + *q = *r; +} + +void +wc_nd_set_publisher_node (uword node_index, uword event_type) +{ + ip6_neighbor_main_t *nm = &ip6_neighbor_main; + nm->wc_ip6_nd_publisher_node = node_index; + nm->wc_ip6_nd_publisher_et = event_type; +} + static u8 * format_ip6_neighbor_ip6_entry (u8 * s, va_list * va) { @@ -3931,6 +3978,8 @@ ip6_neighbor_init (vlib_main_t * vm) /* default, configurable */ nm->limit_neighbor_cache_size = 50000; + nm->wc_ip6_nd_publisher_node = (uword) ~ 0; + #if 0 /* $$$$ Hack fix for today */ vec_validate_init_empty @@ -4047,7 +4096,6 @@ vnet_ip6_nd_term (vlib_main_t * vm, { ip6_neighbor_main_t *nm = &ip6_neighbor_main; icmp6_neighbor_solicitation_or_advertisement_header_t *ndh; - pending_resolution_t *mc; ndh = ip6_next_header (ip); if (ndh->icmp.type != ICMP6_neighbor_solicitation && @@ -4063,26 +4111,11 @@ vnet_ip6_nd_term (vlib_main_t * vm, } /* Check if anyone want ND events for L2 BDs */ - uword *p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero); - if (p && !ip6_address_is_link_local_unicast (&ip->src_address)) + if (PREDICT_FALSE + (nm->wc_ip6_nd_publisher_node != (uword) ~ 0 + && !ip6_address_is_link_local_unicast (&ip->src_address))) { - u32 next_index = p[0]; - while (next_index != (u32) ~ 0) - { - int (*fp) (u32, u8 *, u32, ip6_address_t *); - int rv = 1; - mc = pool_elt_at_index (nm->mac_changes, next_index); - fp = mc->data_callback; - /* Call the callback, return 1 to suppress dup events */ - if (fp) - rv = (*fp) (mc->data, - eth->src_address, sw_if_index, &ip->src_address); - /* Signal the resolver process */ - if (rv == 0) - vlib_process_signal_event (vm, mc->node_index, - mc->type_opaque, mc->data); - next_index = mc->next_index; - } + vnet_nd_wc_publish (sw_if_index, eth->src_address, &ip->src_address); } /* Check if MAC entry exsist for solicited target IP */ diff --git a/src/vnet/ip/ip6_neighbor.h b/src/vnet/ip/ip6_neighbor.h index 0e302ed4..ed80381b 100644 --- a/src/vnet/ip/ip6_neighbor.h +++ b/src/vnet/ip/ip6_neighbor.h @@ -89,6 +89,14 @@ extern int ip6_neighbor_proxy_add_del (u32 sw_if_index, u32 ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add); +typedef struct +{ + u32 sw_if_index; + ip6_address_t ip6; + u8 mac[6]; +} wc_nd_report_t; + +void wc_nd_set_publisher_node (uword node_index, uword event_type); #endif /* included_ip6_neighbor_h */ diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index e229a5e3..d020314b 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -1345,8 +1345,6 @@ arp_change_data_callback (u32 pool_index, u8 * new_mac, vpe_api_main_t *am = &vpe_api_main; vlib_main_t *vm = am->vlib_main; vl_api_ip4_arp_event_t *event; - static f64 arp_event_last_time; - f64 now = vlib_time_now (vm); if (pool_is_free_index (am->arp_events, pool_index)) return 1; @@ -1360,7 +1358,6 @@ arp_change_data_callback (u32 pool_index, u8 * new_mac, clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); event->sw_if_index = htonl (sw_if_index); - arp_event_last_time = now; return 0; } @@ -1371,35 +1368,19 @@ nd_change_data_callback (u32 pool_index, u8 * new_mac, vpe_api_main_t *am = &vpe_api_main; vlib_main_t *vm = am->vlib_main; vl_api_ip6_nd_event_t *event; - static f64 nd_event_last_time; - f64 now = vlib_time_now (vm); if (pool_is_free_index (am->nd_events, pool_index)) return 1; event = pool_elt_at_index (am->nd_events, pool_index); - - /* *INDENT-OFF* */ - if (memcmp (event->new_mac, new_mac, sizeof (event->new_mac))) + if (eth_mac_equal (event->new_mac, new_mac) && + sw_if_index == ntohl (event->sw_if_index)) { - clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); - } - else - { /* same mac */ - if (sw_if_index == ntohl(event->sw_if_index) && - (!event->mac_ip || - /* for BD case, also check IP address with 10 sec timeout */ - (ip6_address_is_equal (address, - (ip6_address_t *) event->address) && - (now - nd_event_last_time) < 10.0))) - return 1; + return 1; } - /* *INDENT-ON* */ - nd_event_last_time = now; + clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac)); event->sw_if_index = htonl (sw_if_index); - if (event->mac_ip) - clib_memcpy (event->address, address, sizeof (event->address)); return 0; } @@ -1427,61 +1408,107 @@ nd_change_delete_callback (u32 pool_index, u8 * notused) return 0; } -static vlib_node_registration_t wc_ip4_arp_process_node; +static vlib_node_registration_t wc_arp_process_node; + +enum +{ WC_ARP_REPORT, WC_ND_REPORT }; static uword -wc_ip4_arp_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, vlib_frame_t * f) +wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) { /* These cross the longjmp boundry (vlib_process_wait_for_event) * and need to be volatile - to prevent them from being optimized into * a register - which could change during suspension */ - volatile wc_arp_report_t prev = { 0 }; - volatile f64 last = vlib_time_now (vm); + volatile wc_arp_report_t arp_prev = { 0 }; + volatile wc_nd_report_t nd_prev = { 0 }; + volatile f64 last_arp = vlib_time_now (vm); + volatile f64 last_nd = vlib_time_now (vm); while (1) { vlib_process_wait_for_event (vm); uword event_type; - wc_arp_report_t *event_data = - vlib_process_get_event_data (vm, &event_type); + void *event_data = vlib_process_get_event_data (vm, &event_type); f64 now = vlib_time_now (vm); int i; - for (i = 0; i < vec_len (event_data); i++) + if (event_type == WC_ARP_REPORT) + { + wc_arp_report_t *arp_events = event_data; + for (i = 0; i < vec_len (arp_events); i++) + { + /* discard dup event */ + if (arp_prev.ip4 == arp_events[i].ip4 && + eth_mac_equal ((u8 *) arp_prev.mac, arp_events[i].mac) && + arp_prev.sw_if_index == arp_events[i].sw_if_index && + (now - last_arp) < 10.0) + { + continue; + } + arp_prev = arp_events[i]; + last_arp = now; + vpe_client_registration_t *reg; + /* *INDENT-OFF* */ + pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations, + ({ + unix_shared_memory_queue_t *q; + q = vl_api_client_index_to_input_queue (reg->client_index); + if (q && q->cursize < q->maxsize) + { + vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event); + memset (event, 0, sizeof *event); + event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT); + event->client_index = reg->client_index; + event->pid = reg->client_pid; + event->mac_ip = 1; + event->address = arp_events[i].ip4; + event->sw_if_index = htonl(arp_events[i].sw_if_index); + memcpy(event->new_mac, arp_events[i].mac, sizeof event->new_mac); + vl_msg_api_send_shmem (q, (u8 *) &event); + } + })); + /* *INDENT-ON* */ + } + } + else if (event_type == WC_ND_REPORT) { - /* discard dup event */ - if (prev.ip4 == event_data[i].ip4 && - eth_mac_equal ((u8 *) prev.mac, event_data[i].mac) && - prev.sw_if_index == event_data[i].sw_if_index && - (now - last) < 10.0) + wc_nd_report_t *nd_events = event_data; + for (i = 0; i < vec_len (nd_events); i++) { - continue; + /* discard dup event */ + if (ip6_address_is_equal + ((ip6_address_t *) & nd_prev.ip6, &nd_events[i].ip6) + && eth_mac_equal ((u8 *) nd_prev.mac, nd_events[i].mac) + && nd_prev.sw_if_index == nd_events[i].sw_if_index + && (now - last_nd) < 10.0) + { + continue; + } + nd_prev = nd_events[i]; + last_nd = now; + vpe_client_registration_t *reg; + /* *INDENT-OFF* */ + pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations, + ({ + unix_shared_memory_queue_t *q; + q = vl_api_client_index_to_input_queue (reg->client_index); + if (q && q->cursize < q->maxsize) + { + vl_api_ip6_nd_event_t * event = vl_msg_api_alloc (sizeof *event); + memset (event, 0, sizeof *event); + event->_vl_msg_id = htons (VL_API_IP6_ND_EVENT); + event->client_index = reg->client_index; + event->pid = reg->client_pid; + event->mac_ip = 1; + memcpy(event->address, nd_events[i].ip6.as_u8, sizeof event->address); + event->sw_if_index = htonl(nd_events[i].sw_if_index); + memcpy(event->new_mac, nd_events[i].mac, sizeof event->new_mac); + vl_msg_api_send_shmem (q, (u8 *) &event); + } + })); + /* *INDENT-ON* */ } - prev = event_data[i]; - last = now; - vpe_client_registration_t *reg; - /* *INDENT-OFF* */ - pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations, - ({ - unix_shared_memory_queue_t *q; - q = vl_api_client_index_to_input_queue (reg->client_index); - if (q && q->cursize < q->maxsize) - { - vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event); - memset (event, 0, sizeof *event); - event->_vl_msg_id = htons (VL_API_IP4_ARP_EVENT); - event->client_index = reg->client_index; - event->pid = reg->client_pid; - event->mac_ip = 1; - event->address = event_data[i].ip4; - event->sw_if_index = htonl(event_data[i].sw_if_index); - memcpy(event->new_mac, event_data[i].mac, sizeof event->new_mac); - vl_msg_api_send_shmem (q, (u8 *) &event); - } - })); - /* *INDENT-ON* */ } vlib_process_put_event_data (vm, event_data); } @@ -1490,8 +1517,8 @@ wc_ip4_arp_process (vlib_main_t * vm, } /* *INDENT-OFF* */ -VLIB_REGISTER_NODE (wc_ip4_arp_process_node,static) = { - .function = wc_ip4_arp_process, +VLIB_REGISTER_NODE (wc_arp_process_node,static) = { + .function = wc_arp_process, .type = VLIB_NODE_TYPE_PROCESS, .name = "wildcard-ip4-arp-publisher-process", }; @@ -1526,7 +1553,7 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) hash_unset (am->wc_ip4_arp_events_registration_hash, mp->client_index); if (pool_elts (am->wc_ip4_arp_events_registrations) == 0) - wc_arp_set_publisher_node (~0); + wc_arp_set_publisher_node (~0, WC_ARP_REPORT); goto reply; } } @@ -1541,7 +1568,7 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp) rp->client_pid = mp->pid; hash_set (am->wc_ip4_arp_events_registration_hash, rp->client_index, rp - am->wc_ip4_arp_events_registrations); - wc_arp_set_publisher_node (wc_ip4_arp_process_node.index); + wc_arp_set_publisher_node (wc_arp_process_node.index, WC_ARP_REPORT); goto reply; } @@ -1588,7 +1615,47 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp) vpe_api_main_t *am = &vpe_api_main; vnet_main_t *vnm = vnet_get_main (); vl_api_want_ip6_nd_events_reply_t *rmp; - int rv; + int rv = 0; + + if (ip6_address_is_zero ((ip6_address_t *) mp->address)) + { + uword *p = + hash_get (am->wc_ip6_nd_events_registration_hash, mp->client_index); + vpe_client_registration_t *rp; + if (p) + { + if (mp->enable_disable) + { + clib_warning ("pid %d: already enabled...", mp->pid); + rv = VNET_API_ERROR_INVALID_REGISTRATION; + goto reply; + } + else + { + rp = + pool_elt_at_index (am->wc_ip6_nd_events_registrations, p[0]); + pool_put (am->wc_ip6_nd_events_registrations, rp); + hash_unset (am->wc_ip6_nd_events_registration_hash, + mp->client_index); + if (pool_elts (am->wc_ip6_nd_events_registrations) == 0) + wc_nd_set_publisher_node (~0, 2); + goto reply; + } + } + if (mp->enable_disable == 0) + { + clib_warning ("pid %d: already disabled...", mp->pid); + rv = VNET_API_ERROR_INVALID_REGISTRATION; + goto reply; + } + pool_get (am->wc_ip6_nd_events_registrations, rp); + rp->client_index = mp->client_index; + rp->client_pid = mp->pid; + hash_set (am->wc_ip6_nd_events_registration_hash, rp->client_index, + rp - am->wc_ip6_nd_events_registrations); + wc_nd_set_publisher_node (wc_arp_process_node.index, WC_ND_REPORT); + goto reply; + } if (mp->enable_disable) { @@ -1604,17 +1671,14 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp) if (rv) { pool_put (am->nd_events, event); - goto out; + goto reply; } memset (event, 0, sizeof (*event)); event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT); event->client_index = mp->client_index; - clib_memcpy (event->address, mp->address, 16); + clib_memcpy (event->address, mp->address, sizeof event->address); event->pid = mp->pid; - if (ip6_address_is_zero ((ip6_address_t *) mp->address)) - event->mac_ip = 1; - } else { @@ -1624,7 +1688,7 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp) vpe_resolver_process_node.index, IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ ); } -out: +reply: REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY); } @@ -2325,10 +2389,7 @@ format_nd_event (u8 * s, va_list * args) vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *); s = format (s, "pid %d: ", ntohl (event->pid)); - if (event->mac_ip) - s = format (s, "bd mac/ip6 binding events"); - else - s = format (s, "resolution for %U", format_ip6_address, event->address); + s = format (s, "resolution for %U", format_ip6_address, event->address); return s; } @@ -2340,7 +2401,9 @@ show_ip_arp_nd_events_fn (vlib_main_t * vm, vl_api_ip4_arp_event_t *arp_event; vl_api_ip6_nd_event_t *nd_event; - if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0)) + if (pool_elts (am->arp_events) == 0 && pool_elts (am->nd_events) == 0 && + pool_elts (am->wc_ip4_arp_events_registrations) == 0 && + pool_elts (am->wc_ip6_nd_events_registrations) == 0) { vlib_cli_output (vm, "No active arp or nd event registrations"); return 0; @@ -2363,6 +2426,12 @@ show_ip_arp_nd_events_fn (vlib_main_t * vm, ({ vlib_cli_output (vm, "%U", format_nd_event, nd_event); })); + + pool_foreach(reg, am->wc_ip6_nd_events_registrations, + ({ + vlib_cli_output (vm, "pid %d: bd mac/ip6 binding events", + ntohl (reg->client_pid)); + })); /* *INDENT-ON* */ return 0; diff --git a/test/test_l2bd_arp_term.py b/test/test_l2bd_arp_term.py index 20885f88..20cc537e 100644 --- a/test/test_l2bd_arp_term.py +++ b/test/test_l2bd_arp_term.py @@ -168,6 +168,13 @@ class TestL2bdArpTerm(VppTestCase): def arp_event_hosts(self, evs): return {self.arp_event_host(e) for e in evs} + def nd_event_host(self, e): + return Host(mac=':'.join(['%02x' % ord(char) for char in e.new_mac]), + ip6=inet_ntop(AF_INET6, e.address)) + + def nd_event_hosts(self, evs): + return {self.nd_event_host(e) for e in evs} + @classmethod def ns_req(cls, src_host, host): nsma = in6_getnsma(inet_pton(AF_INET6, "fd10::ffff")) @@ -178,7 +185,11 @@ class TestL2bdArpTerm(VppTestCase): ICMPv6NDOptSrcLLAddr(lladdr=src_host.mac)) @classmethod - def ns_reqs(cls, src_host, entries): + def ns_reqs_dst(cls, entries, dst_host): + return [cls.ns_req(e, dst_host) for e in entries] + + @classmethod + def ns_reqs_src(cls, src_host, entries): return [cls.ns_req(src_host, e) for e in entries] def na_resp_host(self, src_host, rx): @@ -237,7 +248,7 @@ class TestL2bdArpTerm(VppTestCase): self.assertEqual(len(resps ^ resp_hosts), 0) def verify_nd(self, src_host, req_hosts, resp_hosts, bd_id=1): - reqs = self.ns_reqs(src_host, req_hosts) + reqs = self.ns_reqs_src(src_host, req_hosts) for swif in self.bd_swifs(bd_id): swif.add_stream(reqs) @@ -423,6 +434,59 @@ class TestL2bdArpTerm(VppTestCase): self.assertEqual(len(self.vapi.collect_events()), 0) self.bd_add_del(1, is_add=0) + def test_l2bd_arp_term_12(self): + """ L2BD ND term - send NS packets verify reports + """ + self.vapi.want_ip6_nd_events(address=inet_pton(AF_INET6, "::0")) + dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44") + self.bd_add_del(1, is_add=1) + self.set_bd_flags(1, arp_term=True, flood=False, + uu_flood=False, learn=False) + macs = self.mac_list(range(10, 15)) + hosts = self.ip6_hosts(5, 1, macs) + reqs = self.ns_reqs_dst(hosts, dst_host) + self.bd_swifs(1)[0].add_stream(reqs) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + evs = [self.vapi.wait_for_event(2, "ip6_nd_event") + for i in range(len(hosts))] + ev_hosts = self.nd_event_hosts(evs) + self.assertEqual(len(ev_hosts ^ hosts), 0) + + def test_l2bd_arp_term_13(self): + """ L2BD ND term - send duplicate ns, verify suppression + """ + dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44") + macs = self.mac_list(range(10, 11)) + hosts = self.ip6_hosts(5, 1, macs) + reqs = self.ns_reqs_dst(hosts, dst_host) * 5 + self.bd_swifs(1)[0].add_stream(reqs) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + evs = [self.vapi.wait_for_event(2, "ip6_nd_event") + for i in range(len(hosts))] + ev_hosts = self.nd_event_hosts(evs) + self.assertEqual(len(ev_hosts ^ hosts), 0) + + def test_l2bd_arp_term_14(self): + """ L2BD ND term - disable ip4 arp events,send ns, verify no events + """ + self.vapi.want_ip6_nd_events(enable_disable=0, + address=inet_pton(AF_INET6, "::0")) + dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44") + macs = self.mac_list(range(10, 15)) + hosts = self.ip6_hosts(5, 1, macs) + reqs = self.ns_reqs_dst(hosts, dst_host) + self.bd_swifs(1)[0].add_stream(reqs) + + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.sleep(1) + self.assertEqual(len(self.vapi.collect_events()), 0) + self.bd_add_del(1, is_add=0) + if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index fcc67849..71e7aea1 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -425,6 +425,12 @@ class VppPapiProvider(object): 'address': address, 'pid': os.getpid(), }) + def want_ip6_nd_events(self, enable_disable=1, address=0): + return self.api(self.papi.want_ip6_nd_events, + {'enable_disable': enable_disable, + 'address': address, + 'pid': os.getpid(), }) + def l2fib_add_del(self, mac, bd_id, sw_if_index, is_add=1, static_mac=0, filter_mac=0, bvi_mac=0): """Create/delete L2 FIB entry. -- cgit 1.2.3-korg