From 543852a46ce107243ed92254bd88b87ca82bbd0b Mon Sep 17 00:00:00 2001 From: Dave Wallace Date: Thu, 3 Aug 2017 02:11:34 -0400 Subject: Add VPP Communications Library (VCL) - VCL library - client/server test application - test script (make test integration tbd) - gdb command file templates - vppcom test config file Change-Id: I21eab7aa09b4e5dc3412acf5c2eab07415c2fc0f Signed-off-by: Dave Wallace --- src/uri/sock_test_server.c | 586 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 src/uri/sock_test_server.c (limited to 'src/uri/sock_test_server.c') diff --git a/src/uri/sock_test_server.c b/src/uri/sock_test_server.c new file mode 100644 index 00000000..52c60dc4 --- /dev/null +++ b/src/uri/sock_test_server.c @@ -0,0 +1,586 @@ +/* + * 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct +{ + uint8_t is_alloc; + int fd; + uint8_t *buf; + uint32_t buf_size; + sock_test_cfg_t cfg; + sock_test_stats_t stats; +#ifdef VCL_TEST + vppcom_endpt_t endpt; + uint8_t ip[16]; +#endif +} sock_server_conn_t; + +#define SOCK_SERVER_MAX_TEST_CONN 10 +typedef struct +{ + int listen_fd; + size_t num_conn; + size_t conn_pool_size; + sock_server_conn_t *conn_pool; + int nfds; + fd_set rd_fdset; + fd_set wr_fdset; + struct timeval timeout; +} sock_server_main_t; + +sock_server_main_t sock_server_main; + +static inline int +get_nfds (void) +{ + sock_server_main_t *ssm = &sock_server_main; + int i, nfds; + + for (nfds = i = 0; i < FD_SETSIZE; i++) + { + if (FD_ISSET (i, &ssm->rd_fdset) || FD_ISSET (i, &ssm->wr_fdset)) + nfds = i + 1; + } + return nfds; +} + +static inline void +conn_fdset_set (sock_server_conn_t * conn, fd_set * fdset) +{ + sock_server_main_t *ssm = &sock_server_main; + + FD_SET (conn->fd, fdset); + ssm->nfds = get_nfds (); +} + +static inline void +conn_fdset_clr (sock_server_conn_t * conn, fd_set * fdset) +{ + sock_server_main_t *ssm = &sock_server_main; + + FD_CLR (conn->fd, fdset); + ssm->nfds = get_nfds (); +} + +static inline void +conn_pool_expand (size_t expand_size) +{ + sock_server_main_t *ssm = &sock_server_main; + sock_server_conn_t *conn_pool; + size_t new_size = ssm->conn_pool_size + expand_size; + int i; + + conn_pool = realloc (ssm->conn_pool, new_size * sizeof (*ssm->conn_pool)); + if (conn_pool) + { + for (i = ssm->conn_pool_size; i < new_size; i++) + { + sock_server_conn_t *conn = &conn_pool[i]; + memset (conn, 0, sizeof (*conn)); + sock_test_cfg_init (&conn->cfg); + sock_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , + &conn->buf, &conn->buf_size); + conn->cfg.txbuf_size = conn->cfg.rxbuf_size; + } + + ssm->conn_pool = conn_pool; + ssm->conn_pool_size = new_size; + } + else + { + int errno_val = errno; + perror ("ERROR in conn_pool_expand()"); + fprintf (stderr, "ERROR: Memory allocation failed (errno = %d)!\n", + errno_val); + } +} + +static inline sock_server_conn_t * +conn_pool_alloc (void) +{ + sock_server_main_t *ssm = &sock_server_main; + int i; + + for (i = 0; i < ssm->conn_pool_size; i++) + { + if (!ssm->conn_pool[i].is_alloc) + { +#ifdef VCL_TEST + ssm->conn_pool[i].endpt.ip = ssm->conn_pool[i].ip; +#endif + ssm->conn_pool[i].is_alloc = 1; + return (&ssm->conn_pool[i]); + } + } + + return 0; +} + +static inline void +conn_pool_free (sock_server_conn_t * conn) +{ + sock_server_main_t *ssm = &sock_server_main; + + conn_fdset_clr (conn, &ssm->rd_fdset); + conn_fdset_clr (conn, &ssm->wr_fdset); + conn->fd = 0; + conn->is_alloc = 0; +} + +static inline void +sync_config_and_reply (sock_server_conn_t * conn, sock_test_cfg_t * rx_cfg) +{ + conn->cfg = *rx_cfg; + sock_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , + &conn->buf, &conn->buf_size); + conn->cfg.txbuf_size = conn->cfg.rxbuf_size; + + if (conn->cfg.verbose) + { + printf ("\nSERVER (fd %d): Replying to cfg message!\n", conn->fd); + sock_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); + } + (void) sock_test_write (conn->fd, (uint8_t *) & conn->cfg, + sizeof (conn->cfg), NULL, conn->cfg.verbose); +} + +static void +stream_test_server_start_stop (sock_server_conn_t * conn, + sock_test_cfg_t * rx_cfg) +{ + sock_server_main_t *ssm = &sock_server_main; + int client_fd = conn->fd; + sock_test_t test = rx_cfg->test; + + if (rx_cfg->ctrl_handle == conn->fd) + { + int i; + clock_gettime (CLOCK_REALTIME, &conn->stats.stop); + + for (i = 0; i < ssm->conn_pool_size; i++) + { + sock_server_conn_t *tc = &ssm->conn_pool[i]; + + if (tc->cfg.ctrl_handle == conn->fd) + { + sock_test_stats_accumulate (&conn->stats, &tc->stats); + + if (conn->cfg.verbose) + { + static char buf[64]; + + sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd); + sock_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ , + test == SOCK_TEST_TYPE_BI + /* show tx */ , + conn->cfg.verbose); + } + } + } + + sock_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ , + (test == SOCK_TEST_TYPE_BI) /* show_tx */ , + conn->cfg.verbose); + sock_test_cfg_dump (&conn->cfg, 0 /* is_client */ ); + if (conn->cfg.verbose) + { + printf (" sock server main\n" + SOCK_TEST_SEPARATOR_STRING + " buf: %p\n" + " buf size: %u (0x%08x)\n" + SOCK_TEST_SEPARATOR_STRING, + conn->buf, conn->buf_size, conn->buf_size); + } + + sync_config_and_reply (conn, rx_cfg); + printf ("\nSERVER (fd %d): %s-directional Stream Test Complete!\n" + SOCK_TEST_BANNER_STRING "\n", conn->fd, + test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni"); + } + else + { + printf ("\n" SOCK_TEST_BANNER_STRING + "SERVER (fd %d): %s-directional Stream Test!\n" + " Sending client the test cfg to start streaming data...\n", + client_fd, test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni"); + + rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd : + rx_cfg->ctrl_handle; + + sync_config_and_reply (conn, rx_cfg); + + /* read the 1st chunk, record start time */ + memset (&conn->stats, 0, sizeof (conn->stats)); + clock_gettime (CLOCK_REALTIME, &conn->stats.start); + } +} + + +static inline void +stream_test_server (sock_server_conn_t * conn, int rx_bytes) +{ + int client_fd = conn->fd; + sock_test_t test = conn->cfg.test; + + if (test == SOCK_TEST_TYPE_BI) + (void) sock_test_write (client_fd, conn->buf, rx_bytes, &conn->stats, + conn->cfg.verbose); + + if (conn->stats.rx_bytes >= conn->cfg.total_bytes) + { + clock_gettime (CLOCK_REALTIME, &conn->stats.stop); + } +} + +static inline void +new_client (void) +{ + sock_server_main_t *ssm = &sock_server_main; + int client_fd; + sock_server_conn_t *conn; + + if (ssm->conn_pool_size < (ssm->num_conn + SOCK_SERVER_MAX_TEST_CONN + 1)) + conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1); + + conn = conn_pool_alloc (); + if (!conn) + { + fprintf (stderr, "\nERROR: No free connections!\n"); + return; + } + +#ifdef VCL_TEST + client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, + -1.0 /* wait forever */ ); +#else + client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL); +#endif + if (client_fd < 0) + { + int errno_val; + errno_val = errno; + perror ("ERROR in main()"); + fprintf (stderr, "ERROR: accept failed (errno = %d)!\n", errno_val); + } + + printf ("SERVER: Got a connection -- fd = %d (0x%08x)!\n", + client_fd, client_fd); + + conn->fd = client_fd; + conn_fdset_set (conn, &ssm->rd_fdset); +} + +int +main (int argc, char **argv) +{ + sock_server_main_t *ssm = &sock_server_main; + int client_fd, rv, main_rv = 0; + int tx_bytes, rx_bytes, nbytes; + sock_server_conn_t *conn; + sock_test_cfg_t *rx_cfg; + uint32_t xtra = 0; + uint64_t xtra_bytes = 0; + struct sockaddr_in servaddr; + int errno_val; + int v, i; + uint16_t port = SOCK_TEST_SERVER_PORT; + fd_set _rfdset, *rfdset = &_rfdset; +#ifdef VCL_TEST + vppcom_endpt_t endpt; +#else + fd_set _wfdset, *wfdset = &_wfdset; +#endif + + if ((argc == 2) && (sscanf (argv[1], "%d", &v) == 1)) + port = (uint16_t) v; + + conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1); + +#ifdef VCL_TEST + rv = vppcom_app_create ("vcl_test_server"); + if (rv) + { + errno = -rv; + ssm->listen_fd = -1; + } + else + { + ssm->listen_fd = + vppcom_session_create (VPPCOM_VRF_DEFAULT, VPPCOM_PROTO_TCP, + 0 /* is_nonblocking */ ); + } +#else + ssm->listen_fd = socket (AF_INET, SOCK_STREAM, 0); +#endif + if (ssm->listen_fd < 0) + { + errno_val = errno; + perror ("ERROR in main()"); + fprintf (stderr, "ERROR: socket() failed (errno = %d)!\n", errno_val); + return ssm->listen_fd; + } + + memset (&servaddr, 0, sizeof (servaddr)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htons (INADDR_ANY); + servaddr.sin_port = htons (port); + +#ifdef VCL_TEST + endpt.vrf = VPPCOM_VRF_DEFAULT; + endpt.is_ip4 = (servaddr.sin_family == AF_INET); + endpt.ip = (uint8_t *) & servaddr.sin_addr; + endpt.port = (uint16_t) servaddr.sin_port; + + rv = vppcom_session_bind (ssm->listen_fd, &endpt); + if (rv) + { + errno = -rv; + rv = -1; + } +#else + rv = + bind (ssm->listen_fd, (struct sockaddr *) &servaddr, sizeof (servaddr)); +#endif + if (rv < 0) + { + errno_val = errno; + perror ("ERROR in main()"); + fprintf (stderr, "ERROR: bind failed (errno = %d)!\n", errno_val); + return rv; + } + +#ifdef VCL_TEST + rv = vppcom_session_listen (ssm->listen_fd, 10); + if (rv) + { + errno = -rv; + rv = -1; + } +#else + rv = listen (ssm->listen_fd, 10); +#endif + if (rv < 0) + { + errno_val = errno; + perror ("ERROR in main()"); + fprintf (stderr, "ERROR: listen failed (errno = %d)!\n", errno_val); + return rv; + } + + FD_ZERO (&ssm->wr_fdset); + FD_ZERO (&ssm->rd_fdset); + + FD_SET (ssm->listen_fd, &ssm->rd_fdset); + ssm->nfds = ssm->listen_fd + 1; + + printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port); + + while (1) + { + _rfdset = ssm->rd_fdset; + +#ifdef VCL_TEST + rv = vppcom_select (ssm->nfds, (uint64_t *) rfdset, NULL, NULL, 0); +#else + { + struct timeval timeout; + timeout = ssm->timeout; + _wfdset = ssm->wr_fdset; + rv = select (ssm->nfds, rfdset, wfdset, NULL, &timeout); + } +#endif + if (rv < 0) + { + perror ("select()"); + fprintf (stderr, "\nERROR: select() failed -- aborting!\n"); + main_rv = -1; + goto done; + } + else if (rv == 0) + continue; + + if (FD_ISSET (ssm->listen_fd, rfdset)) + new_client (); + + for (i = 0; i < ssm->conn_pool_size; i++) + { + if (!ssm->conn_pool[i].is_alloc) + continue; + + conn = &ssm->conn_pool[i]; + client_fd = conn->fd; + + if (FD_ISSET (client_fd, rfdset)) + { + rx_bytes = sock_test_read (client_fd, conn->buf, + conn->buf_size, &conn->stats); + if (rx_bytes > 0) + { + rx_cfg = (sock_test_cfg_t *) conn->buf; + if (rx_cfg->magic == SOCK_TEST_CFG_CTRL_MAGIC) + { + if (rx_cfg->verbose) + { + printf ("SERVER (fd %d): Received a cfg message!\n", + client_fd); + sock_test_cfg_dump (rx_cfg, 0 /* is_client */ ); + } + + if (rx_bytes != sizeof (*rx_cfg)) + { + printf ("SERVER (fd %d): Invalid cfg message " + "size (%d)!\n Should be %lu bytes.\n", + client_fd, rx_bytes, sizeof (*rx_cfg)); + conn->cfg.rxbuf_size = 0; + conn->cfg.num_writes = 0; + if (conn->cfg.verbose) + { + printf ("SERVER (fd %d): Replying to " + "cfg message!\n", client_fd); + sock_test_cfg_dump (rx_cfg, 0 /* is_client */ ); + } + sock_test_write (client_fd, (uint8_t *) & conn->cfg, + sizeof (conn->cfg), NULL, + conn->cfg.verbose); + continue; + } + + switch (rx_cfg->test) + { + case SOCK_TEST_TYPE_NONE: + case SOCK_TEST_TYPE_ECHO: + sync_config_and_reply (conn, rx_cfg); + break; + + case SOCK_TEST_TYPE_BI: + case SOCK_TEST_TYPE_UNI: + stream_test_server_start_stop (conn, rx_cfg); + break; + + case SOCK_TEST_TYPE_EXIT: + printf ("SERVER: Have a great day, " + "connection %d!\n", client_fd); +#ifdef VCL_TEST + vppcom_session_close (client_fd); +#else + close (client_fd); +#endif + conn_pool_free (conn); + + if (ssm->nfds == (ssm->listen_fd + 1)) + { + printf ("SERVER: All client connections " + "closed.\n\nSERVER: " + "May the force be with you!\n\n"); + goto done; + } + break; + + default: + fprintf (stderr, "ERROR: Unknown test type!\n"); + sock_test_cfg_dump (rx_cfg, 0 /* is_client */ ); + break; + } + continue; + } + + else if ((conn->cfg.test == SOCK_TEST_TYPE_UNI) || + (conn->cfg.test == SOCK_TEST_TYPE_BI)) + { + stream_test_server (conn, rx_bytes); + continue; + } + + else if (strlen ((char *) conn->buf)) + printf ("\nSERVER (fd %d): RX (%d bytes) - '%s'\n", + conn->fd, rx_bytes, conn->buf); + } + else // rx_bytes < 0 + { + if (errno == ECONNRESET) + { + printf ("\nSERVER: Connection reset by remote peer.\n" + " Y'all have a great day now!\n\n"); + break; + } + else + continue; + } + + if (isascii (conn->buf[0]) && strlen ((const char *) conn->buf)) + { + if (xtra) + fprintf (stderr, + "ERROR: FIFO not drained in previous test!\n" + " extra chunks %u (0x%x)\n" + " extra bytes %lu (0x%lx)\n", + xtra, xtra, xtra_bytes, xtra_bytes); + + xtra = 0; + xtra_bytes = 0; + + if (conn->cfg.verbose) + printf ("SERVER (fd %d): Echoing back\n", client_fd); + + nbytes = strlen ((const char *) conn->buf) + 1; + + tx_bytes = sock_test_write (client_fd, conn->buf, + nbytes, &conn->stats, + conn->cfg.verbose); + if (tx_bytes >= 0) + printf ("SERVER (fd %d): TX (%d bytes) - '%s'\n", + conn->fd, tx_bytes, conn->buf); + } + + else // Extraneous read data from non-echo tests??? + { + xtra++; + xtra_bytes += rx_bytes; + } + } + } + } + +done: +#ifdef VCL_TEST + vppcom_session_close (ssm->listen_fd); + vppcom_app_destroy (); +#else + close (ssm->listen_fd); +#endif + if (ssm->conn_pool) + free (ssm->conn_pool); + + return main_rv; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From 33e002b168a211b1d620f4fffbd3752c8f1f2129 Mon Sep 17 00:00:00 2001 From: Dave Wallace Date: Wed, 6 Sep 2017 01:20:02 -0400 Subject: Fix session connect_* api message handling. Change-Id: If7fd125989c90240de12953658d10007b9eb4f07 Signed-off-by: Dave Wallace --- extras/gdb/gdb_cmdfile.vcl_client | 6 +- extras/gdb/gdb_cmdfile.vcl_server | 6 +- src/uri/sock_test_server.c | 2 +- src/uri/uri_tcp_test.c | 4 +- src/uri/uri_udp_test.c | 8 +- src/uri/vppcom.c | 225 ++++++++++++++++++-------------------- src/vnet/session/session.api | 45 +++----- src/vnet/session/session.h | 22 ++++ src/vnet/session/session_api.c | 26 ++--- 9 files changed, 165 insertions(+), 179 deletions(-) (limited to 'src/uri/sock_test_server.c') diff --git a/extras/gdb/gdb_cmdfile.vcl_client b/extras/gdb/gdb_cmdfile.vcl_client index a622f958..9b43ed6a 100644 --- a/extras/gdb/gdb_cmdfile.vcl_client +++ b/extras/gdb/gdb_cmdfile.vcl_client @@ -1,10 +1,10 @@ -echo \n\n====== gdb_cmdfile.vppcom_client ======\n +echo \n\n====== gdb_cmdfile.vcl_client ======\n -# Here are some interesting vppcom breakpoints... +# Here are some interesting VCL breakpoints... # Uncomment them out to set during gdb init. # #b vppcom_session_connect #b vppcom_session_write #b vppcom_session_read #b vl_api_connect_sock_t_handler -#b vl_api_connect_sock_reply_t_handler +#b vl_api_connect_session_reply_t_handler diff --git a/extras/gdb/gdb_cmdfile.vcl_server b/extras/gdb/gdb_cmdfile.vcl_server index 8e441018..f3ce4fbc 100644 --- a/extras/gdb/gdb_cmdfile.vcl_server +++ b/extras/gdb/gdb_cmdfile.vcl_server @@ -1,10 +1,10 @@ -echo \n\n====== gdb_cmdfile.vppcom_server ======\n +echo \n\n====== gdb_cmdfile.vcl_server ======\n -# Here are some interesting vppcom breakpoints... +# Here are some interesting VCL breakpoints... # Uncomment them out to set during gdb init. # #b vppcom_session_accept #b vppcom_session_write #b vppcom_session_read #b vl_api_connect_sock_t_handler -#b vl_api_connect_sock_reply_t_handler +#b vl_api_connect_session_reply_t_handler diff --git a/src/uri/sock_test_server.c b/src/uri/sock_test_server.c index 52c60dc4..f703b177 100644 --- a/src/uri/sock_test_server.c +++ b/src/uri/sock_test_server.c @@ -345,7 +345,7 @@ main (int argc, char **argv) memset (&servaddr, 0, sizeof (servaddr)); servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htons (INADDR_ANY); + servaddr.sin_addr.s_addr = htonl (INADDR_ANY); servaddr.sin_port = htons (port); #ifdef VCL_TEST diff --git a/src/uri/uri_tcp_test.c b/src/uri/uri_tcp_test.c index f5fbbd23..cb297b55 100755 --- a/src/uri/uri_tcp_test.c +++ b/src/uri/uri_tcp_test.c @@ -526,7 +526,7 @@ client_rx_thread_fn (void *arg) static void -vl_api_connect_uri_reply_t_handler (vl_api_connect_uri_reply_t * mp) +vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) { uri_tcp_test_main_t *utm = &uri_tcp_test_main; session_t *session; @@ -1122,7 +1122,7 @@ vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t * _(BIND_URI_REPLY, bind_uri_reply) \ _(UNBIND_URI_REPLY, unbind_uri_reply) \ _(ACCEPT_SESSION, accept_session) \ -_(CONNECT_URI_REPLY, connect_uri_reply) \ +_(CONNECT_SESSION_REPLY, connect_session_reply) \ _(DISCONNECT_SESSION, disconnect_session) \ _(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \ _(RESET_SESSION, reset_session) \ diff --git a/src/uri/uri_udp_test.c b/src/uri/uri_udp_test.c index aea4707c..f50ee688 100644 --- a/src/uri/uri_udp_test.c +++ b/src/uri/uri_udp_test.c @@ -518,7 +518,7 @@ vl_api_connect_uri_t_handler (vl_api_connect_uri_t * mp) svm_fifo_segment_create_args_t _a, *a = &_a; svm_fifo_segment_private_t *seg; unix_shared_memory_queue_t *client_q; - vl_api_connect_uri_reply_t *rmp; + vl_api_connect_session_reply_t *rmp; session_t *session = 0; int rv = 0; @@ -566,7 +566,7 @@ send_reply: rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_CONNECT_URI_REPLY); + rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY); rmp->context = mp->context; rmp->retval = ntohl (rv); rmp->segment_name_length = vec_len (a->segment_name); @@ -674,7 +674,7 @@ vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp) } static void -vl_api_connect_uri_reply_t_handler (vl_api_connect_uri_reply_t * mp) +vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) { uri_udp_test_main_t *utm = &uri_udp_test_main; @@ -727,7 +727,7 @@ vl_api_connect_uri_reply_t_handler (vl_api_connect_uri_reply_t * mp) #define foreach_uri_msg \ _(BIND_URI_REPLY, bind_uri_reply) \ _(CONNECT_URI, connect_uri) \ -_(CONNECT_URI_REPLY, connect_uri_reply) \ +_(CONNECT_SESSION_REPLY, connect_session_reply) \ _(UNBIND_URI_REPLY, unbind_uri_reply) \ _(ACCEPT_SESSION, accept_session) \ _(DISCONNECT_SESSION, disconnect_session) \ diff --git a/src/uri/vppcom.c b/src/uri/vppcom.c index c41acd54..aec1295f 100644 --- a/src/uri/vppcom.c +++ b/src/uri/vppcom.c @@ -1,5 +1,5 @@ /* - * 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 * You may obtain a copy of the License at: @@ -76,7 +76,7 @@ typedef struct svm_fifo_t *server_tx_fifo; u32 sm_seg_index; u64 vpp_session_handle; - unix_shared_memory_queue_t *event_queue; + unix_shared_memory_queue_t *vpp_event_queue; /* Socket configuration state */ u8 is_server; @@ -682,7 +682,7 @@ vl_api_reset_session_t_handler (vl_api_reset_session_t * mp) } static void -vl_api_connect_sock_reply_t_handler (vl_api_connect_sock_reply_t * mp) +vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) { vppcom_main_t *vcm = &vppcom_main; session_t *session; @@ -698,9 +698,9 @@ vl_api_connect_sock_reply_t_handler (vl_api_connect_sock_reply_t * mp) return; } - session_index = ntohl (mp->app_connect); + session_index = mp->context; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] app_connect = %d 0x%08x", vcm->my_pid, + clib_warning ("[%d] session_index = %d 0x%08x", vcm->my_pid, session_index, session_index); clib_spinlock_lock (&vcm->sessions_lockp); @@ -743,8 +743,8 @@ vl_api_connect_sock_reply_t_handler (vl_api_connect_sock_reply_t * mp) session = pool_elt_at_index (vcm->sessions, session_index); session->is_cut_thru = is_cut_thru; - session->event_queue = uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address, + unix_shared_memory_queue_t *); rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *); rx_fifo->client_session_index = session_index; @@ -773,13 +773,11 @@ vppcom_send_connect_sock (session_t * session, u32 session_index) memset (cmp, 0, sizeof (*cmp)); cmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK); cmp->client_index = vcm->my_client_index; - cmp->context = htonl (0xfeedface); - cmp->app_connect = session_index; + cmp->context = session_index; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] session_index = %d 0x%08x, app_connect = %d 0x%08x", - vcm->my_pid, session_index, session_index, - cmp->app_connect, cmp->app_connect); + clib_warning ("[%d] session_index = %d 0x%08x", + vcm->my_pid, session_index, session_index); cmp->vrf = session->vrf; cmp->is_ip4 = session->is_ip4; @@ -991,8 +989,8 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) session->server_rx_fifo = rx_fifo; session->server_tx_fifo = tx_fifo; - session->event_queue = uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address, + unix_shared_memory_queue_t *); session->state = STATE_ACCEPT; session->is_cut_thru = 0; session->port = ntohs (mp->port); @@ -1029,7 +1027,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) u32 session_index; svm_fifo_segment_private_t *seg; unix_shared_memory_queue_t *client_q; - vl_api_connect_sock_reply_t *rmp; + vl_api_connect_session_reply_t *rmp; session_t *session = 0; int rv = 0; svm_fifo_t *rx_fifo; @@ -1119,7 +1117,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) ssvm_lock_non_recursive (sh, 1); oldheap = ssvm_push_heap (sh); - event_q = session->event_queue = + event_q = session->vpp_event_queue = unix_shared_memory_queue_init (vcm->cfg.event_queue_size, sizeof (session_fifo_event_t), vcm->my_pid, 0 /* signal not sent */ ); @@ -1139,9 +1137,8 @@ send_reply: rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SOCK_REPLY); + rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY); rmp->context = mp->context; - rmp->app_connect = htonl (mp->app_connect); rmp->retval = htonl (rv); rmp->segment_name_length = vec_len (a->segment_name); clib_memcpy (rmp->segment_name, a->segment_name, vec_len (a->segment_name)); @@ -1293,7 +1290,7 @@ _(BIND_SOCK_REPLY, bind_sock_reply) \ _(UNBIND_SOCK_REPLY, unbind_sock_reply) \ _(ACCEPT_SESSION, accept_session) \ _(CONNECT_SOCK, connect_sock) \ -_(CONNECT_SOCK_REPLY, connect_sock_reply) \ +_(CONNECT_SESSION_REPLY, connect_session_reply) \ _(DISCONNECT_SESSION, disconnect_session) \ _(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \ _(RESET_SESSION, reset_session) \ @@ -1878,6 +1875,7 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) vppcom_main_t *vcm = &vppcom_main; session_t *session = 0; int rv; + ip46_address_t *ip46; if (!ep || !ep->ip) return VPPCOM_EINVAL; @@ -1898,8 +1896,9 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) session->vrf = ep->vrf; session->is_ip4 = ep->is_ip4; - memset (session->ip, 0, sizeof (*session->ip)); - clib_memcpy (session->ip, ep->ip, sizeof (session->ip)); + memset (session->ip, 0, sizeof (session->ip)); + ip46 = (ip46_address_t *) session->ip; + *ip46 = to_ip46 (!ep->is_ip4, ep->ip); session->port = ep->port; clib_spinlock_unlock (&vcm->sessions_lockp); @@ -1907,32 +1906,33 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) } int -vppcom_session_listen (uint32_t session_index, uint32_t q_len) +vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) { vppcom_main_t *vcm = &vppcom_main; - session_t *session = 0; + session_t *listen_session = 0; int rv; clib_spinlock_lock (&vcm->sessions_lockp); - rv = vppcom_session_at_index (session_index, &session); + rv = vppcom_session_at_index (listen_session_index, &listen_session); if (PREDICT_FALSE (rv)) { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) clib_warning ("[%d] invalid session, sid (%d) has been closed!", - vcm->my_pid, session_index); + vcm->my_pid, listen_session_index); return rv; } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sid %d", vcm->my_pid, session_index); + clib_warning ("[%d] sid %d", vcm->my_pid, listen_session_index); ASSERT (vcm->bind_session_index == ~0); - vcm->bind_session_index = session_index; - vppcom_send_bind_sock (session); + vcm->bind_session_index = listen_session_index; + vppcom_send_bind_sock (listen_session); clib_spinlock_unlock (&vcm->sessions_lockp); - rv = vppcom_wait_for_session_state_change (session_index, STATE_LISTEN, - vcm->cfg.session_timeout); + rv = + vppcom_wait_for_session_state_change (listen_session_index, STATE_LISTEN, + vcm->cfg.session_timeout); if (PREDICT_FALSE (rv)) { vcm->bind_session_index = ~0; @@ -1943,16 +1943,16 @@ vppcom_session_listen (uint32_t session_index, uint32_t q_len) } clib_spinlock_lock (&vcm->sessions_lockp); - rv = vppcom_session_at_index (session_index, &session); + rv = vppcom_session_at_index (listen_session_index, &listen_session); if (PREDICT_FALSE (rv)) { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) clib_warning ("[%d] invalid session, sid (%d) has been closed!", - vcm->my_pid, session_index); + vcm->my_pid, listen_session_index); return rv; } - session->is_listen = 1; + listen_session->is_listen = 1; clib_spinlock_unlock (&vcm->sessions_lockp); clib_fifo_validate (vcm->client_session_index_fifo, q_len); @@ -1964,13 +1964,14 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, double wait_for_time) { vppcom_main_t *vcm = &vppcom_main; - session_t *session = 0; + session_t *listen_session = 0; + session_t *client_session = 0; u32 client_session_index; int rv; f64 wait_for; clib_spinlock_lock (&vcm->sessions_lockp); - rv = vppcom_session_at_index (listen_session_index, &session); + rv = vppcom_session_at_index (listen_session_index, &listen_session); if (PREDICT_FALSE (rv)) { clib_spinlock_unlock (&vcm->sessions_lockp); @@ -1980,21 +1981,23 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, return rv; } - if (session->state != STATE_LISTEN) + if (listen_session->state != STATE_LISTEN) { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) clib_warning ("[%d] session not in listen state, state = %s", - vcm->my_pid, vppcom_session_state_str (session->state)); + vcm->my_pid, + vppcom_session_state_str (listen_session->state)); return VPPCOM_EBADFD; } - wait_for = session->is_nonblocking ? 0 : + wait_for = listen_session->is_nonblocking ? 0 : (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sid %d, state %s (%d)", vcm->my_pid, + clib_warning ("[%d] sid %d: %s (%d)", vcm->my_pid, listen_session_index, - vppcom_session_state_str (session->state), session->state); + vppcom_session_state_str (listen_session->state), + listen_session->state); clib_spinlock_unlock (&vcm->sessions_lockp); while (1) @@ -2015,23 +2018,23 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, clib_fifo_sub1 (vcm->client_session_index_fifo, client_session_index); - session = 0; clib_spinlock_lock (&vcm->sessions_lockp); - rv = vppcom_session_at_index (client_session_index, &session); + rv = vppcom_session_at_index (client_session_index, &client_session); ASSERT (rv == VPPCOM_OK); - ASSERT (session->is_server); + ASSERT (client_session->is_ip4 == listen_session->is_ip4); if (VPPCOM_DEBUG > 0) clib_warning ("[%d] Got a request: client sid %d", vcm->my_pid, client_session_index); - ep->vrf = session->vrf; - ep->is_cut_thru = session->is_cut_thru; - ep->is_ip4 = session->is_ip4; - ep->port = session->port; - memset (ep->ip, 0, sizeof (ip6_address_t)); - clib_memcpy (ep->ip, session->ip, sizeof (ip6_address_t)); - session->state = STATE_LISTEN; + ep->vrf = client_session->vrf; + ep->is_cut_thru = client_session->is_cut_thru; + ep->is_ip4 = client_session->is_ip4; + ep->port = client_session->port; + if (client_session->is_ip4) + clib_memcpy (ep->ip, client_session->ip, sizeof (ip4_address_t)); + else + clib_memcpy (ep->ip, client_session->ip, sizeof (ip6_address_t)); clib_spinlock_unlock (&vcm->sessions_lockp); return (int) client_session_index; } @@ -2066,6 +2069,7 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) session->vrf = server_ep->vrf; session->is_ip4 = server_ep->is_ip4; + memset (session->ip, 0, sizeof (session->ip)); ip46 = (ip46_address_t *) session->ip; *ip46 = to_ip46 (!server_ep->is_ip4, server_ep->ip); session->port = server_ep->port; @@ -2097,12 +2101,12 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) int vppcom_session_read (uint32_t session_index, void *buf, int n) { - session_fifo_event_t _e, *e = &_e; vppcom_main_t *vcm = &vppcom_main; session_t *session = 0; svm_fifo_t *rx_fifo; int n_read = 0; int rv; + int max_dequeue; char *fifo_str; ASSERT (buf); @@ -2118,100 +2122,62 @@ vppcom_session_read (uint32_t session_index, void *buf, int n) return rv; } - if (session->is_cut_thru) + if (session->state == STATE_DISCONNECT) { - rx_fifo = session->is_server ? session->server_rx_fifo : - session->server_tx_fifo; - fifo_str = session->is_server ? "server_rx_fifo" : "server_tx_fifo"; clib_spinlock_unlock (&vcm->sessions_lockp); - - n_read = svm_fifo_dequeue_nowait (rx_fifo, n, buf); - - if (n_read <= 0) - return VPPCOM_EAGAIN; - + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] sid (%d) has been closed by remote peer!", + vcm->my_pid, session_index); + return VPPCOM_ECONNRESET; } - else - { - rv = unix_shared_memory_queue_sub (session->event_queue, (u8 *) e, - 1 /* nowait */ ); - clib_spinlock_unlock (&vcm->sessions_lockp); - if (rv < 0) - return VPPCOM_EAGAIN; - - switch (e->event_type) - { - case FIFO_EVENT_APP_RX: - rx_fifo = e->fifo; - fifo_str = "app_rx_fifo"; - n_read = svm_fifo_dequeue_nowait (rx_fifo, n, buf); - break; - case FIFO_EVENT_DISCONNECT: - return VPPCOM_ECONNRESET; + rx_fifo = ((!session->is_cut_thru || session->is_server) ? + session->server_rx_fifo : session->server_tx_fifo); + fifo_str = ((!session->is_cut_thru || session->is_server) ? + "server_rx_fifo" : "server_tx_fifo"); + clib_spinlock_unlock (&vcm->sessions_lockp); - default: - if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] unknown event type %d", vcm->my_pid, - e->event_type); - return VPPCOM_EAGAIN; - } - } + max_dequeue = (int) svm_fifo_max_dequeue (rx_fifo); + n_read = svm_fifo_dequeue_nowait (rx_fifo, clib_min (n, max_dequeue), buf); if (VPPCOM_DEBUG > 2) clib_warning ("[%d] sid %d, read %d bytes from %s (%p)", vcm->my_pid, session_index, n_read, fifo_str, rx_fifo); - return n_read; + + return (n_read <= 0) ? VPPCOM_EAGAIN : n_read; } static inline int vppcom_session_read_ready (session_t * session, u32 session_index) { - session_fifo_event_t _e, *e = &_e; vppcom_main_t *vcm = &vppcom_main; svm_fifo_t *rx_fifo; - int rv; int ready = 0; /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ - if (session->is_cut_thru) + if (session->state == STATE_DISCONNECT) { - rx_fifo = session->is_server ? session->server_rx_fifo : - session->server_tx_fifo; - - ready = svm_fifo_max_dequeue (rx_fifo); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] sid (%d) has been closed by remote peer!", + vcm->my_pid, session_index); + return VPPCOM_ECONNRESET; } - else if (session->is_listen) + + if (session->is_listen) ready = clib_fifo_elts (vcm->client_session_index_fifo); else { - rv = unix_shared_memory_queue_sub (vcm->app_event_queue, (u8 *) e, - 1 /* nowait */ ); - if (rv >= 0) - { - switch (e->event_type) - { - case FIFO_EVENT_APP_RX: - rx_fifo = e->fifo; - ready = svm_fifo_max_dequeue (rx_fifo); - break; + rx_fifo = ((!session->is_cut_thru || session->is_server) ? + session->server_rx_fifo : session->server_tx_fifo); - case FIFO_EVENT_DISCONNECT: - return VPPCOM_ECONNRESET; - - default: - clib_warning ("[%d] unknown event type %d", vcm->my_pid, - e->event_type); - } - } + ready = svm_fifo_max_dequeue (rx_fifo); } - if (VPPCOM_DEBUG > 2) + if (VPPCOM_DEBUG > 3) clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", vcm->my_pid, session_index, session->is_server ? "server_rx_fifo" : "server_tx_fifo", rx_fifo, ready); - return ready; } @@ -2240,10 +2206,20 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) return rv; } + if (session->state == STATE_DISCONNECT) + { + clib_spinlock_unlock (&vcm->sessions_lockp); + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] sid (%d) has been closed by remote peer!", + vcm->my_pid, session_index); + return VPPCOM_ECONNRESET; + } + tx_fifo = ((!session->is_cut_thru || session->is_server) ? session->server_tx_fifo : session->server_rx_fifo); fifo_str = ((!session->is_cut_thru || session->is_server) ? "server_tx_fifo" : "server_rx_fifo"); + is_nonblocking = session->is_nonblocking; clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2254,7 +2230,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) while (!is_nonblocking && (rv <= 0)); /* If event wasn't set, add one */ - if ((rv > 0) && svm_fifo_set_event (tx_fifo)) + if (!session->is_cut_thru && (rv > 0) && svm_fifo_set_event (tx_fifo)) { int rval; @@ -2273,7 +2249,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) vcm->my_pid, session_index); return rval; } - q = session->event_queue; + q = session->vpp_event_queue; clib_spinlock_unlock (&vcm->sessions_lockp); ASSERT (q); unix_shared_memory_queue_add (q, (u8 *) & evt, @@ -2292,19 +2268,28 @@ vppcom_session_write_ready (session_t * session, u32 session_index) { vppcom_main_t *vcm = &vppcom_main; svm_fifo_t *tx_fifo; + char *fifo_str; int rv; /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ + if (session->state == STATE_DISCONNECT) + { + if (VPPCOM_DEBUG > 0) + clib_warning ("[%d] sid (%d) has been closed by remote peer!", + vcm->my_pid, session_index); + return VPPCOM_ECONNRESET; + } + tx_fifo = ((!session->is_cut_thru || session->is_server) ? session->server_tx_fifo : session->server_rx_fifo); + fifo_str = ((!session->is_cut_thru || session->is_server) ? + "server_tx_fifo" : "server_rx_fifo"); rv = svm_fifo_max_enqueue (tx_fifo); - if (VPPCOM_DEBUG > 2) + if (VPPCOM_DEBUG > 3) clib_warning ("[%d] sid %d, peek %s (%p), ready = %d", vcm->my_pid, - session_index, - session->is_server ? "server_tx_fifo" : "server_rx_fifo", - tx_fifo, rv); + session_index, fifo_str, tx_fifo, rv); return rv; } diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api index e01cc75e..30d2ae96 100644 --- a/src/vnet/session/session.api +++ b/src/vnet/session/session.api @@ -105,7 +105,7 @@ autoreply define unbind_uri { @param client_queue_address - binary API client queue address. Used by local server when connect was redirected. */ -define connect_uri { +autoreply define connect_uri { u32 client_index; u32 context; u8 uri[128]; @@ -113,31 +113,6 @@ define connect_uri { u64 options[16]; }; -/** \brief vpp->client, connect reply - @param context - sender context, to match reply w/ request - @param retval - return code for the request - @param handle - session handle - @param server_rx_fifo - rx (vpp -> vpp-client) fifo address - @param server_tx_fifo - tx (vpp-client -> vpp) fifo address - @param vpp_event_queue_address - vpp's event queue address - @param segment_size - size of segment to be attached. Only for redirects. - @param segment_name_length - non-zero if the client needs to attach to - the fifo segment. This should only happen - if session was redirected. - @param segment_name - set if the client needs to attach to the segment -*/ -define connect_uri_reply { - u32 context; - i32 retval; - u64 handle; - u64 server_rx_fifo; - u64 server_tx_fifo; - u64 vpp_event_queue_address; - u32 segment_size; - u8 segment_name_length; - u8 segment_name[128]; -}; - /** \brief vpp->client, accept this session @param context - sender context, to match reply w/ request @param listener_handle - tells client which listener this pertains to @@ -273,10 +248,9 @@ autoreply define unbind_sock { used to perform redirects @param options - socket options, fifo sizes, etc. when doing redirects */ -define connect_sock { +autoreply define connect_sock { u32 client_index; u32 context; - u32 app_connect; u32 vrf; u8 is_ip4; u8 ip[16]; @@ -305,11 +279,19 @@ define bind_sock_reply { u8 segment_name[128]; }; -/** \brief vpp/server->client, connect reply +/* Dummy connect message -- needed to satisfy api generators +* +* NEVER USED, doxygen tags elided on purpose. +*/ +define connect_session { + u32 client_index; + u32 context; +}; + +/** \brief vpp/server->client, connect reply -- used for all connect_* messages @param context - sender context, to match reply w/ request @param retval - return code for the request @param handle - connection handle - @param app_connect - application connection id from connect msg @param server_rx_fifo - rx (vpp -> vpp-client) fifo address @param server_tx_fifo - tx (vpp-client -> vpp) fifo address @param vpp_event_queue_address - vpp's event queue address @@ -318,11 +300,10 @@ define bind_sock_reply { the fifo segment @param segment_name - set if the client needs to attach to the segment */ -define connect_sock_reply { +define connect_session_reply { u32 context; i32 retval; u64 handle; - u32 app_connect; u64 server_rx_fifo; u64 server_tx_fifo; u64 vpp_event_queue_address; diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index 74d82a40..83addec2 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -38,6 +38,28 @@ typedef enum FIFO_EVENT_RPC, } fifo_event_type_t; +static inline const char * +fifo_event_type_str (fifo_event_type_t et) +{ + switch (et) + { + case FIFO_EVENT_APP_RX: + return "FIFO_EVENT_APP_RX"; + case FIFO_EVENT_APP_TX: + return "FIFO_EVENT_APP_TX"; + case FIFO_EVENT_TIMEOUT: + return "FIFO_EVENT_TIMEOUT"; + case FIFO_EVENT_DISCONNECT: + return "FIFO_EVENT_DISCONNECT"; + case FIFO_EVENT_BUILTIN_RX: + return "FIFO_EVENT_BUILTIN_RX"; + case FIFO_EVENT_RPC: + return "FIFO_EVENT_RPC"; + default: + return "UNKNOWN FIFO EVENT"; + } +} + #define foreach_session_input_error \ _(NO_SESSION, "No session drops") \ _(NO_LISTENER, "No listener for dst port drops") \ diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index 6bee3e27..60d9b4de 100755 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -155,7 +155,7 @@ int send_session_connected_callback (u32 app_index, u32 api_context, stream_session_t * s, u8 is_fail) { - vl_api_connect_uri_reply_t *mp; + vl_api_connect_session_reply_t *mp; unix_shared_memory_queue_t *q; application_t *app; unix_shared_memory_queue_t *vpp_queue; @@ -167,7 +167,7 @@ send_session_connected_callback (u32 app_index, u32 api_context, return -1; mp = vl_msg_api_alloc (sizeof (*mp)); - mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_CONNECT_URI_REPLY); + mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_CONNECT_SESSION_REPLY); mp->context = api_context; if (!is_fail) { @@ -415,7 +415,7 @@ done: static void vl_api_connect_uri_t_handler (vl_api_connect_uri_t * mp) { - vl_api_connect_uri_reply_t *rmp; + vl_api_connect_session_reply_t *rmp; vnet_connect_args_t _a, *a = &_a; application_t *app; int rv; @@ -447,7 +447,7 @@ vl_api_connect_uri_t_handler (vl_api_connect_uri_t * mp) done: /* *INDENT-OFF* */ - REPLY_MACRO (VL_API_CONNECT_URI_REPLY); + REPLY_MACRO (VL_API_CONNECT_SESSION_REPLY); /* *INDENT-ON* */ } @@ -593,11 +593,11 @@ vl_api_bind_sock_t_handler (vl_api_bind_sock_t * mp) app = application_lookup (mp->client_index); if (app) { + ip46_address_t *ip46 = (ip46_address_t *) mp->ip; + memset (a, 0, sizeof (*a)); - clib_memcpy (&a->tep.ip, mp->ip, (mp->is_ip4 ? - sizeof (ip4_address_t) : - sizeof (ip6_address_t))); a->tep.is_ip4 = mp->is_ip4; + a->tep.ip = *ip46; a->tep.port = mp->port; a->tep.vrf = mp->vrf; a->app_index = app->index; @@ -637,7 +637,7 @@ done: static void vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) { - vl_api_connect_sock_reply_t *rmp; + vl_api_connect_session_reply_t *rmp; vnet_connect_args_t _a, *a = &_a; application_t *app; int rv; @@ -652,16 +652,14 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) if (app) { unix_shared_memory_queue_t *client_q; - u8 *ip = mp->is_ip4 ? (u8 *) & a->tep.ip.ip4 : (u8 *) & a->tep.ip; + ip46_address_t *ip46 = (ip46_address_t *) mp->ip; client_q = vl_api_client_index_to_input_queue (mp->client_index); mp->client_queue_address = pointer_to_uword (client_q); a->tep.is_ip4 = mp->is_ip4; + a->tep.ip = *ip46; a->tep.port = mp->port; - - clib_memcpy (ip, mp->ip, - (mp->is_ip4 ? sizeof (ip4_address_t) : - sizeof (ip6_address_t))); + a->tep.vrf = mp->vrf; a->api_context = mp->context; a->app_index = app->index; a->proto = mp->proto; @@ -679,7 +677,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) /* Got some error, relay it */ done: - REPLY_MACRO (VL_API_CONNECT_SOCK_REPLY); + REPLY_MACRO (VL_API_CONNECT_SESSION_REPLY); } static clib_error_t * -- cgit 1.2.3-korg From ab7b8d93cf1098970bc17fb4937376bb1ff33a21 Mon Sep 17 00:00:00 2001 From: Chris Luke Date: Thu, 7 Sep 2017 07:40:13 -0400 Subject: Fixes for issues reported by Coverity (VPP-972) Change-Id: I25238debb7081b4467aec4620dfdef33fbef3295 Signed-off-by: Chris Luke --- src/svm/svm_fifo.c | 2 +- src/uri/sock_test_client.c | 2 ++ src/uri/sock_test_server.c | 12 +++++++++--- src/uri/vppcom.c | 17 ++++++++--------- src/vlib/unix/main.c | 8 ++++---- src/vnet/ipsec/ikev2.c | 11 ++++++++++- src/vppinfra/socket.c | 16 ++++++++++++++-- 7 files changed, 48 insertions(+), 20 deletions(-) (limited to 'src/uri/sock_test_server.c') diff --git a/src/svm/svm_fifo.c b/src/svm/svm_fifo.c index 8fe82f56..42eb1ee8 100644 --- a/src/svm/svm_fifo.c +++ b/src/svm/svm_fifo.c @@ -443,7 +443,7 @@ ooo_segment_try_collect (svm_fifo_t * f, u32 n_bytes_enqueued) } } - ASSERT (bytes >= 0 && bytes <= f->nitems); + ASSERT (bytes <= f->nitems); return bytes; } diff --git a/src/uri/sock_test_client.c b/src/uri/sock_test_client.c index 4319f01b..ab8e5a0e 100644 --- a/src/uri/sock_test_client.c +++ b/src/uri/sock_test_client.c @@ -895,6 +895,8 @@ main (int argc, char **argv) case 'w': fprintf (stderr, "ERROR: Option -%c requires an argument.\n", optopt); + break; + default: if (isprint (optopt)) fprintf (stderr, "ERROR: Unknown option `-%c'.\n", optopt); diff --git a/src/uri/sock_test_server.c b/src/uri/sock_test_server.c index f703b177..29adea25 100644 --- a/src/uri/sock_test_server.c +++ b/src/uri/sock_test_server.c @@ -514,9 +514,15 @@ main (int argc, char **argv) continue; } - else if (strlen ((char *) conn->buf)) - printf ("\nSERVER (fd %d): RX (%d bytes) - '%s'\n", - conn->fd, rx_bytes, conn->buf); + else if (((char *) conn->buf)[0] != 0) + { + // If it looks vaguely like a string, make sure it's terminated + ((char *) conn->buf)[rx_bytes < + conn->buf_size ? rx_bytes : + conn->buf_size - 1] = 0; + printf ("\nSERVER (fd %d): RX (%d bytes) - '%s'\n", + conn->fd, rx_bytes, conn->buf); + } } else // rx_bytes < 0 { diff --git a/src/uri/vppcom.c b/src/uri/vppcom.c index aec1295f..aa307f1d 100644 --- a/src/uri/vppcom.c +++ b/src/uri/vppcom.c @@ -1369,23 +1369,18 @@ vppcom_cfg_heapsize (char *conf_fname) argc++; char **tmp = realloc (argv, argc * sizeof (char *)); if (tmp == NULL) - { - fclose (fp); - goto defaulted; - } + goto defaulted; argv = tmp; arg = strndup (p, 1024); if (arg == NULL) - { - fclose (fp); - goto defaulted; - } + goto defaulted; argv[argc - 1] = arg; p = strtok (NULL, " \t\n"); } } fclose (fp); + fp = NULL; char **tmp = realloc (argv, (argc + 1) * sizeof (char *)); if (tmp == NULL) @@ -1438,6 +1433,10 @@ vppcom_cfg_heapsize (char *conf_fname) } defaulted: + if (fp != NULL) + fclose (fp); + if (argv != NULL) + free (argv); if (!clib_mem_init (0, vcl_cfg->heapsize)) clib_warning ("[%d] vppcom heap allocation failure!", vcm->my_pid); else if (VPPCOM_DEBUG > 0) @@ -1687,7 +1686,7 @@ input_done: unformat_free (input); file_done: - if (fd > 0) + if (fd >= 0) close (fd); } diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c index c90e1331..3a92b2e3 100644 --- a/src/vlib/unix/main.c +++ b/src/vlib/unix/main.c @@ -434,6 +434,10 @@ unix_config (vlib_main_t * vm, unformat_input_t * input) vlib_default_runtime_dir, 0); } + error = setup_signal_handlers (um); + if (error) + return error; + if (um->pidfile) { if ((error = vlib_unix_validate_runtime_file (um, @@ -448,10 +452,6 @@ unix_config (vlib_main_t * vm, unformat_input_t * input) } } - error = setup_signal_handlers (um); - if (error) - return error; - if (!(um->flags & UNIX_FLAG_INTERACTIVE)) { openlog (vm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON); diff --git a/src/vnet/ipsec/ikev2.c b/src/vnet/ipsec/ikev2.c index 296654ec..a3dc7b87 100644 --- a/src/vnet/ipsec/ikev2.c +++ b/src/vnet/ipsec/ikev2.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1595,8 +1596,16 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, + sa->profile->lifetime; if (sa->profile->lifetime_jitter) { + // This is not much better than rand(3), which Coverity warns + // is unsuitable for security applications; random_u32 is + // however fast. If this perturbance to the expiration time + // needs to use a better RNG then we may need to use something + // like /dev/urandom which has significant overhead. + u32 rnd = (u32) (vlib_time_now (vnm->vlib_main) * 1e6); + rnd = random_u32 (&rnd); + child->time_to_expiration += - 1 + (rand () % sa->profile->lifetime_jitter); + 1 + (rnd % sa->profile->lifetime_jitter); } } diff --git a/src/vppinfra/socket.c b/src/vppinfra/socket.c index 7ade440c..37dcbbfd 100644 --- a/src/vppinfra/socket.c +++ b/src/vppinfra/socket.c @@ -359,9 +359,21 @@ clib_socket_init (clib_socket_t * s) && s->flags & SOCKET_ALLOW_GROUP_WRITE) { struct stat st = { 0 }; - stat (((struct sockaddr_un *) &addr)->sun_path, &st); + if (stat (((struct sockaddr_un *) &addr)->sun_path, &st) < 0) + { + error = clib_error_return_unix (0, "stat (fd %d, '%s')", + s->fd, s->config); + goto done; + } st.st_mode |= S_IWGRP; - chmod (((struct sockaddr_un *) &addr)->sun_path, st.st_mode); + if (chmod (((struct sockaddr_un *) &addr)->sun_path, st.st_mode) < + 0) + { + error = + clib_error_return_unix (0, "chmod (fd %d, '%s', mode %o)", + s->fd, s->config, st.st_mode); + goto done; + } } } else -- cgit 1.2.3-korg From 879ace3d3b238ec8db80f52ebfd556aa6f12b4c7 Mon Sep 17 00:00:00 2001 From: Chris Luke Date: Tue, 26 Sep 2017 13:15:16 -0400 Subject: Various fixes for issues found by Coverity (VPP-972) 174267: Revisit this string termination issue 174816: Add check for NULL when trace is enabled 177211: Add notation that mutex is not required here 177117: Added check for log2_page_size == 0 and returns an error if so 163697,163698: Added missing sw_if_index validation Change-Id: I5a76fcf6505c785bfb3269e353360031c6a0fd0f Signed-off-by: Chris Luke --- src/uri/sock_test_server.c | 8 ++++++-- src/vnet/srv6/sr_api.c | 10 ++++++++++ src/vnet/tcp/tcp_input.c | 3 ++- src/vpp-api/vapi/vapi.c | 1 + src/vppinfra/linux/mem.c | 6 ++++++ 5 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src/uri/sock_test_server.c') diff --git a/src/uri/sock_test_server.c b/src/uri/sock_test_server.c index 29adea25..35046aa0 100644 --- a/src/uri/sock_test_server.c +++ b/src/uri/sock_test_server.c @@ -514,7 +514,7 @@ main (int argc, char **argv) continue; } - else if (((char *) conn->buf)[0] != 0) + else if (isascii (conn->buf[0])) { // If it looks vaguely like a string, make sure it's terminated ((char *) conn->buf)[rx_bytes < @@ -536,8 +536,12 @@ main (int argc, char **argv) continue; } - if (isascii (conn->buf[0]) && strlen ((const char *) conn->buf)) + if (isascii (conn->buf[0])) { + // If it looks vaguely like a string, make sure it's terminated + ((char *) conn->buf)[rx_bytes < + conn->buf_size ? rx_bytes : + conn->buf_size - 1] = 0; if (xtra) fprintf (stderr, "ERROR: FIFO not drained in previous test!\n" diff --git a/src/vnet/srv6/sr_api.c b/src/vnet/srv6/sr_api.c index 925b50a1..623f672a 100644 --- a/src/vnet/srv6/sr_api.c +++ b/src/vnet/srv6/sr_api.c @@ -60,6 +60,9 @@ static void vl_api_sr_localsid_add_del_t_handler * char end_psp, u8 behavior, u32 sw_if_index, u32 vlan_index, u32 fib_table, * ip46_address_t *nh_addr, void *ls_plugin_mem) */ + + VALIDATE_SW_IF_INDEX (mp); + rv = sr_cli_localsid (mp->is_del, (ip6_address_t *) & mp->localsid_addr, mp->end_psp, @@ -69,6 +72,8 @@ static void vl_api_sr_localsid_add_del_t_handler ntohl (mp->fib_table), (ip46_address_t *) & mp->nh_addr, NULL); + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SR_LOCALSID_ADD_DEL_REPLY); } @@ -158,6 +163,9 @@ static void vl_api_sr_steering_add_del_t_handler * u32 table_id, ip46_address_t *prefix, u32 mask_width, u32 sw_if_index, * u8 traffic_type) */ + + VALIDATE_SW_IF_INDEX (mp); + rv = sr_steering_policy (mp->is_del, (ip6_address_t *) & mp->bsid_addr, ntohl (mp->sr_policy_index), @@ -166,6 +174,8 @@ static void vl_api_sr_steering_add_del_t_handler ntohl (mp->mask_width), ntohl (mp->sw_if_index), mp->traffic_type); + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SR_STEERING_ADD_DEL_REPLY); } diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index 62dcdc5e..63d6fd87 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -2163,7 +2163,8 @@ tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node, drop: b0->error = error0 ? node->errors[error0] : 0; - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE + ((b0->flags & VLIB_BUFFER_IS_TRACED) && tcp0 != 0)) { t0 = vlib_add_trace (vm, node, b0, sizeof (*t0)); clib_memcpy (&t0->tcp_header, tcp0, sizeof (t0->tcp_header)); diff --git a/src/vpp-api/vapi/vapi.c b/src/vpp-api/vapi/vapi.c index 59415e03..3150d2b4 100644 --- a/src/vpp-api/vapi/vapi.c +++ b/src/vpp-api/vapi/vapi.c @@ -305,6 +305,7 @@ vapi_connect (vapi_ctx_t ctx, const char *name, } ctx->requests = tmp; memset (ctx->requests, 0, size); + /* coverity[MISSING_LOCK] - 177211 requests_mutex is not needed here */ ctx->requests_start = ctx->requests_count = 0; if (chroot_prefix) { diff --git a/src/vppinfra/linux/mem.c b/src/vppinfra/linux/mem.c index df46763a..2d8f593d 100644 --- a/src/vppinfra/linux/mem.c +++ b/src/vppinfra/linux/mem.c @@ -132,6 +132,12 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a) } } log2_page_size = clib_mem_vm_get_log2_page_size (fd); + + if (log2_page_size == 0) + { + err = clib_error_return_unix (0, "cannot determine page size"); + goto error; + } } else /* not CLIB_MEM_VM_F_SHARED */ { -- cgit 1.2.3-korg