From: Ole Troan Date: Thu, 14 Jun 2018 12:42:14 +0000 (+0200) Subject: STATS: Separate socket for fd exchange. X-Git-Tag: v18.07-rc1~165 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=e906aacc1089ce86158486ec52d37a8470359ec2 STATS: Separate socket for fd exchange. stats { interval socket-name | default } Where the default socket is in /run/vpp/stats.sock Change-Id: Idd501b328c662804d4ccd58034b0ea6b8aa1f89a Signed-off-by: Ole Troan --- diff --git a/src/vat/api_format.c b/src/vat/api_format.c index b9f08048651..f2d10b78de5 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -5930,8 +5930,7 @@ _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \ _(SESSION_RULES_DETAILS, session_rules_details) \ _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply) \ _(OUTPUT_ACL_SET_INTERFACE_REPLY, output_acl_set_interface_reply) \ -_(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply) \ -_(MAP_STATS_SEGMENT_REPLY, map_stats_segment_reply) +_(QOS_RECORD_ENABLE_DISABLE_REPLY, qos_record_enable_disable_reply) #define foreach_standalone_reply_msg \ _(SW_INTERFACE_EVENT, sw_interface_event) \ @@ -22531,92 +22530,6 @@ api_app_namespace_add_del (vat_main_t * vam) return ret; } -static void vl_api_map_stats_segment_reply_t_handler - (vl_api_map_stats_segment_reply_t * mp) -{ -#if VPP_API_TEST_BUILTIN == 0 - vat_main_t *vam = &vat_main; - ssvm_private_t *ssvmp = &vam->stat_segment; - ssvm_shared_header_t *shared_header; - socket_client_main_t *scm = vam->socket_client_main; - int rv = ntohl (mp->retval); - int my_fd, retval; - clib_error_t *error; - - vam->retval = rv; - - if (rv != 0) - { - vam->result_ready = 1; - return; - } - - /* - * Check the socket for the magic fd - */ - error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 5); - if (error) - { - clib_error_report (error); - vam->retval = -99; - vam->result_ready = 1; - return; - } - - memset (ssvmp, 0, sizeof (*ssvmp)); - ssvmp->fd = my_fd; - - /* Note: this closes memfd.fd */ - retval = ssvm_slave_init_memfd (ssvmp); - if (retval) - { - clib_warning ("WARNING: segment map returned %d", retval); - vam->retval = -99; - vam->result_ready = 1; - return; - } - else - errmsg ("stat segment mapped OK..."); - - ASSERT (ssvmp && ssvmp->sh); - - /* Pick up the segment lock from the shared memory header */ - shared_header = ssvmp->sh; - vam->stat_segment_lockp = (clib_spinlock_t *) (shared_header->opaque[0]); - vam->retval = 0; - vam->result_ready = 1; -#endif -} - -static void vl_api_map_stats_segment_reply_t_handler_json - (vl_api_map_stats_segment_reply_t * mp) -{ -#if VPP_API_TEST_BUILTIN == 0 - vat_main_t *vam = &vat_main; - clib_warning ("not implemented"); - vam->retval = -99; - vam->result_ready = 1; -#endif -} - -static int -api_map_stats_segment (vat_main_t * vam) -{ -#if VPP_API_TEST_BUILTIN == 0 - vl_api_map_stats_segment_t *mp; - int ret; - - M (MAP_STATS_SEGMENT, mp); - S (mp); - W (ret); - - return ret; -#else - errmsg ("api unavailable"); - return -99; -#endif -} - static int api_sock_init_shm (vat_main_t * vam) { @@ -24063,8 +23976,7 @@ _(ip_container_proxy_add_del, "[add|del]
") \ _(output_acl_set_interface, \ " | sw_if_index [ip4-table ] [ip6-table ]\n" \ " [l2-table ] [del]") \ -_(qos_record_enable_disable, " | sw_if_index [disable]") \ -_(map_stats_segment, "") +_(qos_record_enable_disable, " | sw_if_index [disable]") /* List of command functions, CLI names map directly to functions */ #define foreach_cli_function \ diff --git a/src/vpp/app/stat_client.c b/src/vpp/app/stat_client.c index b3dee5331ca..0ee78d200af 100644 --- a/src/vpp/app/stat_client.c +++ b/src/vpp/app/stat_client.c @@ -1,6 +1,6 @@ /* *------------------------------------------------------------------ - * api_format.c + * stat_client.c * * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,60 +19,42 @@ #include -#include - -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs - -#define vl_endianfun /* define endian fcns */ -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) fformat (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - stat_client_main_t stat_client_main; -static void vl_api_map_stats_segment_reply_t_handler - (vl_api_map_stats_segment_reply_t * mp) +static int +stat_segment_connect (stat_client_main_t * sm) { - stat_client_main_t *sm = &stat_client_main; ssvm_private_t *ssvmp = &sm->stat_segment; ssvm_shared_header_t *shared_header; - socket_client_main_t *scm = sm->socket_client_main; - int rv = ntohl (mp->retval); - int my_fd, retval; - clib_error_t *error; - - if (rv != 0) + clib_socket_t s = { 0 }; + clib_error_t *err; + int fd = -1, retval; + + s.config = (char *) sm->socket_name; + s.flags = CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET; + err = clib_socket_init (&s); + if (err) { - fformat (stderr, "ERROR mapping stats segment: %d", rv); + clib_error_report (err); exit (1); } - - /* - * Check the socket for the magic fd - */ - error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 5); - if (error) + err = clib_socket_recvmsg (&s, 0, 0, &fd, 1); + if (err) { - clib_error_report (error); - exit (1); + clib_error_report (err); + return -1; } + clib_socket_close (&s); memset (ssvmp, 0, sizeof (*ssvmp)); - ssvmp->fd = my_fd; + ssvmp->fd = fd; /* Note: this closes memfd.fd */ retval = ssvm_slave_init_memfd (ssvmp); if (retval) { clib_warning ("WARNING: segment map returned %d", retval); - exit (1); + return -1; } fformat (stdout, "Stat segment mapped OK...\n"); @@ -84,60 +66,6 @@ static void vl_api_map_stats_segment_reply_t_handler sm->stat_segment_lockp = (clib_spinlock_t *) (shared_header->opaque[0]); sm->segment_ready = 1; - /* No need to keep the socket API connection open */ - close (sm->socket_client_main->socket_fd); -} - -#define foreach_api_reply_msg \ -_(MAP_STATS_SEGMENT_REPLY, map_stats_segment_reply) - -static void -vpp_api_hookup (void) -{ -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_api_reply_msg; -#undef _ -} - -static int -connect_to_vpp (stat_client_main_t * sm) -{ - int rv; - vl_api_map_stats_segment_t *mp; - api_main_t *am = &api_main; - - sm->socket_client_main = &socket_client_main; - - rv = vl_socket_client_connect ((char *) sm->socket_name, - "stat_client", - 0 /* default socket rx, tx buffer */ ); - if (rv) - { - fformat (stderr, "Error connecting to vpp...\n"); - exit (1); - } - - /* Hook up reply handler */ - vpp_api_hookup (); - - /* Map the stats segment */ - mp = vl_socket_client_msg_alloc (sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_MAP_STATS_SEGMENT); - mp->client_index = am->my_client_index; - mp->context = 0xdeaddabe; - - /* Send the message */ - vl_socket_client_write (); - - /* Wait for a reply, process it.. */ - vl_socket_client_read (5 /* timeout in seconds */ ); - return 0; } @@ -399,24 +327,23 @@ stat_poll_loop (stat_client_main_t * sm) } } - int main (int argc, char **argv) { unformat_input_t _argv, *a = &_argv; stat_client_main_t *sm = &stat_client_main; - u8 *socket_name; + u8 *stat_segment_name; int rv; clib_mem_init (0, 128 << 20); unformat_init_command_line (a, argv); - socket_name = (u8 *) API_SOCKET_FILE; + stat_segment_name = (u8 *) STAT_SEGMENT_SOCKET_FILE; while (unformat_check_input (a) != UNFORMAT_END_OF_INPUT) { - if (unformat (a, "socket-name %s", &socket_name)) + if (unformat (a, "socket-name %s", &stat_segment_name)) ; else { @@ -425,14 +352,13 @@ main (int argc, char **argv) } } - sm->socket_name = socket_name; - - rv = connect_to_vpp (sm); + sm->socket_name = stat_segment_name; + rv = stat_segment_connect (sm); if (rv) { fformat (stderr, "Couldn't connect to vpp, does %s exist?\n", - socket_name); + stat_segment_name); exit (1); } diff --git a/src/vpp/app/stat_client.h b/src/vpp/app/stat_client.h index 87e5409ed6f..97bd3f9bb0b 100644 --- a/src/vpp/app/stat_client.h +++ b/src/vpp/app/stat_client.h @@ -18,10 +18,6 @@ #include #include #include -#include -#include -#include -#include #include typedef struct @@ -50,9 +46,6 @@ typedef struct /* mapped stats segment object */ ssvm_private_t stat_segment; - /* Socket client object */ - socket_client_main_t *socket_client_main; - /* Spinlock for the stats segment */ clib_spinlock_t *stat_segment_lockp; diff --git a/src/vpp/stats/stats.api b/src/vpp/stats/stats.api index bd1c3f634fe..72e03b0b40c 100644 --- a/src/vpp/stats/stats.api +++ b/src/vpp/stats/stats.api @@ -58,8 +58,6 @@ service { rpc want_udp_encap_stats returns want_udp_encap_stats_reply events vnet_udp_encap_counters; - rpc map_stats_segment - returns map_stats_segment_reply; }; /** \brief Want Stats, enable/disable ALL stats updates @@ -474,12 +472,6 @@ manual_print manual_endian define vnet_udp_encap_counters vl_api_udp_encap_counter_t c[count]; }; -autoreply define map_stats_segment -{ - u32 client_index; - u32 context; -}; - /* * Local Variables: diff --git a/src/vpp/stats/stats.c b/src/vpp/stats/stats.c index 31cfc336aca..452871febdc 100644 --- a/src/vpp/stats/stats.c +++ b/src/vpp/stats/stats.c @@ -65,8 +65,7 @@ _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) \ _(WANT_IP6_NBR_STATS, want_ip6_nbr_stats) \ _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) \ _(STATS_GET_POLLER_DELAY, stats_get_poller_delay) \ -_(WANT_UDP_ENCAP_STATS, want_udp_encap_stats) \ -_(MAP_STATS_SEGMENT, map_stats_segment) +_(WANT_UDP_ENCAP_STATS, want_udp_encap_stats) #define vl_msg_name_crc_list #include @@ -2258,14 +2257,74 @@ stats_set_poller_delay (u32 poller_delay_sec) } } +/* + * Accept connection on the socket and exchange the fd for the shared + * memory segment. + */ +static clib_error_t * +stats_socket_accept_ready (clib_file_t * uf) +{ + stats_main_t *sm = &stats_main; + ssvm_private_t *ssvmp = &sm->stat_segment; + clib_error_t *err; + clib_socket_t client = { 0 }; + + err = clib_socket_accept (sm->socket, &client); + if (err) + { + clib_error_report (err); + return err; + } + + /* Send the fd across and close */ + err = clib_socket_sendmsg (&client, 0, 0, &ssvmp->fd, 1); + if (err) + clib_error_report (err); + clib_socket_close (&client); + + return 0; +} + +static void +stats_segment_socket_init (void) +{ + stats_main_t *sm = &stats_main; + clib_error_t *error; + clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t)); + + s->config = (char *) sm->socket_name; + s->flags = CLIB_SOCKET_F_IS_SERVER | CLIB_SOCKET_F_SEQPACKET | + CLIB_SOCKET_F_ALLOW_GROUP_WRITE | CLIB_SOCKET_F_PASSCRED; + if ((error = clib_socket_init (s))) + { + clib_error_report (error); + return; + } + + clib_file_t template = { 0 }; + clib_file_main_t *fm = &file_main; + template.read_function = stats_socket_accept_ready; + template.file_descriptor = s->fd; + template.description = + format (0, "stats segment listener %s", STAT_SEGMENT_SOCKET_FILE); + clib_file_add (fm, &template); + + sm->socket = s; +} + static clib_error_t * stats_config (vlib_main_t * vm, unformat_input_t * input) { + stats_main_t *sm = &stats_main; u32 sec; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "interval %u", &sec)) + if (unformat (input, "socket-name %s", &sm->socket_name)) + ; + else if (unformat (input, "default")) + sm->socket_name = format (0, "%s", STAT_SEGMENT_SOCKET_FILE); + else if (unformat (input, "interval %u", &sec)) { int rv = stats_set_poller_delay (sec); if (rv) @@ -2274,7 +2333,6 @@ stats_config (vlib_main_t * vm, unformat_input_t * input) "`stats_set_poller_delay' API call failed, rv=%d:%U", (int) rv, format_vnet_api_errno, rv); } - return 0; } else { @@ -2282,6 +2340,10 @@ stats_config (vlib_main_t * vm, unformat_input_t * input) format_unformat_error, input); } } + + if (sm->socket_name) + stats_segment_socket_init (); + return 0; } @@ -2989,50 +3051,6 @@ stats_memclnt_delete_callback (u32 client_index) #define vl_api_vnet_ip4_nbr_counters_t_print vl_noop_handler #define vl_api_vnet_ip6_nbr_counters_t_endian vl_noop_handler #define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler -#define vl_api_map_stats_segment_t_print vl_noop_handler - -static void -vl_api_map_stats_segment_t_handler (vl_api_map_stats_segment_t * mp) -{ - vl_api_map_stats_segment_reply_t *rmp; - stats_main_t *sm = &stats_main; - ssvm_private_t *ssvmp = &sm->stat_segment; - vl_api_registration_t *regp; - api_main_t *am = &api_main; - clib_file_t *cf; - vl_api_shm_elem_config_t *config = 0; - vl_shmem_hdr_t *shmem_hdr; - int rv = 0; - - regp = vl_api_client_index_to_registration (mp->client_index); - if (regp == 0) - { - clib_warning ("API client disconnected"); - return; - } - if (regp->registration_type != REGISTRATION_TYPE_SOCKET_SERVER) - rv = VNET_API_ERROR_INVALID_REGISTRATION; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = htons (VL_API_MAP_STATS_SEGMENT_REPLY); - rmp->context = mp->context; - rmp->retval = htonl (rv); - - vl_api_send_msg (regp, (u8 *) rmp); - - if (rv != 0) - return; - - /* - * We need the reply message to make it out the back door - * before we send the magic fd message so force a flush - */ - cf = vl_api_registration_file (regp); - cf->write_function (cf); - - /* Send the magic "here's your sign (aka fd)" socket message */ - vl_sock_api_send_fd_msg (cf->file_descriptor, ssvmp->fd); -} static clib_error_t * stats_init (vlib_main_t * vm) diff --git a/src/vpp/stats/stats.h b/src/vpp/stats/stats.h index 262304e81ed..3b6f781eee3 100644 --- a/src/vpp/stats/stats.h +++ b/src/vpp/stats/stats.h @@ -29,6 +29,9 @@ #include #include +/* Default socket to exchange segment fd */ +#define STAT_SEGMENT_SOCKET_FILE "/run/vpp/stats.sock" + typedef struct { volatile u32 lock; @@ -162,6 +165,8 @@ typedef struct ssvm_private_t stat_segment; uword *counter_vector_by_name; clib_spinlock_t *stat_segment_lockp; + clib_socket_t *socket; + u8 *socket_name; /* Pointers to scalar stats maintained by the stat thread */ f64 *input_rate_ptr;