From: Dave Wallace Date: Thu, 4 Jan 2018 03:24:41 +0000 (-0500) Subject: LD_PRELOAD: stateless LDP X-Git-Tag: v18.04-rc1~476 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=048b1d6ab787e46ad91574ac950329bccc7fe809 LD_PRELOAD: stateless LDP - Refactor LDP to be stateless. - Use upper bit of fd to identify tag as VCL session. - Clean up debug output. - Add VCOM config env vars for app name and sid bit. - Add VCL get/set attributes - Add VCL poll implementation. Change-Id: I4603ae88254c460a024fdb79fe91c6d1ef9bc7b9 Signed-off-by: Dave Wallace --- diff --git a/src/vcl.am b/src/vcl.am index 763efc220f5..642cb351588 100644 --- a/src/vcl.am +++ b/src/vcl.am @@ -33,7 +33,6 @@ nobase_include_HEADERS += \ libvcl_ldpreload_la_SOURCES += \ vcl/vcom_socket_wrapper.c \ vcl/vcom.c \ - vcl/vcom_socket.c \ $(libvppcom_la_SOURCES) \ $(libvppinfra_la_SOURCES) \ $(libvlib_la_SOURCES) \ @@ -43,8 +42,7 @@ libvcl_ldpreload_la_SOURCES += \ nobase_include_HEADERS += \ vcl/vcom_socket_wrapper.h \ vcl/vcom_glibc_socket.h \ - vcl/vcom.h \ - vcl/vcom_socket.h + vcl/vcom.h noinst_PROGRAMS += \ vcl_test_server \ diff --git a/src/vcl/sock_test.h b/src/vcl/sock_test.h index 281ba6fd473..b4a22adbe20 100644 --- a/src/vcl/sock_test.h +++ b/src/vcl/sock_test.h @@ -157,7 +157,8 @@ sock_test_buf_alloc (sock_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf, { int errno_val = errno; perror ("ERROR in sock_test_buf_alloc()"); - fprintf (stderr, "ERROR: Buffer allocation failed (errno = %d)!\n" + fprintf (stderr, "SOCK_TEST: ERROR: Buffer allocation " + "failed (errno = %d)!\n" " Using buffer size %d instead of desired" " size (%d)\n", errno_val, *bufsize, alloc_size); } @@ -340,8 +341,8 @@ sock_test_read (int fd, uint8_t *buf, uint32_t nbytes, { errno_val = errno; perror ("ERROR in sock_test_read()"); - fprintf (stderr, "ERROR: socket read failed (errno = %d)!\n", - errno_val); + fprintf (stderr, "SOCK_TEST: ERROR: socket read " + "failed (errno = %d)!\n", errno_val); errno = errno_val; } else if (stats) @@ -392,8 +393,8 @@ sock_test_write (int fd, uint8_t *buf, uint32_t nbytes, stats->tx_incomp++; if (verbose) { - printf ("WARNING: bytes written (%d) != bytes to write (%d)!\n", - tx_bytes, nbytes); + printf ("SOCK_TEST: WARNING: bytes written (%d) " + "!= bytes to write (%d)!\n", tx_bytes, nbytes); } } @@ -403,8 +404,8 @@ sock_test_write (int fd, uint8_t *buf, uint32_t nbytes, { errno_val = errno; perror ("ERROR in sock_test_write()"); - fprintf (stderr, "ERROR: socket write failed (errno = %d)!\n", - errno_val); + fprintf (stderr, "SOCK_TEST: ERROR: socket write failed " + "(errno = %d)!\n", errno_val); } else if (stats) stats->tx_bytes += tx_bytes; diff --git a/src/vcl/sock_test_client.c b/src/vcl/sock_test_client.c index 41ee4be9241..563b05fd8dd 100644 --- a/src/vcl/sock_test_client.c +++ b/src/vcl/sock_test_client.c @@ -54,7 +54,8 @@ sock_test_cfg_sync (sock_test_socket_t * socket) sizeof (ctrl->cfg), NULL, ctrl->cfg.verbose); if (tx_bytes < 0) { - fprintf (stderr, "ERROR: write test cfg failed (%d)!\n", tx_bytes); + fprintf (stderr, "CLIENT: ERROR: write test cfg failed (%d)!\n", + tx_bytes); return tx_bytes; } @@ -65,7 +66,7 @@ sock_test_cfg_sync (sock_test_socket_t * socket) if (rl_cfg->magic != SOCK_TEST_CFG_CTRL_MAGIC) { - fprintf (stderr, "ERROR: Bad server reply cfg -- aborting!\n"); + fprintf (stderr, "CLIENT: ERROR: Bad server reply cfg -- aborting!\n"); return -1; } if (socket->cfg.verbose) @@ -76,8 +77,8 @@ sock_test_cfg_sync (sock_test_socket_t * socket) if ((rx_bytes != sizeof (sock_test_cfg_t)) || !sock_test_cfg_verify (rl_cfg, &ctrl->cfg)) { - fprintf (stderr, - "ERROR: Invalid config received from server -- aborting!\n"); + fprintf (stderr, "CLIENT: ERROR: Invalid config received " + "from server -- aborting!\n"); sock_test_cfg_dump (rl_cfg, 1 /* is_client */ ); return -1; } @@ -141,7 +142,8 @@ echo_test_client () if (rv < 0) { perror ("select()"); - fprintf (stderr, "\nERROR: select() failed -- aborting test!\n"); + fprintf (stderr, "\nCLIENT: ERROR: select() failed -- " + "aborting test!\n"); return; } else if (rv == 0) @@ -163,8 +165,8 @@ echo_test_client () &tsock->stats, ctrl->cfg.verbose); if (tx_bytes < 0) { - fprintf (stderr, "\nERROR: sock_test_write(%d) failed " - "-- aborting test!\n", tsock->fd); + fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) " + "failed -- aborting test!\n", tsock->fd); return; } @@ -184,9 +186,9 @@ echo_test_client () tsock->fd, rx_bytes, tsock->rxbuf); if (tsock->stats.rx_bytes != tsock->stats.tx_bytes) - printf - ("WARNING: bytes read (%lu) != bytes written (%lu)!\n", - tsock->stats.rx_bytes, tsock->stats.tx_bytes); + printf ("CLIENT: WARNING: bytes read (%lu) " + "!= bytes written (%lu)!\n", + tsock->stats.rx_bytes, tsock->stats.tx_bytes); } } @@ -265,7 +267,7 @@ stream_test_client (sock_test_t test) if (sock_test_cfg_sync (ctrl)) { - fprintf (stderr, "ERROR: test cfg sync failed -- aborting!"); + fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!"); return; } @@ -312,7 +314,8 @@ stream_test_client (sock_test_t test) if (rv < 0) { perror ("select()"); - fprintf (stderr, "\nERROR: select() failed -- aborting test!\n"); + fprintf (stderr, "\nCLIENT: ERROR: select() failed -- " + "aborting test!\n"); return; } else if (rv == 0) @@ -325,6 +328,15 @@ stream_test_client (sock_test_t test) (tsock->stats.stop.tv_nsec == 0))) continue; + if ((test == SOCK_TEST_TYPE_BI) && + FD_ISSET (tsock->fd, rfdset) && + (tsock->stats.rx_bytes < ctrl->cfg.total_bytes)) + { + (void) sock_test_read (tsock->fd, + (uint8_t *) tsock->rxbuf, + tsock->rxbuf_size, &tsock->stats); + } + if (FD_ISSET (tsock->fd, wfdset) && (tsock->stats.tx_bytes < ctrl->cfg.total_bytes)) { @@ -334,21 +346,12 @@ stream_test_client (sock_test_t test) ctrl->cfg.verbose); if (tx_bytes < 0) { - fprintf (stderr, "\nERROR: sock_test_write(%d) failed " - "-- aborting test!\n", tsock->fd); + fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) " + "failed -- aborting test!\n", tsock->fd); return; } } - if ((test == SOCK_TEST_TYPE_BI) && - FD_ISSET (tsock->fd, rfdset) && - (tsock->stats.rx_bytes < ctrl->cfg.total_bytes)) - { - (void) sock_test_read (tsock->fd, - (uint8_t *) tsock->rxbuf, - tsock->rxbuf_size, &tsock->stats); - } - if (((test == SOCK_TEST_TYPE_UNI) && (tsock->stats.tx_bytes >= ctrl->cfg.total_bytes)) || ((test == SOCK_TEST_TYPE_BI) && @@ -366,7 +369,7 @@ stream_test_client (sock_test_t test) if (sock_test_cfg_sync (ctrl)) { - fprintf (stderr, "ERROR: test cfg sync failed -- aborting!"); + fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!"); return; } @@ -409,7 +412,7 @@ stream_test_client (sock_test_t test) ctrl->cfg.test = SOCK_TEST_TYPE_ECHO; if (sock_test_cfg_sync (ctrl)) - fprintf (stderr, "ERROR: post-test cfg sync failed!"); + fprintf (stderr, "CLIENT: ERROR: post-test cfg sync failed!"); printf ("CLIENT (fd %d): %s-directional Stream Test Complete!\n" SOCK_TEST_BANNER_STRING "\n", ctrl->fd, @@ -491,7 +494,8 @@ sock_test_connect_test_sockets (uint32_t num_test_sockets) { errno_val = errno; perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "ERROR: socket failed (errno = %d)!\n", errno_val); + fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n", + errno_val); return -1; } @@ -518,7 +522,7 @@ sock_test_connect_test_sockets (uint32_t num_test_sockets) { errno_val = errno; perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "ERROR: socket failed (errno = %d)!\n", + fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n", errno_val); return tsock->fd; } @@ -539,8 +543,8 @@ sock_test_connect_test_sockets (uint32_t num_test_sockets) { errno_val = errno; perror ("ERROR in sock_test_connect_test_sockets()"); - fprintf (stderr, "ERROR: connect failed (errno = %d)!\n", - errno_val); + fprintf (stderr, "CLIENT: ERROR: connect failed " + "(errno = %d)!\n", errno_val); return -1; } tsock->cfg = ctrl->cfg; @@ -562,7 +566,7 @@ dump_help (void) { #define INDENT "\n " - printf ("Test configuration commands:" + printf ("CLIENT: Test configuration commands:" INDENT SOCK_TEST_TOKEN_HELP "\t\t\tDisplay help." INDENT SOCK_TEST_TOKEN_EXIT @@ -600,8 +604,8 @@ cfg_txbuf_size_set (void) sock_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); } else - fprintf (stderr, - "ERROR: Invalid txbuf size (%lu) < minimum buf size (%u)!\n", + fprintf (stderr, "CLIENT: ERROR: Invalid txbuf size (%lu) < " + "minimum buf size (%u)!\n", txbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN); } @@ -621,7 +625,7 @@ cfg_num_writes_set (void) } else { - fprintf (stderr, "ERROR: invalid num writes: %u\n", num_writes); + fprintf (stderr, "CLIENT: ERROR: invalid num writes: %u\n", num_writes); } } @@ -643,7 +647,8 @@ cfg_num_test_sockets_set (void) } else { - fprintf (stderr, "ERROR: invalid num test sockets: %u, (%d max)\n", + fprintf (stderr, "CLIENT: ERROR: invalid num test sockets: " + "%u, (%d max)\n", num_test_sockets, SOCK_TEST_CFG_MAX_TEST_SCKTS); } } @@ -664,8 +669,8 @@ cfg_rxbuf_size_set (void) sock_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ ); } else - fprintf (stderr, - "ERROR: Invalid rxbuf size (%lu) < minimum buf size (%u)!\n", + fprintf (stderr, "CLIENT: ERROR: Invalid rxbuf size (%lu) < " + "minimum buf size (%u)!\n", rxbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN); } @@ -772,14 +777,15 @@ main (int argc, char **argv) if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sockets) != 1) if (sscanf (optarg, "%u", &ctrl->cfg.num_test_sockets) != 1) { - fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c); + fprintf (stderr, "CLIENT: ERROR: Invalid value for " + "option -%c!\n", c); print_usage_and_exit (); } if (!ctrl->cfg.num_test_sockets || (ctrl->cfg.num_test_sockets > FD_SETSIZE)) { - fprintf (stderr, "ERROR: Invalid number of sockets (%d)" - "specified for option -%c!\n" + fprintf (stderr, "CLIENT: ERROR: Invalid number of " + "sockets (%d) specified for option -%c!\n" " Valid range is 1 - %d\n", ctrl->cfg.num_test_sockets, c, FD_SETSIZE); print_usage_and_exit (); @@ -787,7 +793,7 @@ main (int argc, char **argv) break; case 'w': - fprintf (stderr, "Writing test results to files is TBD.\n"); + fprintf (stderr, "CLIENT: Writing test results to files is TBD.\n"); break; case 'X': @@ -797,8 +803,8 @@ main (int argc, char **argv) case 'E': if (strlen (optarg) > ctrl->txbuf_size) { - fprintf (stderr, - "ERROR: Option -%c value larger than txbuf size (%d)!\n", + fprintf (stderr, "CLIENT: ERROR: Option -%c value " + "larger than txbuf size (%d)!\n", optopt, ctrl->txbuf_size); print_usage_and_exit (); } @@ -810,13 +816,15 @@ main (int argc, char **argv) if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sockets) != 1) if (sscanf (optarg, "%d", &ctrl->cfg.num_test_sockets) != 1) { - fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c); + fprintf (stderr, "CLIENT: ERROR: Invalid value for " + "option -%c!\n", c); print_usage_and_exit (); } if (ctrl->cfg.num_test_sockets > SOCK_TEST_CFG_MAX_TEST_SCKTS) { - fprintf (stderr, "ERROR: value greater than max number test" - " sockets (%d)!", SOCK_TEST_CFG_MAX_TEST_SCKTS); + fprintf (stderr, "CLIENT: ERROR: value greater than max " + "number test sockets (%d)!", + SOCK_TEST_CFG_MAX_TEST_SCKTS); print_usage_and_exit (); } break; @@ -825,7 +833,8 @@ main (int argc, char **argv) if (sscanf (optarg, "0x%lx", &ctrl->cfg.num_writes) != 1) if (sscanf (optarg, "%ld", &ctrl->cfg.num_writes) != 1) { - fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c); + fprintf (stderr, "CLIENT: ERROR: Invalid value for " + "option -%c!\n", c); print_usage_and_exit (); } ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size; @@ -835,7 +844,8 @@ main (int argc, char **argv) if (sscanf (optarg, "0x%lx", &ctrl->cfg.rxbuf_size) != 1) if (sscanf (optarg, "%ld", &ctrl->cfg.rxbuf_size) != 1) { - fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c); + fprintf (stderr, "CLIENT: ERROR: Invalid value for " + "option -%c!\n", c); print_usage_and_exit (); } if (ctrl->cfg.rxbuf_size >= SOCK_TEST_CFG_BUF_SIZE_MIN) @@ -847,8 +857,8 @@ main (int argc, char **argv) } else { - fprintf (stderr, - "ERROR: rxbuf size (%lu) less than minumum (%u)\n", + fprintf (stderr, "CLIENT: ERROR: rxbuf size (%lu) " + "less than minumum (%u)\n", ctrl->cfg.rxbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN); print_usage_and_exit (); } @@ -859,7 +869,8 @@ main (int argc, char **argv) if (sscanf (optarg, "0x%lx", &ctrl->cfg.txbuf_size) != 1) if (sscanf (optarg, "%ld", &ctrl->cfg.txbuf_size) != 1) { - fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c); + fprintf (stderr, "CLIENT: ERROR: Invalid value " + "for option -%c!\n", c); print_usage_and_exit (); } if (ctrl->cfg.txbuf_size >= SOCK_TEST_CFG_BUF_SIZE_MIN) @@ -873,8 +884,8 @@ main (int argc, char **argv) } else { - fprintf (stderr, - "ERROR: txbuf size (%lu) less than minumum (%u)!\n", + fprintf (stderr, "CLIENT: ERROR: txbuf size (%lu) " + "less than minumum (%u)!\n", ctrl->cfg.txbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN); print_usage_and_exit (); } @@ -901,16 +912,17 @@ main (int argc, char **argv) case 'R': case 'T': case 'w': - fprintf (stderr, "ERROR: Option -%c requires an argument.\n", - optopt); + fprintf (stderr, "CLIENT: ERROR: Option -%c " + "requires an argument.\n", optopt); break; default: if (isprint (optopt)) - fprintf (stderr, "ERROR: Unknown option `-%c'.\n", optopt); + fprintf (stderr, "CLIENT: ERROR: Unknown " + "option `-%c'.\n", optopt); else - fprintf (stderr, "ERROR: Unknown option character `\\x%x'.\n", - optopt); + fprintf (stderr, "CLIENT: ERROR: Unknown " + "option character `\\x%x'.\n", optopt); } /* fall thru */ case 'h': @@ -920,7 +932,7 @@ main (int argc, char **argv) if (argc < (optind + 2)) { - fprintf (stderr, "ERROR: Insufficient number of arguments!\n"); + fprintf (stderr, "CLIENT: ERROR: Insufficient number of arguments!\n"); print_usage_and_exit (); } @@ -949,7 +961,8 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: socket failed (errno = %d)!\n", errno_val); + fprintf (stderr, "CLIENT: ERROR: socket " + "failed (errno = %d)!\n", errno_val); return ctrl->fd; } @@ -986,7 +999,7 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: connect failed (errno = %d)!\n", + fprintf (stderr, "CLIENT: ERROR: connect failed (errno = %d)!\n", errno_val); return -1; } @@ -1053,7 +1066,7 @@ main (int argc, char **argv) memset (ctrl->txbuf, 0, ctrl->txbuf_size); memset (ctrl->rxbuf, 0, ctrl->rxbuf_size); - printf ("\nType some characters and hit \n" + printf ("\nCLIENT: Type some characters and hit \n" "('" SOCK_TEST_TOKEN_HELP "' for help): "); if (fgets (ctrl->txbuf, ctrl->txbuf_size, stdin) != NULL) diff --git a/src/vcl/sock_test_server.c b/src/vcl/sock_test_server.c index b30dcf949b2..75ee1d72c74 100644 --- a/src/vcl/sock_test_server.c +++ b/src/vcl/sock_test_server.c @@ -138,8 +138,8 @@ conn_pool_expand (size_t expand_size) { int errno_val = errno; perror ("ERROR in conn_pool_expand()"); - fprintf (stderr, "ERROR: Memory allocation failed (errno = %d)!\n", - errno_val); + fprintf (stderr, "SERVER: ERROR: Memory allocation " + "failed (errno = %d)!\n", errno_val); } } @@ -295,13 +295,12 @@ new_client (void) conn = conn_pool_alloc (); if (!conn) { - fprintf (stderr, "\nERROR: No free connections!\n"); + fprintf (stderr, "\nSERVER: ERROR: No free connections!\n"); return; } #ifdef VCL_TEST - client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, 0, - -1.0 /* wait forever */ ); + client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, 0); if (client_fd < 0) errno = -client_fd; #elif HAVE_ACCEPT4 @@ -314,7 +313,8 @@ new_client (void) int errno_val; errno_val = errno; perror ("ERROR in new_client()"); - fprintf (stderr, "ERROR: accept failed (errno = %d)!\n", errno_val); + fprintf (stderr, "SERVER: ERROR: accept failed " + "(errno = %d)!\n", errno_val); return; } @@ -345,7 +345,7 @@ new_client (void) int errno_val; errno_val = errno; perror ("ERROR in new_client()"); - fprintf (stderr, "ERROR: epoll_ctl failed (errno = %d)!\n", + fprintf (stderr, "SERVER: ERROR: epoll_ctl failed (errno = %d)!\n", errno_val); } else @@ -404,7 +404,8 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: socket() failed (errno = %d)!\n", errno_val); + fprintf (stderr, "SERVER: ERROR: socket() failed " + "(errno = %d)!\n", errno_val); return ssm->listen_fd; } @@ -426,31 +427,6 @@ main (int argc, char **argv) errno = -rv; rv = -1; } - -#if VPPCOM_SESSION_ATTR_UNIT_TEST - buflen = BUFLEN; - if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS, - buffer, &buflen) != VPPCOM_OK) - printf ("\nGET_FLAGS0: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n"); - buflen = BUFLEN; - *flags = O_RDWR | O_NONBLOCK; - if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_SET_FLAGS, - buffer, &buflen) != VPPCOM_OK) - printf ("\nSET_FLAGS1: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n"); - buflen = BUFLEN; - if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS, - buffer, &buflen) != VPPCOM_OK) - printf ("\nGET_FLAGS1:Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n"); - *flags = O_RDWR; - buflen = BUFLEN; - if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_SET_FLAGS, - buffer, &buflen) != VPPCOM_OK) - printf ("\nSET_FLAGS2: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n"); - buflen = BUFLEN; - if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS, - buffer, &buflen) != VPPCOM_OK) - printf ("\nGET_FLAGS2:Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n"); -#endif #else rv = bind (ssm->listen_fd, (struct sockaddr *) &servaddr, sizeof (servaddr)); @@ -459,7 +435,8 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: bind failed (errno = %d)!\n", errno_val); + fprintf (stderr, "SERVER: ERROR: bind failed (errno = %d)!\n", + errno_val); return rv; } @@ -477,7 +454,8 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: listen failed (errno = %d)!\n", errno_val); + fprintf (stderr, "SERVER: ERROR: listen failed " + "(errno = %d)!\n", errno_val); return rv; } @@ -503,7 +481,7 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: epoll_create failed (errno = %d)!\n", + fprintf (stderr, "SERVER: ERROR: epoll_create failed (errno = %d)!\n", errno_val); return ssm->epfd; } @@ -522,7 +500,8 @@ main (int argc, char **argv) { errno_val = errno; perror ("ERROR in main()"); - fprintf (stderr, "ERROR: epoll_ctl failed (errno = %d)!\n", errno_val); + fprintf (stderr, "SERVER: ERROR: epoll_ctl failed " + "(errno = %d)!\n", errno_val); return rv; } #endif @@ -545,7 +524,7 @@ main (int argc, char **argv) if (rv < 0) { perror ("select()"); - fprintf (stderr, "\nERROR: select() failed -- aborting!\n"); + fprintf (stderr, "\nSERVER: ERROR: select() failed -- aborting!\n"); main_rv = -1; goto done; } @@ -575,13 +554,14 @@ main (int argc, char **argv) if (num_ev < 0) { perror ("epoll_wait()"); - fprintf (stderr, "\nERROR: epoll_wait() failed -- aborting!\n"); + fprintf (stderr, "\nSERVER: ERROR: epoll_wait() " + "failed -- aborting!\n"); main_rv = -1; goto done; } if (num_ev == 0) { - fprintf (stderr, "\nepoll_wait() timeout!\n"); + fprintf (stderr, "\nSERVER: epoll_wait() timeout!\n"); continue; } for (i = 0; i < num_ev; i++) @@ -601,32 +581,6 @@ main (int argc, char **argv) if (EPOLLIN & ssm->wait_events[i].events) #endif { -#ifdef VCL_TEST -#if VPPCOM_SESSION_ATTR_UNIT_TEST - { - vppcom_endpt_t ep; - uint8_t addr[16]; - - ep.ip = addr; - buflen = BUFLEN; - if (vppcom_session_attr (client_fd, VPPCOM_ATTR_GET_NREAD, - buffer, &buflen) < VPPCOM_OK) - printf ("\nNREAD: Oh no, Mr. " - "Biiiiiiiiiiiilllllll ! ! ! !\n"); - buflen = sizeof (ep); - if (vppcom_session_attr (client_fd, - VPPCOM_ATTR_GET_PEER_ADDR, - &ep, &buflen) != VPPCOM_OK) - printf ("\nGET_PEER_ADDR: Oh no, Mr. " - "Biiiiiiiiiiiilllllll ! ! ! !\n"); - buflen = sizeof (ep); - if (vppcom_session_attr (client_fd, VPPCOM_ATTR_GET_LCL_ADDR, - &ep, &buflen) != VPPCOM_OK) - printf ("\nGET_LCL_ADDR: Oh no, Mr. " - "Biiiiiiiiiiiilllllll ! ! ! !\n"); - } -#endif -#endif rx_bytes = sock_test_read (client_fd, conn->buf, conn->buf_size, &conn->stats); if (rx_bytes > 0) @@ -697,7 +651,8 @@ main (int argc, char **argv) break; default: - fprintf (stderr, "ERROR: Unknown test type!\n"); + fprintf (stderr, + "SERVER: ERROR: Unknown test type!\n"); sock_test_cfg_dump (rx_cfg, 0 /* is_client */ ); break; } @@ -735,13 +690,15 @@ main (int argc, char **argv) if (isascii (conn->buf[0])) { - // If it looks vaguely like a string, make sure it's terminated + /* 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" + fprintf (stderr, "SERVER: 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); diff --git a/src/vcl/vcom.c b/src/vcl/vcom.c index 4f8435f41bf..7c163112ba1 100644 --- a/src/vcl/vcom.c +++ b/src/vcl/vcom.c @@ -20,21 +20,15 @@ #include #include #include +#include #include #include #include #include -#include - -/* GCC have printf type attribute check. */ -#ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT -#define PRINTF_ATTRIBUTE(a,b) \ - __attribute__ ((__format__ (__printf__, a, b))) -#else -#define PRINTF_ATTRIBUTE(a,b) -#endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */ +#include +#include #define HAVE_CONSTRUCTOR_ATTRIBUTE #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE @@ -52,3230 +46,3351 @@ #define DESTRUCTOR_ATTRIBUTE #endif -#define HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE \ - __attribute__((no_sanitize_address)) -#else -#define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE -#endif - -#define VCOM_SOCKET_FD_MAX 0x10000 - -static char vcom_app_name[MAX_VCOM_APP_NAME]; +typedef struct +{ + int init; + char app_name[VCOM_APP_NAME_MAX]; + u32 sid_bit_val; + u32 sid_bit_mask; + u32 debug; + u8 *io_buffer; + clib_time_t clib_time; + clib_bitmap_t *rd_bitmap; + clib_bitmap_t *wr_bitmap; + clib_bitmap_t *ex_bitmap; + clib_bitmap_t *sid_rd_bitmap; + clib_bitmap_t *sid_wr_bitmap; + clib_bitmap_t *sid_ex_bitmap; + clib_bitmap_t *libc_rd_bitmap; + clib_bitmap_t *libc_wr_bitmap; + clib_bitmap_t *libc_ex_bitmap; + vcl_poll_t *vcl_poll; + u8 select_vcl; + u8 epoll_wait_vcl; +} vcom_main_t; +#define VCOM_DEBUG vcom->debug + +static vcom_main_t vcom_main = { + .sid_bit_val = (1 << VCOM_SID_BIT_MIN), + .sid_bit_mask = (1 << VCOM_SID_BIT_MIN) - 1, + .debug = VCOM_DEBUG_INIT, +}; + +static vcom_main_t *vcom = &vcom_main; /* * RETURN: 0 on success or -1 on error. * */ -int -vcom_set_app_name (char *__app_name) +static inline void +vcom_set_app_name (char *app_name) { - return snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-%s-%d", - __app_name, getpid ()) < 0 ? -1 : 0; + int rv = snprintf (vcom->app_name, VCOM_APP_NAME_MAX, + "vcom-%d-%s", getpid (), app_name); + + if (rv >= VCOM_APP_NAME_MAX) + app_name[VCOM_APP_NAME_MAX - 1] = 0; } -static char * +static inline char * vcom_get_app_name () { - if (vcom_app_name[0] == '\0') - { - snprintf (vcom_app_name, MAX_VCOM_APP_NAME, "vcom-app-%d", getpid ()); - } - return vcom_app_name; -} + if (vcom->app_name[0] == '\0') + vcom_set_app_name ("app"); -/* - * 1 if init, 0 otherwise - */ -static int is_vcom_init; - -/* - * TBD: Make it thread safe - */ + return vcom->app_name; +} -/* - * constructor function called before main is called - * RETURN: 0 on success -1 on failure - * */ static inline int -vcom_init (void) +vcom_fd_from_sid (u32 sid) { - pid_t pid = getpid (); - int rv; - - if (!is_vcom_init) - { - rv = vppcom_app_create (vcom_get_app_name ()); - if (rv) - { - printf ("\n[%d] vcom_init...failed!\n", pid); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_init: vppcom_app_create failed!\n", pid); - return rv; - } - if (vcom_socket_main_init () != 0) - { - printf ("\n[%d] vcom_init...failed!\n", pid); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_init: vcom_socket_main_init failed!\n", pid); - return -1; - } - - is_vcom_init = 1; - printf ("\n[%d] vcom_init...done!\n", pid); - } - return 0; + if (PREDICT_FALSE (sid >= vcom->sid_bit_val)) + return -EMFILE; + else + return (sid | vcom->sid_bit_val); } -static inline void -vcom_destroy (void) +static inline int +vcom_fd_is_sid (int fd) { - pid_t pid = getpid (); - - if (is_vcom_init) - { - vcom_socket_main_destroy (); - vppcom_app_destroy (); - is_vcom_init = 0; - fprintf (stderr, "\n[%d] vcom_destroy...done!\n", pid); - } + return ((u32) fd & vcom->sid_bit_val) ? 1 : 0; } -static inline int -is_vcom_socket_fd (int fd) +static inline u32 +vcom_sid_from_fd (int fd) { - return vcom_socket_is_vcom_fd (fd); + return (vcom_fd_is_sid (fd) ? ((u32) fd & vcom->sid_bit_mask) : + INVALID_SESSION_ID); } static inline int -is_vcom_epfd (int epfd) +vcom_init (void) { - return vcom_socket_is_vcom_epfd (epfd); -} + int rv = 0; + if (PREDICT_FALSE (!vcom->init)) + { + vcom->init = 1; + rv = vppcom_app_create (vcom_get_app_name ()); + if (rv == VPPCOM_OK) + { + char *env_var_str = getenv (VCOM_ENV_DEBUG); + if (env_var_str) + { + u32 tmp; + if (sscanf (env_var_str, "%u", &tmp) != 1) + clib_warning ("LDP<%d>: WARNING: Invalid VCOM debug level " + "specified in the env var " VCOM_ENV_DEBUG + " (%s)!", getpid (), env_var_str); + else + { + vcom->debug = tmp; + clib_warning ("LDP<%d>: configured VCOM debug level (%u) " + "from the env var " VCOM_ENV_DEBUG "!", + getpid (), vcom->debug); + } + } -/* - * - * Generic glibc fd api - * - */ + env_var_str = getenv (VCOM_ENV_APP_NAME); + if (env_var_str) + { + vcom_set_app_name (env_var_str); + clib_warning ("LDP<%d>: configured VCOM app name (%s) " + "from the env var " VCOM_ENV_APP_NAME "!", + getpid (), vcom->app_name); + } -/* Close the file descriptor FD. + env_var_str = getenv (VCOM_ENV_SID_BIT); + if (env_var_str) + { + u32 sb; + if (sscanf (env_var_str, "%u", &sb) != 1) + { + clib_warning ("LDP<%d>: WARNING: Invalid VCOM sid bit " + "specified in the env var " + VCOM_ENV_SID_BIT " (%s)!" + "sid bit value %d (0x%x)", + getpid (), env_var_str, + vcom->sid_bit_val, vcom->sid_bit_val); + } + else if (sb < VCOM_SID_BIT_MIN) + { + vcom->sid_bit_val = (1 << VCOM_SID_BIT_MIN); + vcom->sid_bit_mask = vcom->sid_bit_val - 1; + + clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) " + "specified in the env var " + VCOM_ENV_SID_BIT " (%s) is too small. " + "Using VCOM_SID_BIT_MIN (%d)! " + "sid bit value %d (0x%x)", + getpid (), sb, env_var_str, VCOM_SID_BIT_MIN, + vcom->sid_bit_val, vcom->sid_bit_val); + } + else if (sb > VCOM_SID_BIT_MAX) + { + vcom->sid_bit_val = (1 << VCOM_SID_BIT_MAX); + vcom->sid_bit_mask = vcom->sid_bit_val - 1; + + clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) " + "specified in the env var " + VCOM_ENV_SID_BIT " (%s) is too big. " + "Using VCOM_SID_BIT_MAX (%d)! " + "sid bit value %d (0x%x)", + getpid (), sb, env_var_str, VCOM_SID_BIT_MAX, + vcom->sid_bit_val, vcom->sid_bit_val); + } + else + { + vcom->sid_bit_val = (1 << sb); + vcom->sid_bit_mask = vcom->sid_bit_val - 1; - This function is a cancellation point and therefore - not marked with __THROW. */ -/* - * PRE: is_vcom_socket_fd(__fd) == 1 - * RETURN: 0 on success and -1 for errors. - * */ -int -vcom_close (int __fd) -{ - if (vcom_init () != 0) - { - return -1; - } + clib_warning ("LDP<%d>: configured VCOM sid bit (%u) " + "from " VCOM_ENV_SID_BIT + "! sid bit value %d (0x%x)", getpid (), + sb, vcom->sid_bit_val, vcom->sid_bit_val); + } + } - if (vcom_socket_close (__fd) != 0) - { - return -1; + clib_time_init (&vcom->clib_time); + clib_warning ("LDP<%d>: VCOM initialization: done!", getpid ()); + } + else + { + fprintf (stderr, "\nLDP<%d>: ERROR: vcom_init: vppcom_app_create()" + " failed! rv = %d (%s)\n", + getpid (), rv, vppcom_retval_str (rv)); + vcom->init = 0; + } } - - return 0; + return rv; } -/* - * RETURN: 0 on success, or -1 on error - */ int -close (int __fd) +close (int fd) { int rv; - pid_t pid = getpid (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd) || is_vcom_epfd (__fd)) + if (sid != INVALID_SESSION_ID) { + int epfd; + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); + if (epfd > 0) + { + func_str = "libc_close"; + + if (VCOM_DEBUG > 0) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)", + getpid (), fd, fd, func_str, epfd, epfd); + + rv = libc_close (epfd); + if (rv < 0) + { + u32 size = sizeof (epfd); + epfd = 0; + + (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD, + &epfd, &size); + } + } + else if (PREDICT_FALSE (epfd < 0)) + { + errno = -epfd; + rv = -1; + goto done; + } + + func_str = "vppcom_session_close"; + if (VCOM_DEBUG > 0) - fprintf (stderr, "[%d] close: fd %d\n", pid, __fd); - rv = vcom_close (__fd); - if (VCOM_DEBUG > 0) - fprintf (stderr, "[%d] close: vcom_close() returned %d\n", pid, rv); - if (rv != 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + + rv = vppcom_session_close (sid); + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; } - return 0; } - return libc_close (__fd); -} + else + { + func_str = "libc_close"; -/* Read NBYTES into BUF from FD. Return the - number read, -1 for errors or 0 for EOF. + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s()", + getpid (), fd, fd, func_str); - This function is a cancellation point and therefore - not marked with __THROW. */ -ssize_t -vcom_read (int __fd, void *__buf, size_t __nbytes) -{ - if (vcom_init () != 0) - { - return -1; + rv = libc_close (fd); } - return vcom_socket_read (__fd, __buf, __nbytes); +done: + if (VCOM_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; } ssize_t -read (int __fd, void *__buf, size_t __nbytes) +read (int fd, void *buf, size_t nbytes) { - ssize_t size = 0; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); + ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { + func_str = "vppcom_session_read"; + if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] read:1 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __nbytes); - size = vcom_read (__fd, __buf, __nbytes); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] read:2 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __nbytes); + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, nbytes %u", getpid (), + fd, fd, func_str, sid, sid, buf, nbytes); + + size = vppcom_session_read (sid, buf, nbytes); if (size < 0) { errno = -size; - return -1; + size = -1; } - return size; } - return libc_read (__fd, __buf, __nbytes); -} - -ssize_t -vcom_readv (int __fd, const struct iovec * __iov, int __iovcnt) -{ - if (vcom_init () != 0) + else { - return -1; + func_str = "libc_read"; + + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, nbytes %u", getpid (), + fd, fd, func_str, buf, nbytes); + + size = libc_read (fd, buf, nbytes); } - return vcom_socket_readv (__fd, __iov, __iovcnt); + if (VCOM_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; } ssize_t -readv (int __fd, const struct iovec * __iov, int __iovcnt) +readv (int fd, const struct iovec * iov, int iovcnt) { + const char *func_str; ssize_t size = 0; + u32 sid = vcom_sid_from_fd (fd); + int rv, i, total = 0; - if (is_vcom_socket_fd (__fd)) + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - size = vcom_readv (__fd, __iov, __iovcnt); - if (size < 0) + func_str = "vppcom_session_read"; + do { - errno = -size; - return -1; + for (i = 0; i < iovcnt; ++i) + { + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: " + "sid %u (0x%x), iov %p, iovcnt %d, total %d", + getpid (), fd, fd, func_str, i, sid, sid, + iov, iovcnt, total); + + rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len); + if (rv < 0) + break; + else + { + total += rv; + if (rv < iov[i].iov_len) + { + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): " + "rv (%d) < iov[%d].iov_len (%d)", + getpid (), fd, fd, rv, i, + iov[i].iov_len); + break; + } + } + } + } + while ((rv >= 0) && (total == 0)); + + if (rv < 0) + { + errno = -rv; + size = -1; } - return size; + else + size = total; } else - return libc_readv (__fd, __iov, __iovcnt); -} + { + func_str = "libc_readv"; -/* Write N bytes of BUF to FD. Return the number written, or -1. + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt); - This function is a cancellation point and therefore - not marked with __THROW. */ -ssize_t -vcom_write (int __fd, const void *__buf, size_t __n) -{ - if (vcom_init () != 0) - { - return -1; + size = libc_readv (fd, iov, iovcnt); } - return vcom_socket_write (__fd, (void *) __buf, __n); + if (VCOM_DEBUG > 2) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); + } + return size; } ssize_t -write (int __fd, const void *__buf, size_t __n) +write (int fd, const void *buf, size_t nbytes) { + const char *func_str; ssize_t size = 0; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { + func_str = "vppcom_session_write"; + if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] write:1 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __n); - size = vcom_write (__fd, __buf, __n); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d][%lu (0x%lx)] write:2 " - "'%04d'='%04d', '%p', '%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - (int) size, __fd, __buf, (int) __n); + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, nbytes %u", getpid (), + fd, fd, func_str, sid, sid, buf, nbytes); + + size = vppcom_session_write (sid, (void *) buf, nbytes); if (size < 0) { errno = -size; - return -1; + size = -1; } - return size; } - return libc_write (__fd, __buf, __n); -} - -ssize_t -vcom_writev (int __fd, const struct iovec * __iov, int __iovcnt) -{ - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_write"; - return vcom_socket_writev (__fd, __iov, __iovcnt); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, nbytes %u", getpid (), + fd, fd, func_str, buf, nbytes); -ssize_t -writev (int __fd, const struct iovec * __iov, int __iovcnt) -{ - ssize_t size = 0; + size = libc_write (fd, buf, nbytes); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - size = vcom_writev (__fd, __iov, __iovcnt); if (size < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - else - return libc_writev (__fd, __iov, __iovcnt); + return size; } -/* Do the file control operation described by CMD on FD. - The remaining arguments are interpreted depending on CMD. - - This function is a cancellation point and therefore - not marked with __THROW. */ -int -vcom_fcntl_va (int __fd, int __cmd, va_list __ap) +ssize_t +writev (int fd, const struct iovec * iov, int iovcnt) { - if (vcom_init () != 0) - { - return -1; - } + const char *func_str; + ssize_t size = 0, total = 0; + u32 sid = vcom_sid_from_fd (fd); + int rv, i; - return vcom_socket_fcntl_va (__fd, __cmd, __ap); -} + /* + * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV. + */ -int -vcom_fcntl (int __fd, int __cmd, ...) -{ - int rv = -1; - va_list ap; + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { - va_start (ap, __cmd); - rv = vcom_fcntl_va (__fd, __cmd, ap); - va_end (ap); - } - return rv; -} - -int -fcntl (int __fd, int __cmd, ...) -{ - int rv; - va_list ap; - pid_t pid = getpid (); + func_str = "vppcom_session_write"; + do + { + for (i = 0; i < iovcnt; ++i) + { + if (VCOM_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: " + "sid %u (0x%x), buf %p, nbytes %ld, total %ld", + __func__, __LINE__, getpid (), fd, fd, func_str, + i, sid, sid, iov[i].iov_base, iov[i].iov_len, total); + + rv = vppcom_session_write (sid, iov[i].iov_base, + iov[i].iov_len); + if (rv < 0) + break; + else + { + total += rv; + if (rv < iov[i].iov_len) + { + if (VCOM_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): " + "rv (%d) < iov[%d].iov_len (%ld)", + __func__, __LINE__, getpid (), fd, fd, + rv, i, iov[i].iov_len); + break; + } + } + } + } + while ((rv >= 0) && (total == 0)); - va_start (ap, __cmd); - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_fcntl_va (__fd, __cmd, ap); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] fcntl: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __cmd); if (rv < 0) { errno = -rv; - rv = -1; + size = -1; } - goto out; + else + size = total; } - rv = libc_vfcntl (__fd, __cmd, ap); + else + { + func_str = "libc_writev"; -out: - va_end (ap); - return rv; -} + if (VCOM_DEBUG > 4) + printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): " + "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (), + fd, fd, func_str, iov, iovcnt); -int -vcom_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap) -{ - if (vcom_init () != 0) - { - return -1; + size = libc_writev (fd, iov, iovcnt); } - return vcom_socket_ioctl_va (__fd, __cmd, __ap); + if (VCOM_DEBUG > 4) + { + if (size < 0) + { + int errno_val = errno; + perror (func_str); + fprintf (stderr, + "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd, + fd, func_str, size, errno_val); + errno = errno_val; + } + else + printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n", + __func__, __LINE__, getpid (), fd, fd, size); + } + return size; } int -vcom_ioctl (int __fd, unsigned long int __cmd, ...) +fcntl (int fd, int cmd, ...) { - int rv = -1; + const char *func_str = __func__; + int rv = 0; va_list ap; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + va_start (ap, cmd); + if (sid != INVALID_SESSION_ID) { - va_start (ap, __cmd); - rv = vcom_ioctl_va (__fd, __cmd, ap); - va_end (ap); - } - return rv; -} + int flags = va_arg (ap, int); + u32 size; -int -ioctl (int __fd, unsigned long int __cmd, ...) -{ - int rv; - va_list ap; - pid_t pid = getpid (); + size = sizeof (flags); + rv = -EOPNOTSUPP; + switch (cmd) + { + case F_SETFL: + func_str = "vppcom_session_attr[SET_FLAGS]"; + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x) flags %d (0x%x), size %d", + getpid (), fd, fd, func_str, sid, sid, + flags, flags, size); - va_start (ap, __cmd); - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_ioctl_va (__fd, __cmd, ap); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] ioctl: " - "'%04d'='%04d', '%04ld'\n", pid, rv, __fd, __cmd); + rv = + vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size); + break; + + case F_GETFL: + func_str = "vppcom_session_attr[GET_FLAGS]"; + if (VCOM_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid, + sid, flags, flags, size); + + rv = + vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size); + if (rv == VPPCOM_OK) + { + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): " + "%s() returned flags %d (0x%x)", + getpid (), fd, fd, cmd, func_str, flags, flags); + rv = flags; + } + break; + + default: + rv = -EOPNOTSUPP; + break; + } if (rv < 0) { errno = -rv; rv = -1; } - goto out; } - rv = libc_vioctl (__fd, __cmd, ap); - -out: - va_end (ap); - return rv; -} - -/* - * Check the first NFDS descriptors each in READFDS (if not NULL) for - * read readiness, in WRITEFDS (if not NULL) for write readiness, - * and in EXCEPTFDS (if not NULL) for exceptional conditions. - * If TIMEOUT is not NULL, time out after waiting the interval - * specified therein. Returns the number of ready descriptors, - * or -1 for errors. - * - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ - -/* - * clear all vcom FDs from fd_sets __readfds, __writefds and - * __exceptfds and update the new nfds - * - * new nfds is the highest-numbered file descriptor - * in any of the three sets, plus 1 - * - * Return the number of file descriptors contained in the - * three descriptor sets. ie. the total number of the bits - * that are set in __readfds, __writefds and __exceptfds - */ -static inline int -vcom_fd_clear (int __nfds, - int *__new_nfds, - fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd = 0; - - - /* clear all vcom fd from the sets */ - for (fd = 0; fd < __nfds; fd++) - { - - /* clear vcom fd from set */ - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - FD_CLR (fd, (F)); \ - } \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - /* - * compute nfd and __new_nfds - */ - for (fd = 0; fd < __nfds; fd++) - { - - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (fd > max_fd) \ - { \ - max_fd = fd; \ - } \ - ++nfd; \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - *__new_nfds = max_fd != -1 ? max_fd + 1 : 0; - return nfd; -} - -/* - * Return the number of file descriptors contained in the - * three descriptor sets. ie. the total number of the bits - * that are set in __readfds, __writefds and __exceptfds - */ -static inline int -vcom_fd_set (int __nfds, - /* dest */ - int *__new_nfds, - fd_set * __restrict __readfds, - fd_set * __restrict __writefds, fd_set * __restrict __exceptfds, - /* src */ - fd_set * __restrict __saved_readfds, - fd_set * __restrict __saved_writefds, - fd_set * __restrict __saved_exceptfds) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd = 0; - - for (fd = 0; fd < __nfds; fd++) - { - /* - * F fd set - * S saved fd set - */ -#define _(S,F) \ - if ((F) && (S) && FD_ISSET (fd, (S))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - FD_SET (fd, (F)); \ - } \ - } - - - _(__saved_readfds, __readfds); - _(__saved_writefds, __writefds); -#undef _ - } - - - /* - * compute nfd and __new_nfds - */ - for (fd = 0; fd < __nfds; fd++) + else { + func_str = "libc_vfcntl"; - /* - * F fd set - */ -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (fd > max_fd) \ - { \ - max_fd = fd; \ - } \ - ++nfd; \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - } - - *__new_nfds = max_fd != -1 ? max_fd + 1 : 0; - return nfd; -} - -/* - * split select sets(src) into - * vcom sets(dest1) and libc sets(dest2) - */ -static inline void -vcom_fd_set_split ( - /* src, select sets */ - int nfds, - fd_set * __restrict readfds, - fd_set * __restrict writefds, - fd_set * __restrict exceptfds, - /* dest1, vcom sets */ - int *vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, int *vcom_nfd, - /* dest2, libc sets */ - int *libc_nfds, - fd_set * __restrict libc_readfds, - fd_set * __restrict libc_writefds, - fd_set * __restrict libc_exceptfds, int *libc_nfd) -{ - int fd; - - /* vcom */ - /* invalid max_fd is -1 */ - int vcom_max_fd = -1; - int vcom_nfd2 = 0; - - /* libc */ - /* invalid max_fd is -1 */ - int libc_max_fd = -1; - int libc_nfd2 = 0; - - - for (fd = 0; fd < nfds; fd++) - { - /* - * S select fd set - * V vcom fd set - * L libc fd set - */ -#define _(S,V,L) \ - if ((S) && FD_ISSET (fd, (S))) \ - { \ - if (is_vcom_socket_fd (fd)) \ - { \ - if ((V)) \ - { \ - FD_SET(fd, (V)); \ - if (fd > vcom_max_fd) \ - { \ - vcom_max_fd = fd; \ - } \ - ++vcom_nfd2; \ - } \ - } \ - else \ - { \ - if ((L)) \ - { \ - FD_SET(fd, (L)); \ - if (fd > libc_max_fd) \ - { \ - libc_max_fd = fd; \ - } \ - ++libc_nfd2; \ - } \ - } \ - } - - - _(readfds, vcom_readfds, libc_readfds); - _(writefds, vcom_writefds, libc_writefds); - _(exceptfds, vcom_exceptfds, libc_exceptfds); -#undef _ - } - - if (vcom_nfds) - *vcom_nfds = vcom_max_fd != -1 ? vcom_max_fd + 1 : 0; - if (vcom_nfd) - *vcom_nfd = vcom_nfd2; - if (libc_nfds) - *libc_nfds = libc_max_fd != -1 ? libc_max_fd + 1 : 0; - if (libc_nfd) - *libc_nfd = libc_nfd2; -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", + getpid (), fd, fd, func_str, cmd); -/* - * merge vcom sets(src1) and libc sets(src2) - * into select sets(dest) - */ -static inline void -vcom_fd_set_merge ( - /* dest, select sets */ - int *nfds, - fd_set * __restrict readfds, - fd_set * __restrict writefds, - fd_set * __restrict exceptfds, int *nfd, - /* src1, vcom sets */ - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, int vcom_nfd, - /* src2, libc sets */ - int libc_nfds, - fd_set * __restrict libc_readfds, - fd_set * __restrict libc_writefds, - fd_set * __restrict libc_exceptfds, int libc_nfd) -{ - int fd; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd2 = 0; - - - /* FD_BIT_OR - * - * dest |= src at current bit index - * update MAX and NFD of dest fd set - * - * - * FS source fd set - * FD dest fd set - * BI bit index - * MAX current max_fd of dest fd sets - * NFD current nfd of dest fd sets - * N nfds of source fd set - */ -#define FD_BIT_OR(FD,FS,BI, \ - MAX,NFD) \ - if ((FS) && (FD) && FD_ISSET ((BI), (FS))) \ - { \ - FD_SET ((BI), (FD)); \ - if ((BI) > (MAX)) \ - { \ - (MAX) = (BI); \ - } \ - ++(NFD); \ + rv = libc_vfcntl (fd, cmd, ap); } + va_end (ap); - /* FD_RWE_SET_OR */ - /* - * SR,SW,SE source RWE fd sets - * DR,DW,DE dest RWE fd sets - * BI bit index - * NFDS nfds of source fd sets - * MAX current max_fd of dest fd sets - * NFD current nfd of dest fd sets - */ -#define FD_RWE_SETS_OR(DR,DW,DE, \ - SR,SW,SE, \ - BI,NFDS, \ - MAX,NFD) \ - do \ - { \ - for ((BI) = 0; (BI) < (NFDS); (BI)++) \ - { \ - FD_BIT_OR((DR), (SR), (BI), (MAX), (NFD)); \ - FD_BIT_OR((DW), (SW), (BI), (MAX), (NFD)); \ - FD_BIT_OR((DE), (SE), (BI), (MAX), (NFD)); \ - } \ - } \ - while (0); - - - /* source(vcom) to dest(select) rwe fd sets */ - FD_RWE_SETS_OR (readfds, writefds, exceptfds, - vcom_readfds, vcom_writefds, vcom_exceptfds, - fd, vcom_nfds, max_fd, nfd2); - - /* source(libc) to dest(select) rwe fd sets */ - FD_RWE_SETS_OR (readfds, writefds, exceptfds, - libc_readfds, libc_writefds, libc_exceptfds, - fd, libc_nfds, max_fd, nfd2); - -#undef FD_RWE_SETS_OR -#undef FD_BIT_OR - - if (nfds) - *nfds = max_fd != -1 ? max_fd + 1 : 0; - if (nfd) - *nfd = nfd2; -} - -/* - * RETURN 1 if fds is NULL or empty. 0 otherwise - */ -static inline int -fd_set_iszero (fd_set * __restrict fds) -{ - int fd; - - /* NULL fds */ - if (!fds) - return 1; - - for (fd = 0; fd < FD_SETSIZE; fd++) + if (VCOM_DEBUG > 2) { - if (FD_ISSET (fd, fds)) + if (rv < 0) { - /* non-empty fds */ - return 0; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - /* empty fds */ - return 1; -} - - -/* - * ################ - * kernel time64.h - * ################ - * */ -typedef long int s64; -typedef unsigned long int u64; - -typedef long long int __s64; -typedef unsigned long long int __u64; - -typedef __s64 time64_t; -typedef __u64 timeu64_t; - -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L -#define USEC_PER_MSEC 1000L -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC 1000000L -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L -#define FSEC_PER_SEC 1000000000000000LL - - -/* - * ################ - * kernel time.h - * ################ - * */ - - -#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1) - -#ifdef VCOM_USE_TIMESPEC_EQUAL -static inline int -timespec_equal (const struct timespec *a, const struct timespec *b) -{ - return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec); -} -#endif - -/* - * lhs < rhs: return <0 - * lhs == rhs: return 0 - * lhs > rhs: return >0 - */ -static inline int -timespec_compare (const struct timespec *lhs, const struct timespec *rhs) -{ - if (lhs->tv_sec < rhs->tv_sec) - return -1; - if (lhs->tv_sec > rhs->tv_sec) - return 1; - return lhs->tv_nsec - rhs->tv_nsec; -} - -#ifdef VCOM_USE_TIMEVAL_COMPARE -static inline int -timeval_compare (const struct timeval *lhs, const struct timeval *rhs) -{ - if (lhs->tv_sec < rhs->tv_sec) - return -1; - if (lhs->tv_sec > rhs->tv_sec) - return 1; - return lhs->tv_usec - rhs->tv_usec; -} -#endif - -extern void set_normalized_timespec (struct timespec *ts, time_t sec, - s64 nsec); - -static inline struct timespec -timespec_add (struct timespec lhs, struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec (&ts_delta, lhs.tv_sec + rhs.tv_sec, - lhs.tv_nsec + rhs.tv_nsec); - return ts_delta; -} - -/* - * sub = lhs - rhs, in normalized form - */ -static inline struct timespec -timespec_sub (struct timespec lhs, struct timespec rhs) -{ - struct timespec ts_delta; - set_normalized_timespec (&ts_delta, lhs.tv_sec - rhs.tv_sec, - lhs.tv_nsec - rhs.tv_nsec); - return ts_delta; -} - -/* - * ################ - * kernel time.c - * ################ - * */ - - -/** - * set_normalized_timespec - set timespec sec and nsec parts and normalize - * - * @ts: pointer to timespec variable to be set - * @sec: seconds to set - * @nsec: nanoseconds to set - * - * Set seconds and nanoseconds field of a timespec variable and - * normalize to the timespec storage format - * - * Note: The tv_nsec part is always in the range of - * 0 <= tv_nsec < NSEC_PER_SEC - * For negative values only the tv_sec field is negative ! - */ -void -set_normalized_timespec (struct timespec *ts, time_t sec, s64 nsec) -{ - while (nsec >= NSEC_PER_SEC) - { - /* - * The following asm() prevents the compiler from - * optimising this loop into a modulo operation. See - * also __iter_div_u64_rem() in include/linux/time.h - */ - asm ("":"+rm" (nsec)); - nsec -= NSEC_PER_SEC; - ++sec; - } - while (nsec < 0) - { - asm ("":"+rm" (nsec)); - nsec += NSEC_PER_SEC; - --sec; - } - ts->tv_sec = sec; - ts->tv_nsec = nsec; -} - -#define vcom_timerisvalid(tvp) (!((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0)) - -/* Macros for converting between `struct timeval' and `struct timespec'. */ -#define VCOM_TIMEVAL_TO_TIMESPEC(tv, ts) { \ - (ts)->tv_sec = (tv)->tv_sec; \ - (ts)->tv_nsec = (tv)->tv_usec * 1000; \ -} -#define VCOM_TIMESPEC_TO_TIMEVAL(tv, ts) { \ - (tv)->tv_sec = (ts)->tv_sec; \ - (tv)->tv_usec = (ts)->tv_nsec / 1000; \ -} - -static inline int -vcom_select_impl (int vcom_nfds, fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, - struct timeval *__restrict timeout) -{ - return vcom_socket_select (vcom_nfds, vcom_readfds, - vcom_writefds, vcom_exceptfds, timeout); + return rv; } int -vcom_select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout) +ioctl (int fd, unsigned long int cmd, ...) { + const char *func_str; int rv; - int rv2 = 0; - pid_t pid = getpid (); - - int timedout = 0; - /* block indefinitely */ - int no_timeout = 0; - int first_clock_gettime_failed = 0; - /* timeout value in units of timespec */ - struct timespec timeout_ts; - struct timespec start_time, now, end_time; - - /* select sets attributes - after merge */ - int new_nfds = 0; - int new_nfd = -1; - - /* vcom */ - int vcom_nfds = 0; - fd_set vcom_readfds; - fd_set vcom_writefds; - fd_set vcom_exceptfds; - int vcom_nfd = -1; - - /* libc */ - int libc_nfds = 0; - fd_set libc_readfds; - fd_set libc_writefds; - fd_set libc_exceptfds; - int libc_nfd = -1; + va_list ap; + u32 sid = vcom_sid_from_fd (fd); - /* for polling */ - struct timeval tv = {.tv_sec = 0,.tv_usec = 0 }; + if ((errno = -vcom_init ())) + return -1; - /* validate __timeout */ - if (__timeout) + va_start (ap, cmd); + if (sid != INVALID_SESSION_ID) { - /* validate tv_sec */ - /* bogus */ - if (!vcom_timerisvalid (__timeout)) + func_str = "vppcom_session_attr[GET_NREAD]"; + + switch (cmd) { - rv = -EINVAL; - goto select_done; - } + case FIONREAD: + if (VCOM_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); - /* validate tv_usec */ - /* TBD: */ - /* init timeout_ts */ - VCOM_TIMEVAL_TO_TIMESPEC (__timeout, &timeout_ts); - set_normalized_timespec (&timeout_ts, - timeout_ts.tv_sec, timeout_ts.tv_nsec); - } + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0); + break; - rv = clock_gettime (CLOCK_MONOTONIC, &start_time); - if (rv == -1) - { - rv = -errno; - first_clock_gettime_failed = 1; - goto select_done; - } + case FIONBIO: + { + u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0; + u32 size = sizeof (flags); + + /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than + * non-blocking, the flags should be read here and merged + * with O_NONBLOCK. + */ + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), flags %d (0x%x), size %d", + getpid (), fd, fd, func_str, sid, sid, + flags, flags, size); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, + &size); + } + break; - /* init end_time */ - if (__timeout) - { - if (timerisset (__timeout)) - { - end_time = timespec_add (start_time, timeout_ts); + default: + rv = -EOPNOTSUPP; + break; } - else + if (rv < 0) { - /* - * if both fields of the timeout structure are zero, - * then select returns immediately - * */ - end_time = start_time; + errno = -rv; + rv = -1; } } else { - /* block indefinitely */ - no_timeout = 1; - } - - - - if (vcom_init () != 0) - { - rv = -1; - goto select_done; - } - - /* validate __nfds */ - if (__nfds < 0 || __nfds > FD_SETSIZE) - { - rv = -EINVAL; - goto select_done; - } + func_str = "libc_vioctl"; + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d", + getpid (), fd, fd, func_str, cmd); - /* - * usleep(3) emulation - * */ - - /* call libc_select() with a finite timeout and - * no file descriptors or empty fd sets and - * zero nfds */ - if (__nfds == 0 && - (!__readfds || fd_set_iszero (__readfds)) && - (!__writefds || fd_set_iszero (__writefds)) && - (!__exceptfds || fd_set_iszero (__exceptfds))) - { - if (__timeout) - { - rv = libc_select (__nfds, - __readfds, __writefds, __exceptfds, __timeout); - if (rv == -1) - rv = -errno; - } - else - { - /* TBD: block indefinitely or return -EINVAL */ - rv = -EINVAL; - } - goto select_done; + rv = libc_vioctl (fd, cmd, ap); } - /* init once before the polling loop */ - - /* zero vcom and libc fd sets */ - /* - * S select fd set - * V vcom fd set - * L libc fd set - */ -#define _(S,V,L) \ - if ((S)) \ - { \ - FD_ZERO ((V)); \ - FD_ZERO ((L)); \ - } - - - _(__readfds, &vcom_readfds, &libc_readfds); - _(__writefds, &vcom_writefds, &libc_writefds); - _(__exceptfds, &vcom_exceptfds, &libc_exceptfds); -#undef _ - new_nfds = 0; - new_nfd = -1; - - vcom_nfds = 0; - vcom_nfd = -1; - libc_nfds = 0; - libc_nfd = -1; - - vcom_fd_set_split ( - /* src, select sets */ - __nfds, __readfds, __writefds, __exceptfds, - /* dest1, vcom sets */ - __readfds || __writefds || __exceptfds ? - &vcom_nfds : NULL, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, - __readfds || __writefds || __exceptfds ? - &vcom_nfd : NULL, - /* dest2, libc sets */ - __readfds || __writefds || __exceptfds ? - &libc_nfds : NULL, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, - __readfds || __writefds || __exceptfds ? - &libc_nfd : NULL); - - /* - * polling loop - * */ - do - { - new_nfd = -1; - vcom_nfd = -1; - libc_nfd = -1; - - /* - * if both fields of timeval structure are zero, - * vcom_select_impl and libc_select returns immediately. - * useful for polling and ensure fairness among - * file descriptors watched. - */ - - /* for polling */ - tv.tv_sec = 0; - tv.tv_usec = 0; - - /* select on vcom fds */ - if (vcom_nfds) - { - vcom_nfd = vcom_select_impl (vcom_nfds, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, - &tv); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] select vcom: " - "'%04d'='%04d'\n", pid, vcom_nfd, vcom_nfds); - - if (vcom_nfd < 0) - { - rv = vcom_nfd; - goto select_done; - } - } - /* select on libc fds */ - if (libc_nfds) - { - libc_nfd = libc_select (libc_nfds, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, &tv); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] select libc: " - "'%04d'='%04d'\n", pid, libc_nfd, libc_nfds); - - if (libc_nfd < 0) - { - /* tv becomes undefined */ - libc_nfd = errno; - rv = libc_nfd; - goto select_done; - } - } - - /* check if any file descriptors changed status */ - if ((vcom_nfds && vcom_nfd > 0) || (libc_nfds && libc_nfd > 0)) - { - /* zero the sets before merge and exit */ - - /* - * F fd set - */ -#define _(F) \ - if ((F)) \ - { \ - FD_ZERO ((F)); \ - } - - - _(__readfds); - _(__writefds); - _(__exceptfds); -#undef _ - new_nfds = 0; - new_nfd = -1; - - /* - * on exit, sets are modified in place to indicate which - * file descriptors actually changed status - * */ - vcom_fd_set_merge ( - /* dest, select sets */ - &new_nfds, - __readfds, __writefds, __exceptfds, &new_nfd, - /* src1, vcom sets */ - vcom_nfds, - __readfds ? &vcom_readfds : NULL, - __writefds ? &vcom_writefds : NULL, - __exceptfds ? &vcom_exceptfds : NULL, vcom_nfd, - /* src2, libc sets */ - libc_nfds, - __readfds ? &libc_readfds : NULL, - __writefds ? &libc_writefds : NULL, - __exceptfds ? &libc_exceptfds : NULL, libc_nfd); - /* - * return the number of file descriptors contained in the - * three returned sets - * */ - rv = 0; - /* - * for documentation - * - * if(vcom_nfd > 0) - * rv += vcom_nfd; - * if(libc_nfd > 0) - * rv += libc_nfd; - */ - - rv = new_nfd == -1 ? 0 : new_nfd; - goto select_done; - } - - rv = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv == -1) - { - rv = -errno; - goto select_done; - } - } - while (no_timeout || timespec_compare (&now, &end_time) < 0); - - /* timeout expired before anything interesting happened */ - timedout = 1; - rv = 0; - -select_done: if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vselect1: " "'%04d'='%04d'\n", pid, rv, __nfds); - /* - * modify timeout parameter to reflect the amount of time not slept - * */ - if (__timeout) { - if (vcom_timerisvalid (__timeout)) + if (rv < 0) { - /* timeout expired */ - if (timedout) - { - timerclear (__timeout); - } - else if (!first_clock_gettime_failed) - { - rv2 = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv2 == -1) - { - rv = -errno; - } - else - { - struct timespec ts_delta; - ts_delta = timespec_sub (end_time, now); - VCOM_TIMESPEC_TO_TIMEVAL (__timeout, &ts_delta); - } - } + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vselect2: " "'%04d',='%04d'\n", pid, rv, __nfds); - + va_end (ap); return rv; } int -vcom_select_internal (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout) +vcom_pselect (int nfds, fd_set * __restrict readfds, + fd_set * __restrict writefds, + fd_set * __restrict exceptfds, + const struct timespec *__restrict timeout, + const __sigset_t * __restrict sigmask) { int rv; - int new_nfds = 0; - int nfd = 0; - pid_t pid = getpid (); - - fd_set saved_readfds; - fd_set saved_writefds; - fd_set saved_exceptfds; + char *func_str = "##"; + f64 time_out; + int fd; + uword sid_bits, sid_bits_set, libc_bits, libc_bits_set; + u32 minbits = clib_max (nfds, BITS (uword)); + u32 sid; - /* validate __nfds */ - if (__nfds < 0) + if (nfds < 0) { errno = EINVAL; return -1; } - /* validate __timeout */ - if (__timeout) + if (nfds <= vcom->sid_bit_val) { - /* validate tv_sec */ - /* bogus */ - if (__timeout->tv_sec < 0 || __timeout->tv_usec < 0) - { - errno = EINVAL; - return -1; - } + func_str = "libc_pselect"; - /* validate tv_usec */ - /* TBD: */ - } + if (VCOM_DEBUG > 3) + clib_warning + ("LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, " + "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds, + readfds, writefds, exceptfds, timeout, sigmask); - /* init saved_x fds */ - if (__readfds) - { - saved_readfds = *__readfds; - /* - memcpy (&saved_readfds, __readfds, sizeof (*__readfds)); - */ + rv = libc_pselect (nfds, readfds, writefds, exceptfds, + timeout, sigmask); + goto done; } - else + + if (PREDICT_FALSE (vcom->sid_bit_val > FD_SETSIZE / 2)) { - FD_ZERO (&saved_readfds); + clib_warning ("LDP<%d>: ERROR: VCOM sid bit value %d (0x%x) > " + "FD_SETSIZE/2 %d (0x%x)!", getpid (), + vcom->sid_bit_val, vcom->sid_bit_val, + FD_SETSIZE / 2, FD_SETSIZE / 2); + errno = EOVERFLOW; + return -1; } - if (__writefds) + if (timeout) { - saved_writefds = *__writefds; - /* - memcpy (&saved_writefds, __writefds, sizeof (*__writefds)); - */ + time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ? + (f64) 0 : (f64) timeout->tv_sec + + (f64) timeout->tv_nsec / (f64) 1000000000 + + (f64) (timeout->tv_nsec % 1000000000) / (f64) 1000000000; - } - else - { - FD_ZERO (&saved_writefds); - } + /* select as fine grained sleep */ + if (!nfds) + { + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: sleeping for %f seconds", + getpid (), time_out); - if (__exceptfds) + time_out += clib_time_now (&vcom->clib_time); + while (clib_time_now (&vcom->clib_time) < time_out) + ; + return 0; + } + } + else if (!nfds) { - saved_exceptfds = *__exceptfds; - /* - memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds)); - */ - + errno = EINVAL; + return -1; } else + time_out = -1; + + sid_bits = libc_bits = 0; + if (readfds) + { + clib_bitmap_validate (vcom->sid_rd_bitmap, minbits); + clib_bitmap_validate (vcom->libc_rd_bitmap, minbits); + clib_bitmap_validate (vcom->rd_bitmap, minbits); + clib_memcpy (vcom->rd_bitmap, readfds, + vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (readfds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, vcom->rd_bitmap, + ({ + sid = vcom_sid_from_fd (fd); + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (vcom->libc_rd_bitmap, fd, 1); + else + clib_bitmap_set_no_check (vcom->sid_rd_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (vcom->sid_rd_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (vcom->libc_rd_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + if (writefds) + { + clib_bitmap_validate (vcom->sid_wr_bitmap, minbits); + clib_bitmap_validate (vcom->libc_wr_bitmap, minbits); + clib_bitmap_validate (vcom->wr_bitmap, minbits); + clib_memcpy (vcom->wr_bitmap, writefds, + vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (writefds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, vcom->wr_bitmap, + ({ + sid = vcom_sid_from_fd (fd); + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (vcom->libc_wr_bitmap, fd, 1); + else + clib_bitmap_set_no_check (vcom->sid_wr_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (vcom->sid_wr_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (vcom->libc_wr_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + if (exceptfds) + { + clib_bitmap_validate (vcom->sid_ex_bitmap, minbits); + clib_bitmap_validate (vcom->libc_ex_bitmap, minbits); + clib_bitmap_validate (vcom->ex_bitmap, minbits); + clib_memcpy (vcom->ex_bitmap, exceptfds, + vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t)); + FD_ZERO (exceptfds); + + /* *INDENT-OFF* */ + clib_bitmap_foreach (fd, vcom->ex_bitmap, + ({ + sid = vcom_sid_from_fd (fd); + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)", + getpid (), fd, fd, sid, sid); + if (sid == INVALID_SESSION_ID) + clib_bitmap_set_no_check (vcom->libc_ex_bitmap, fd, 1); + else + clib_bitmap_set_no_check (vcom->sid_ex_bitmap, sid, 1); + })); + /* *INDENT-ON* */ + + sid_bits_set = clib_bitmap_last_set (vcom->sid_ex_bitmap) + 1; + sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits; + + libc_bits_set = clib_bitmap_last_set (vcom->libc_ex_bitmap) + 1; + libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, " + "libc_bits_set %d, libc_bits %d", getpid (), + sid_bits_set, sid_bits, libc_bits_set, libc_bits); + } + + if (PREDICT_FALSE (!sid_bits && !libc_bits)) { - FD_ZERO (&saved_exceptfds); + errno = EINVAL; + rv = -1; + goto done; } - /* clear vcom fds */ - nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds); - - /* set to an invalid value */ - rv = -2; - /* have kernel fds */ - if (new_nfds) - rv = libc_select (new_nfds, __readfds, - __writefds, __exceptfds, __timeout); - - if (new_nfds && rv == -1) + do { - /* on error, the file descriptor sets are unmodified */ - if (__readfds) - *__readfds = saved_readfds; - if (__writefds) - *__writefds = saved_writefds; - if (__exceptfds) - *__exceptfds = saved_exceptfds; - return rv; + if (sid_bits) + { + if (!vcom->select_vcl) + { + func_str = "vppcom_select"; + + if (readfds) + clib_memcpy (vcom->rd_bitmap, vcom->sid_rd_bitmap, + vec_len (vcom->rd_bitmap) * + sizeof (clib_bitmap_t)); + if (writefds) + clib_memcpy (vcom->wr_bitmap, vcom->sid_wr_bitmap, + vec_len (vcom->wr_bitmap) * + sizeof (clib_bitmap_t)); + if (exceptfds) + clib_memcpy (vcom->ex_bitmap, vcom->sid_ex_bitmap, + vec_len (vcom->ex_bitmap) * + sizeof (clib_bitmap_t)); + + rv = vppcom_select (sid_bits, + readfds ? vcom->rd_bitmap : NULL, + writefds ? vcom->wr_bitmap : NULL, + exceptfds ? vcom->ex_bitmap : NULL, 0); + if (rv < 0) + { + errno = -rv; + rv = -1; + } + else if (rv > 0) + { + if (readfds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, vcom->rd_bitmap, + ({ + fd = vcom_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, readfds); + })); + /* *INDENT-ON* */ + } + if (writefds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, vcom->wr_bitmap, + ({ + fd = vcom_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, writefds); + })); + /* *INDENT-ON* */ + } + if (exceptfds) + { + /* *INDENT-OFF* */ + clib_bitmap_foreach (sid, vcom->ex_bitmap, + ({ + fd = vcom_fd_from_sid (sid); + if (PREDICT_FALSE (fd < 0)) + { + errno = EBADFD; + rv = -1; + goto done; + } + FD_SET (fd, exceptfds); + })); + /* *INDENT-ON* */ + } + vcom->select_vcl = 1; + goto done; + } + } + else + vcom->select_vcl = 0; + } + if (libc_bits) + { + struct timespec tspec; + + func_str = "libc_pselect"; + + if (readfds) + clib_memcpy (readfds, vcom->libc_rd_bitmap, + vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t)); + if (writefds) + clib_memcpy (writefds, vcom->libc_wr_bitmap, + vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t)); + if (exceptfds) + clib_memcpy (exceptfds, vcom->libc_ex_bitmap, + vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t)); + tspec.tv_sec = tspec.tv_nsec = 0; + rv = libc_pselect (libc_bits, + readfds ? readfds : NULL, + writefds ? writefds : NULL, + exceptfds ? exceptfds : NULL, &tspec, sigmask); + if (rv != 0) + goto done; + } } - else if ((new_nfds && rv != -1) || (rv == -2)) + while ((time_out == -1) || (clib_time_now (&vcom->clib_time) < time_out)); + rv = 0; + +done: + /* TBD: set timeout to amount of time left */ + vec_reset_length (vcom->rd_bitmap); + vec_reset_length (vcom->sid_rd_bitmap); + vec_reset_length (vcom->libc_rd_bitmap); + vec_reset_length (vcom->wr_bitmap); + vec_reset_length (vcom->sid_wr_bitmap); + vec_reset_length (vcom->libc_wr_bitmap); + vec_reset_length (vcom->ex_bitmap); + vec_reset_length (vcom->sid_ex_bitmap); + vec_reset_length (vcom->libc_ex_bitmap); + + if (VCOM_DEBUG > 3) { - /* restore vcom fds */ - nfd = vcom_fd_set (__nfds, - &new_nfds, - __readfds, - __writefds, - __exceptfds, - &saved_readfds, &saved_writefds, &saved_exceptfds); - rv = nfd; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", getpid (), + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv); } - - if (VCOM_DEBUG > 0) - fprintf (stderr, "[%d] select: " "'%04d'='%04d'\n", pid, rv, __nfds); return rv; } int -select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, struct timeval *__restrict __timeout) +select (int nfds, fd_set * __restrict readfds, + fd_set * __restrict writefds, + fd_set * __restrict exceptfds, struct timeval *__restrict timeout) { - int rv = 0; - pid_t pid = getpid (); + struct timespec tspec; - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] select1: " "'%04d'='%04d'\n", pid, rv, __nfds); - rv = vcom_select (__nfds, __readfds, __writefds, __exceptfds, __timeout); - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] select2: " "'%04d'='%04d'\n", pid, rv, __nfds); - if (rv < 0) + if (timeout) { - errno = -rv; - return -1; + tspec.tv_sec = timeout->tv_sec; + tspec.tv_nsec = timeout->tv_usec * 1000; } - return rv; + return vcom_pselect (nfds, readfds, writefds, exceptfds, + timeout ? &tspec : NULL, NULL); } #ifdef __USE_XOPEN2K -/* - * Same as above only that the TIMEOUT value is given with higher - * resolution and a sigmask which is been set temporarily. This - * version should be used. - * - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ int -vcom_pselect (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t * __restrict __sigmask) +pselect (int nfds, fd_set * __restrict readfds, + fd_set * __restrict writefds, + fd_set * __restrict exceptfds, + const struct timespec *__restrict timeout, + const __sigset_t * __restrict sigmask) { - int fd; - int vcom_nfds = 0; - - for (fd = 0; fd < __nfds; fd++) - { - if (__readfds && FD_ISSET (fd, __readfds)) - { - if (is_vcom_socket_fd (fd)) - { - vcom_nfds++; - } - } - - if (__writefds && FD_ISSET (fd, __writefds)) - { - if (is_vcom_socket_fd (fd)) - { - vcom_nfds++; - } - } - if (__exceptfds && FD_ISSET (fd, __exceptfds)) - { - if (is_vcom_socket_fd (fd)) - { - FD_CLR (fd, __exceptfds); - } - } - } - return vcom_nfds; + return vcom_pselect (nfds, readfds, writefds, exceptfds, timeout, 0); } +#endif int -pselect (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t * __restrict __sigmask) +socket (int domain, int type, int protocol) { + const char *func_str; int rv; - int new_nfds = 0; - int nfd = 0; - pid_t pid = getpid (); + u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0; + int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); - fd_set saved_readfds; - fd_set saved_writefds; - fd_set saved_exceptfds; + if ((errno = -vcom_init ())) + return -1; - /* validate __nfds */ - if (__nfds < 0) + if (((domain == AF_INET) || (domain == AF_INET6)) && + ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) { - errno = EINVAL; - return -1; - } + int sid; + u32 vrf = VPPCOM_VRF_DEFAULT; + u8 proto = ((sock_type == SOCK_DGRAM) ? + VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP); - /* validate __timeout */ - if (__timeout) - { - /* validate tv_sec */ - /* bogus */ - if (__timeout->tv_sec < 0 || __timeout->tv_nsec < 0) - { - errno = EINVAL; - return -1; - } + func_str = "vppcom_session_create"; - /* validate tv_usec */ - /* TBD: */ - } + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: : calling %s(): vrf %u, " + "proto %u (%s), is_nonblocking %u", + getpid (), func_str, vrf, proto, + vppcom_proto_str (proto), is_nonblocking); - /* init saved fds */ - if (__readfds) - { - saved_readfds = *__readfds; - /* - memcpy (&saved_readfds, __readfds, sizeof (*__readfds)); - */ + sid = vppcom_session_create (vrf, proto, is_nonblocking); + if (sid < 0) + { + errno = -sid; + rv = -1; + } + else + { + func_str = "vcom_fd_from_sid"; + rv = vcom_fd_from_sid (sid); + if (rv < 0) + { + (void) vppcom_session_close (sid); + errno = -rv; + rv = -1; + } + } } else { - FD_ZERO (&saved_readfds); - } + func_str = "libc_socket"; - if (__writefds) - { - saved_writefds = *__writefds; - /* - memcpy (&saved_writefds, __writefds, sizeof (*__writefds)); - */ + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); - } - else - { - FD_ZERO (&saved_writefds); + rv = libc_socket (domain, type, protocol); } - if (__exceptfds) - { - saved_exceptfds = *__exceptfds; - /* - memcpy (&saved_exceptfds, __exceptfds, sizeof (*__exceptfds)); - */ - - } - else + if (VCOM_DEBUG > 0) { - FD_ZERO (&saved_exceptfds); + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); } + return rv; +} - /* clear vcom fds */ - nfd = vcom_fd_clear (__nfds, &new_nfds, __readfds, __writefds, __exceptfds); +/* + * Create two new sockets, of type TYPE in domain DOMAIN and using + * protocol PROTOCOL, which are connected to each other, and put file + * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + * one will be chosen automatically. + * Returns 0 on success, -1 for errors. + * */ +int +socketpair (int domain, int type, int protocol, int fds[2]) +{ + const char *func_str; + int rv; + int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); - /* set to an invalid value */ - rv = -2; - if (new_nfds) - rv = libc_pselect (new_nfds, - __readfds, - __writefds, __exceptfds, __timeout, __sigmask); + if ((errno = -vcom_init ())) + return -1; - if (new_nfds && rv == -1) + if (((domain == AF_INET) || (domain == AF_INET6)) && + ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM))) { - /* on error, the file descriptor sets are unmodified */ - if (__readfds) - *__readfds = saved_readfds; - if (__writefds) - *__writefds = saved_writefds; - if (__exceptfds) - *__exceptfds = saved_exceptfds; - return rv; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + rv = -1; } - else if ((new_nfds && rv != -1) || (rv == -2)) + else { - /* restore vcom fds */ - nfd = vcom_fd_set (__nfds, - &new_nfds, - __readfds, - __writefds, - __exceptfds, - &saved_readfds, &saved_writefds, &saved_exceptfds); - rv = nfd; - } + func_str = "libc_socket"; - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] pselect: " "'%04d'='%04d'\n", pid, rv, __nfds); - return rv; -} -#endif + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str); -/* - * - * Socket specific glibc api - * - */ - -/* Create a new socket of type TYPE in domain DOMAIN, using - * protocol PROTOCOL. If PROTOCOL is zero, one is chosen - * automatically. Returns a file descriptor for the new socket, - * or -1 for errors. - * RETURN: a valid file descriptor for the new socket, - * or -1 for errors. - * */ + rv = libc_socket (domain, type, protocol); + } -int -vcom_socket (int __domain, int __type, int __protocol) -{ - if (vcom_init () != 0) + if (VCOM_DEBUG > 1) { - return -1; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv); } - - return vcom_socket_socket (__domain, __type, __protocol); + return rv; } int -socket (int __domain, int __type, int __protocol) +bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) { int rv; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - /* handle domains implemented by vpp */ - switch (__domain) + if (sid != INVALID_SESSION_ID) { - case AF_INET: - case AF_INET6: - /* handle types implemented by vpp */ - switch (__type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) + vppcom_endpt_t ep; + + func_str = "vppcom_session_bind"; + + ep.vrf = VPPCOM_VRF_DEFAULT; + switch (addr->sa_family) { - case SOCK_STREAM: - case SOCK_DGRAM: - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - rv = vcom_socket (__domain, __type, __protocol); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] socket: " - "'%04d'= D='%04d', T='%04d', P='%04d'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __domain, __type, __protocol); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) + case AF_INET: + if (len != sizeof (struct sockaddr_in)) { - errno = -rv; - return -1; + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " + "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; } - return rv; + ep.is_ip4 = VPPCOM_IS_IP4; + ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; break; - default: - goto CALL_GLIBC_SOCKET_API; + case AF_INET6: + if (len != sizeof (struct sockaddr_in6)) + { + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid " + "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP6; + ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; break; - } - break; + default: + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): " + "Unsupported address family %u!", + getpid (), fd, fd, sid, sid, addr->sa_family); + errno = EAFNOSUPPORT; + rv = -1; + goto done; + } + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); - default: - goto CALL_GLIBC_SOCKET_API; - break; + rv = vppcom_session_bind (sid, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } } + else + { + func_str = "libc_bind"; -CALL_GLIBC_SOCKET_API: - return libc_socket (__domain, __type, __protocol); -} + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); -/* - * Create two new sockets, of type TYPE in domain DOMAIN and using - * protocol PROTOCOL, which are connected to each other, and put file - * descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, - * one will be chosen automatically. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2]) -{ - if (vcom_init () != 0) - { - return -1; + rv = libc_bind (fd, addr, len); } - return vcom_socket_socketpair (__domain, __type, __protocol, __fds); +done: + if (VCOM_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; } -int -socketpair (int __domain, int __type, int __protocol, int __fds[2]) +static inline int +vcom_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len, + vppcom_endpt_t * ep) { - int rv; - pid_t pid = getpid (); + int rv = 0; + int sa_len, copy_len; - /* handle domains implemented by vpp */ - switch (__domain) + if ((errno = -vcom_init ())) + return -1; + + if (addr && len && ep) { - case AF_INET: - case AF_INET6: - /* handle types implemented by vpp */ - switch (__type) + addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6; + switch (addr->sa_family) { - case SOCK_STREAM: - case SOCK_DGRAM: - rv = vcom_socketpair (__domain, __type, __protocol, __fds); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] socketpair: " - "'%04d'= D='%04d', T='%04d', P='%04d'\n", - pid, rv, __domain, __type, __protocol); - if (rv < 0) - { - errno = -rv; - return -1; - } - return 0; + case AF_INET: + ((struct sockaddr_in *) addr)->sin_port = ep->port; + if (*len > sizeof (struct sockaddr_in)) + *len = sizeof (struct sockaddr_in); + sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr); + copy_len = *len - sa_len; + if (copy_len > 0) + memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip, + copy_len); + break; + + case AF_INET6: + ((struct sockaddr_in6 *) addr)->sin6_port = ep->port; + if (*len > sizeof (struct sockaddr_in6)) + *len = sizeof (struct sockaddr_in6); + sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr); + copy_len = *len - sa_len; + if (copy_len > 0) + memcpy (((struct sockaddr_in6 *) addr)->sin6_addr. + __in6_u.__u6_addr8, ep->ip, copy_len); break; default: - goto CALL_GLIBC_SOCKET_API; + /* Not possible */ + rv = -EAFNOSUPPORT; break; } - - break; - - default: - goto CALL_GLIBC_SOCKET_API; - break; } - -CALL_GLIBC_SOCKET_API: - return libc_socketpair (__domain, __type, __protocol, __fds); + return rv; } -/* - * Give the socket FD the local address ADDR - * (which is LEN bytes long). - * */ int -vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) +getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) { int rv; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); - if (vcom_init () != 0) - { - return -1; - } - - /* validate __len */ - switch (__addr->sa_family) - { - case AF_INET: - if (__len != sizeof (struct sockaddr_in)) - return -EINVAL; - break; - case AF_INET6: - if (__len != sizeof (struct sockaddr_in6)) - return -EINVAL; - break; - - default: - return -1; - break; - } + if ((errno = -vcom_init ())) + return -1; - /* handle domains implemented by vpp */ - switch (__addr->sa_family) + if (sid != INVALID_SESSION_ID) { - case AF_INET: - case AF_INET6: - rv = vcom_socket_bind (__fd, __addr, __len); - return rv; - break; - - default: - return -1; - break; - } - - return -1; -} + vppcom_endpt_t ep; + u8 addr_buf[sizeof (struct in6_addr)]; + u32 size = sizeof (ep); -int -bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv; - pid_t pid = getpid (); + ep.ip = addr_buf; + func_str = "vppcom_session_attr[GET_LCL_ADDR]"; - if (is_vcom_socket_fd (__fd)) - { + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); - rv = vcom_bind (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] bind: " - "'%04d'='%04d', '%p', '%04d'\n", - pid, rv, __fd, __addr, __len); - if (rv != 0) + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size); + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; + } + else + { + rv = vcom_copy_ep_to_sockaddr (addr, len, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } } - return 0; } - return libc_bind (__fd, __addr, __len); -} - -/* - * Put the local address of FD into *ADDR and its length in *LEN. - * */ -int -vcom_getsockname (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_getsockname"; - return vcom_socket_getsockname (__fd, __addr, __len); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); -int -getsockname (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len) -{ - int rv; - pid_t pid = getpid (); + rv = libc_getsockname (fd, addr, len); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - rv = vcom_getsockname (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] getsockname: " - "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len); - if (rv != 0) + if (rv < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; } - return 0; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - return libc_getsockname (__fd, __addr, __len); + return rv; } -/* - * Open a connection on socket FD to peer at ADDR - * (which LEN bytes long). For connectionless socket types, just set - * the default address to send to and the only address from which to - * accept transmissions. Return 0 on success, -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ int -vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) +connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len) { int rv; + const char *func_str = __func__; + u32 sid = vcom_sid_from_fd (fd); - rv = vcom_init (); - if (rv) - { - return rv; - } + if ((errno = -vcom_init ())) + return -1; - /* validate __len */ - switch (__addr->sa_family) + if (!addr) { - case AF_INET: - if (__len != INET_ADDRSTRLEN) - return -EINVAL; - break; - case AF_INET6: - if (__len != INET6_ADDRSTRLEN) - return -EINVAL; - break; - - default: - return -EAFNOSUPPORT; - break; + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u", + getpid (), fd, fd, len); + errno = EINVAL; + rv = -1; + goto done; } - /* handle domains implemented by vpp */ - switch (__addr->sa_family) + if (sid != INVALID_SESSION_ID) { - case AF_INET: - case AF_INET6: - rv = vcom_socket_connect (__fd, __addr, __len); - break; + vppcom_endpt_t ep; - default: - return -EPFNOSUPPORT; - break; - } + func_str = "vppcom_session_connect"; - return rv; -} + ep.vrf = VPPCOM_VRF_DEFAULT; + switch (addr->sa_family) + { + case AF_INET: + if (len != sizeof (struct sockaddr_in)) + { + clib_warning + ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " + "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP4; + ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port; + break; -int -connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv; - pid_t pid = getpid (); + case AF_INET6: + if (len != sizeof (struct sockaddr_in6)) + { + clib_warning + ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid " + "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len); + errno = EINVAL; + rv = -1; + goto done; + } + ep.is_ip4 = VPPCOM_IS_IP6; + ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port; + break; - if (is_vcom_socket_fd (__fd)) - { - rv = vcom_connect (__fd, __addr, __len); + default: + clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): " + "Unsupported address family %u!", + getpid (), fd, fd, sid, sid, addr->sa_family); + errno = EAFNOSUPPORT; + rv = -1; + goto done; + } if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] connect: " - "'%04d'='%04d', '%p', '%04d'\n", - pid, rv, __fd, __addr, __len); - if (rv) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) " + "addr %p len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_connect (sid, &ep); + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; } - return 0; } + else + { + func_str = "libc_connect"; - return libc_connect (__fd, __addr, __len); -} + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); -/* - * Put the address of the peer connected to socket FD into *ADDR - * (which is *LEN bytes long), and its actual length into *LEN. - * */ -int -vcom_getpeername (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - if (vcom_init () != 0) - { - return -1; + rv = libc_connect (fd, addr, len); } - return vcom_socket_getpeername (__fd, __addr, __len); +done: + if (VCOM_DEBUG > 0) + { + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); + } + return rv; } int -getpeername (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __len) +getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len) { int rv; - pid_t pid = getpid (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; + + clib_warning ("LDP<%d>: fd %d (0x%x) ", getpid (), fd, fd); - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { - rv = vcom_getpeername (__fd, __addr, __len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] getpeername: " - "'%04d'='%04d', '%p', '%p'\n", pid, rv, __fd, __addr, __len); - if (rv != 0) + vppcom_endpt_t ep; + u8 addr_buf[sizeof (struct in6_addr)]; + u32 size = sizeof (ep); + + ep.ip = addr_buf; + func_str = "vppcom_session_attr[GET_PEER_ADDR]"; + + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "addr %p, len %u", + getpid (), fd, fd, func_str, sid, sid, addr, len); + + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size); + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; + } + else + { + rv = vcom_copy_ep_to_sockaddr (addr, len, &ep); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } } - return 0; } - return libc_getpeername (__fd, __addr, __len); -} - -/* - * Send N bytes of BUF to socket FD. Returns the number sent or -1. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_send (int __fd, const void *__buf, size_t __n, int __flags) -{ - - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_getpeername"; - return vcom_socket_send (__fd, (void *) __buf, (int) __n, __flags); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "addr %p, len %u", + getpid (), fd, fd, func_str, addr, len); -ssize_t -send (int __fd, const void *__buf, size_t __n, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); + rv = libc_getpeername (fd, addr, len); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - size = vcom_send (__fd, __buf, __n, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] send: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags); - if (size < 0) + if (rv < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - return libc_send (__fd, __buf, __n, __flags); + return rv; } ssize_t -sendfile (int __out_fd, int __in_fd, off_t * __offset, size_t __len) +send (int fd, const void *buf, size_t n, int flags) { ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); - if (VCOM_DEBUG > 2) - clib_warning ("[%d] __out_fd %d, __in_fd %d, __offset %p, __len %ld", - getpid (), __out_fd, __in_fd, __offset, __len); + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__out_fd)) + if (sid != INVALID_SESSION_ID) { - /* TBD: refactor this check to be part of is_vcom_socket_fd() */ - if (vcom_init () != 0) - return -1; - size = vcom_socket_sendfile (__out_fd, __in_fd, __offset, __len); + func_str = "vppcom_session_sendto"; + if (VCOM_DEBUG > 2) - clib_warning ("[%d] vcom_socket_sendfile (out_fd %d, in_fd %d, " - "offset %p (%ld), len %lu) returned %ld", - getpid (), __out_fd, __in_fd, __offset, - __offset ? *__offset : -1, __len, size); - if (size < 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "buf %p, n %u, flags 0x%x", + getpid (), fd, fd, func_str, sid, sid, buf, n, flags); + + size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL); + if (size != VPPCOM_OK) { errno = -size; - return -1; + size = -1; } - return size; } - if (VCOM_DEBUG > 2) - clib_warning ("[%d] calling libc_sendfile!", getpid ()); - return libc_sendfile (__out_fd, __in_fd, __offset, __len); -} - -ssize_t -sendfile64 (int __out_fd, int __in_fd, off_t * __offset, size_t __len) -{ - return sendfile (__out_fd, __in_fd, __offset, __len); -} - - -/* - * Read N bytes into BUF from socket FD. - * Returns the number read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_recv (int __fd, void *__buf, size_t __n, int __flags) -{ - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_send"; - return vcom_socket_recv (__fd, __buf, __n, __flags); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x", + getpid (), fd, fd, func_str, buf, n, flags); -ssize_t -recv (int __fd, void *__buf, size_t __n, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); + size = libc_send (fd, buf, n, flags); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - size = vcom_recv (__fd, __buf, __n, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recv: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags); if (size < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_recv (__fd, __buf, __n, __flags); + return size; } -/* - * Send N bytes of BUF on socket FD to peer at address ADDR (which is - * ADDR_LEN bytes long). Returns the number sent, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ ssize_t -vcom_sendto (int __fd, const void *__buf, size_t __n, int __flags, - __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len) +sendfile (int out_fd, int in_fd, off_t * offset, size_t len) { - if (vcom_init () != 0) - { - return -1; + ssize_t size = 0; + const char *func_str; + u32 sid = vcom_sid_from_fd (out_fd); + + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) + { + int rv; + ssize_t results = 0; + size_t n_bytes_left = len; + size_t bytes_to_read; + int nbytes; + int errno_val; + u8 eagain = 0; + u32 flags, flags_len = sizeof (flags); + + func_str = "vppcom_session_attr[GET_FLAGS]"; + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, + &flags_len); + if (PREDICT_FALSE (rv != VPPCOM_OK)) + { + clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " + "sid %u (0x%x), returned %d (%s)!", getpid (), + out_fd, out_fd, func_str, sid, sid, rv, + vppcom_retval_str (rv)); + + vec_reset_length (vcom->io_buffer); + errno = -rv; + size = -1; + goto done; + } + + if (offset) + { + off_t off = lseek (in_fd, *offset, SEEK_SET); + if (PREDICT_FALSE (off == -1)) + { + func_str = "lseek"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): " + "SEEK_SET failed: in_fd %d, offset %p, " + "*offset %ld, rv %ld, errno %d", getpid (), + out_fd, out_fd, in_fd, offset, *offset, off, + errno_val); + errno = errno_val; + size = -1; + goto done; + } + + ASSERT (off == *offset); + } + + do + { + func_str = "vppcom_session_attr[GET_NWRITE]"; + size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0); + if (size < 0) + { + clib_warning + ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), " + "returned %d (%s)!", getpid (), out_fd, out_fd, func_str, + sid, sid, size, vppcom_retval_str (size)); + vec_reset_length (vcom->io_buffer); + errno = -size; + size = -1; + goto done; + } + + bytes_to_read = size; + if (VCOM_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), " + "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (), + out_fd, out_fd, func_str, sid, sid, results, n_bytes_left, + bytes_to_read); + + if (bytes_to_read == 0) + { + if (flags & O_NONBLOCK) + { + if (!results) + { + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " + "EAGAIN", + getpid (), out_fd, out_fd, sid, sid); + eagain = 1; + } + goto update_offset; + } + else + continue; + } + bytes_to_read = clib_min (n_bytes_left, bytes_to_read); + vec_validate (vcom->io_buffer, bytes_to_read); + nbytes = libc_read (in_fd, vcom->io_buffer, bytes_to_read); + if (nbytes < 0) + { + func_str = "libc_read"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), " + "io_buffer %p, bytes_to_read %lu, rv %d, " + "errno %d", getpid (), out_fd, out_fd, func_str, + in_fd, vcom->io_buffer, bytes_to_read, nbytes, + errno_val); + errno = errno_val; + + if (results == 0) + { + vec_reset_length (vcom->io_buffer); + size = -1; + goto done; + } + goto update_offset; + } + func_str = "vppcom_session_write"; + if (VCOM_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), " + "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (), + out_fd, out_fd, func_str, sid, sid, vcom->io_buffer, nbytes, + results, n_bytes_left); + + size = vppcom_session_write (sid, vcom->io_buffer, nbytes); + if (size < 0) + { + if (size == VPPCOM_EAGAIN) + { + if (flags & O_NONBLOCK) + { + if (!results) + { + if (VCOM_DEBUG > 2) + clib_warning + ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): " + "EAGAIN", getpid (), out_fd, out_fd, sid, sid); + eagain = 1; + } + goto update_offset; + } + else + continue; + } + else + { + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():" + "sid %u, io_buffer %p, nbytes %u " + "returned %d (%s)", + getpid (), out_fd, out_fd, func_str, + sid, vcom->io_buffer, nbytes, + size, vppcom_retval_str (size)); + } + if (results == 0) + { + vec_reset_length (vcom->io_buffer); + errno = -size; + size = -1; + goto done; + } + goto update_offset; + } + + results += nbytes; + ASSERT (n_bytes_left >= nbytes); + n_bytes_left = n_bytes_left - nbytes; + } + while (n_bytes_left > 0); + + update_offset: + vec_reset_length (vcom->io_buffer); + if (offset) + { + off_t off = lseek (in_fd, *offset, SEEK_SET); + if (PREDICT_FALSE (off == -1)) + { + func_str = "lseek"; + errno_val = errno; + clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: " + "in_fd %d, offset %p, *offset %ld, " + "rv %ld, errno %d", getpid (), in_fd, + offset, *offset, off, errno_val); + errno = errno_val; + size = -1; + goto done; + } + + ASSERT (off == *offset); + *offset += results + 1; + } + if (eagain) + { + errno = EAGAIN; + size = -1; + } + else + size = results; } + else + { + func_str = "libc_send"; - return vcom_socket_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "in_fd %d, offset %p, len %u", + getpid (), out_fd, out_fd, func_str, + in_fd, offset, len); -ssize_t -sendto (int __fd, const void *__buf, size_t __n, int __flags, - __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len) -{ - ssize_t size; - pid_t pid = getpid (); + size = libc_sendfile (out_fd, in_fd, offset, len); + } - if (is_vcom_socket_fd (__fd)) +done: + if (VCOM_DEBUG > 2) { - size = vcom_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendto: " - "'%04d'='%04d', '%p', '%04d', '%04x', " - "'%p', '%04d'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags, - __addr, __addr_len); if (size < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), out_fd, out_fd, + func_str, size, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), out_fd, out_fd, size, size); } - return libc_sendto (__fd, __buf, __n, __flags, __addr, __addr_len); + return size; } -/* - * Read N bytes into BUF through socket FD. - * If ADDR is not NULL, fill in *ADDR_LEN bytes of it with the - * address of the sender, and store the actual size of the address - * in *ADDR_LEN. - * Returns the number of bytes read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ ssize_t -vcom_recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) +sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len) { - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); + return sendfile (out_fd, in_fd, offset, len); } ssize_t -recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) +recv (int fd, void *buf, size_t n, int flags) { ssize_t size; - pid_t pid = getpid (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { - size = vcom_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvfrom: " - "'%04d'='%04d', '%p', '%04d', '%04x', " - "'%p', '%p'\n", - pid, (int) size, __fd, __buf, (int) __n, __flags, - __addr, __addr_len); + func_str = "vppcom_session_recvfrom"; + + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (), + fd, fd, func_str, sid, sid, buf, n, flags); + + size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); if (size < 0) { errno = -size; - return -1; + size = -1; } - return size; } - return libc_recvfrom (__fd, __buf, __n, __flags, __addr, __addr_len); -} - -/* - * Send a message described MESSAGE on socket FD. - * Returns the number of bytes sent, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_sendmsg (int __fd, const struct msghdr * __message, int __flags) -{ - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_recv"; - return vcom_socket_sendmsg (__fd, __message, __flags); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x", getpid (), + fd, fd, func_str, buf, n, flags); -ssize_t -sendmsg (int __fd, const struct msghdr * __message, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); + size = libc_recv (fd, buf, n, flags); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - size = vcom_sendmsg (__fd, __message, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendmsg: " - "'%04d'='%04d', '%p', '%04x'\n", - pid, (int) size, __fd, __message, __flags); if (size < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_sendmsg (__fd, __message, __flags); + return size; } -#ifdef __USE_GNU -/* - * Send a VLEN messages as described by VMESSAGES to socket FD. - * Returns the number of datagrams successfully written - * or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags) +ssize_t +sendto (int fd, const void *buf, size_t n, int flags, + __CONST_SOCKADDR_ARG addr, socklen_t addr_len) { - if (vcom_init () != 0) + ssize_t size; + const char *func_str = __func__; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - return -1; - } + vppcom_endpt_t *ep = 0; + vppcom_endpt_t _ep; - return vcom_socket_sendmmsg (__fd, __message, __vlen, __flags); -} + if (addr) + { + ep = &_ep; + ep->vrf = VPPCOM_VRF_DEFAULT; + switch (addr->sa_family) + { + case AF_INET: + ep->is_ip4 = VPPCOM_IS_IP4; + ep->ip = + (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr; + ep->port = + (uint16_t) ((const struct sockaddr_in *) addr)->sin_port; + break; + + case AF_INET6: + ep->is_ip4 = VPPCOM_IS_IP6; + ep->ip = + (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr; + ep->port = + (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port; + break; + + default: + errno = EAFNOSUPPORT; + size = -1; + goto done; + } + } -int -sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags) -{ - ssize_t size; - pid_t pid = getpid (); + func_str = "vppcom_session_sendto"; - if (is_vcom_socket_fd (__fd)) - { - size = vcom_sendmmsg (__fd, __message, __vlen, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] sendmmsg: " - "'%04d'='%04d', '%p', '%04d', '%04x'\n", - pid, (int) size, __fd, __vmessages, __vlen, __flags); + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", + getpid (), fd, fd, func_str, sid, sid, buf, n, + flags, ep); + + size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep); if (size < 0) { errno = -size; - return -1; + size = -1; } - return size; } - return libc_sendmmsg (__fd, __message, __vlen, __flags); -} + else + { + func_str = "libc_sendto"; -#endif + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", + getpid (), fd, fd, func_str, buf, n, flags, + addr, addr_len); -/* - * Receive a message as described by MESSAGE from socket FD. - * Returns the number of bytes read or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -ssize_t -vcom_recvmsg (int __fd, struct msghdr * __message, int __flags) -{ - if (vcom_init () != 0) + size = libc_sendto (fd, buf, n, flags, addr, addr_len); + } + +done: + if (VCOM_DEBUG > 2) { - return -1; + if (size < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - - return vcom_socket_recvmsg (__fd, __message, __flags); + return size; } ssize_t -recvmsg (int __fd, struct msghdr * __message, int __flags) +recvfrom (int fd, void *__restrict buf, size_t n, int flags, + __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) { ssize_t size; - pid_t pid = getpid (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { - size = vcom_recvmsg (__fd, __message, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvmsg: " - "'%04d'='%04d', '%p', '%04x'\n", - pid, (int) size, __fd, __message, __flags); + vppcom_endpt_t ep; + u8 src_addr[sizeof (struct sockaddr_in6)]; + + func_str = "vppcom_session_recvfrom"; + + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p", + getpid (), fd, fd, func_str, sid, sid, buf, n, + flags, &ep); + if (addr) + { + ep.ip = src_addr; + size = vppcom_session_recvfrom (sid, buf, n, flags, &ep); + + if (size > 0) + size = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep); + } + else + size = vppcom_session_recvfrom (sid, buf, n, flags, NULL); + if (size < 0) { errno = -size; - return -1; + size = -1; } - return size; } - return libc_recvmsg (__fd, __message, __flags); -} - -#ifdef __USE_GNU -/* - * Receive up to VLEN messages as described by VMESSAGES from socket FD. - * Returns the number of messages received or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ -int -vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo) -{ - if (vcom_init () != 0) + else { - return -1; - } + func_str = "libc_recvfrom"; - return vcom_socket_recvmmsg (__fd, __message, __vlen, __flags, __tmo); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "buf %p, n %u, flags 0x%x, addr %p, addr_len %d", + getpid (), fd, fd, func_str, buf, n, flags, + addr, addr_len); -int -recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo) -{ - ssize_t size; - pid_t pid = getpid (); + size = libc_recvfrom (fd, buf, n, flags, addr, addr_len); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - size = vcom_recvmmsg (__fd, __message, __vlen, __flags, __tmo); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] recvmmsg: " - "'%04d'='%04d', '%p', " - "'%04d', '%04x', '%p'\n", - pid, (int) size, __fd, __vmessages, __vlen, __flags, __tmo); if (size < 0) { - errno = -size; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return size; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_recvmmsg (__fd, __message, __vlen, __flags, __tmo); + return size; } -#endif - -/* - * Put the current value for socket FD's option OPTNAME - * at protocol level LEVEL into OPTVAL (which is *OPTLEN bytes long), - * and set *OPTLEN to the value's actual length. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen) +ssize_t +sendmsg (int fd, const struct msghdr * message, int flags) { - if (vcom_init () != 0) + ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - return -1; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; } + else + { + func_str = "libc_sendmsg"; - return vcom_socket_getsockopt (__fd, __level, __optname, - __optval, __optlen); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "message %p, flags 0x%x", + getpid (), fd, fd, func_str, message, flags); -int -getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen) -{ - int rv; - pid_t pid = getpid (); + size = libc_sendmsg (fd, message, flags); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - rv = vcom_getsockopt (__fd, __level, __optname, __optval, __optlen); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] getsockopt: " - "'%04d'='%04d', '%04d', '%04d', " - "'%p', '%p'\n", - pid, rv, __fd, __level, __optname, __optval, __optlen); - if (rv != 0) + if (size < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return 0; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_getsockopt (__fd, __level, __optname, __optval, __optlen); + return size; } -/* - * Set socket FD's option OPTNAME at protocol level LEVEL - * to *OPTVAL (which is OPTLEN bytes long). - * Returns 0 on success, -1 for errors. - * */ +#ifdef USE_GNU int -vcom_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) +sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags) { - if (vcom_init () != 0) + ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - return -1; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; } + else + { + func_str = "libc_sendmmsg"; - return vcom_socket_setsockopt (__fd, __level, __optname, - __optval, __optlen); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "vmessages %p, vlen %u, flags 0x%x", + getpid (), fd, fd, func_str, vmessages, vlen, flags); -int -setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) -{ - int rv; - pid_t pid = getpid (); + size = libc_sendmmsg (fd, vmessages, vlen, flags); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - rv = vcom_setsockopt (__fd, __level, __optname, __optval, __optlen); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] setsockopt: " - "'%04d'='%04d', '%04d', '%04d', " - "'%p', '%04d'\n", - pid, rv, __fd, __level, __optname, __optval, __optlen); - if (rv != 0) + if (size < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return 0; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_setsockopt (__fd, __level, __optname, __optval, __optlen); + return size; } +#endif -/* - * Prepare to accept connections on socket FD. - * N connection requests will be queued before further - * requests are refused. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_listen (int __fd, int __n) +ssize_t +recvmsg (int fd, struct msghdr * message, int flags) { - if (vcom_init () != 0) + ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - return -1; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; } + else + { + func_str = "libc_recvmsg"; - return vcom_socket_listen (__fd, __n); -} + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "message %p, flags 0x%x", + getpid (), fd, fd, func_str, message, flags); -int -listen (int __fd, int __n) -{ - int rv; - pid_t pid = getpid (); + size = libc_recvmsg (fd, message, flags); + } - if (is_vcom_socket_fd (__fd)) + if (VCOM_DEBUG > 2) { - rv = vcom_listen (__fd, __n); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] listen: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __n); - if (rv != 0) + if (size < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return 0; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_listen (__fd, __n); + return size; } -/* - * Await a connection on socket FD. - * When a connection arrives, open a new socket to communicate - * with it, set *ADDR (which is *ADDR_LEN bytes long) to the address - * of the connecting peer and *ADDR_LEN to the address's actual - * length, and return the new socket's descriptor, or -1 for errors. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ +#ifdef USE_GNU int -vcom_accept (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len) +recvmmsg (int fd, struct mmsghdr *vmessages, + unsigned int vlen, int flags, struct timespec *tmo) { + ssize_t size; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); - if (vcom_init () != 0) + if ((errno = -vcom_init ())) + return -1; + + if (sid != INVALID_SESSION_ID) { - return -1; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + size = -1; } - return vcom_socket_accept (__fd, __addr, __addr_len); -} + else + { + func_str = "libc_recvmmsg"; -int -accept (int __fd, __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len) -{ - int rv = -1; - pid_t pid = getpid (); - pthread_t tid = pthread_self (); + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "vmessages %p, vlen %u, flags 0x%x, tmo %p", + getpid (), fd, fd, func_str, vmessages, vlen, + flags, tmo); - if (is_vcom_socket_fd (__fd)) + size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo); + } + + if (VCOM_DEBUG > 2) { - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] accept1: " - "'%04d'='%04d', '%p', '%p'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __fd, __addr, __addr_len); - rv = vcom_accept (__fd, __addr, __addr_len); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d][%lu (0x%lx)] accept2: " - "'%04d'='%04d', '%p', '%p'\n", - pid, (unsigned long) tid, (unsigned long) tid, - rv, __fd, __addr, __addr_len); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) + if (size < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, size, errno_val); + errno = errno_val; } - return rv; + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, size, size); } - return libc_accept (__fd, __addr, __addr_len); + return size; } +#endif -/* - * Similar to 'accept' but takes an additional parameter to specify - * flags. - * This function is a cancellation point and therefore not marked - * with __THROW. - * */ int -vcom_accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags) +getsockopt (int fd, int level, int optname, + void *__restrict optval, socklen_t * __restrict optlen) { + int rv; + const char *func_str = __func__; + u32 sid = vcom_sid_from_fd (fd); + u32 buflen = (u32) * optlen; - if (vcom_init () != 0) - { - return -1; - } - - return vcom_socket_accept4 (__fd, __addr, __addr_len, __flags); -} + if ((errno = -vcom_init ())) + return -1; -int -accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags) -{ - int rv = 0; - pid_t pid = getpid (); + if (sid != INVALID_SESSION_ID) + { + rv = -EOPNOTSUPP; - fprintf (stderr, - "[%d] accept4: in the beginning... " - "'%04d'='%04d', '%p', '%p', '%04x'\n", - pid, rv, __fd, __addr, __addr_len, __flags); + switch (level) + { + case SOL_TCP: + switch (optname) + { + case TCP_NODELAY: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY, + optval, optlen); + break; + case TCP_MAXSEG: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS, + optval, optlen); + break; + case TCP_KEEPIDLE: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE, + optval, optlen); + break; + case TCP_KEEPINTVL: + func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), SOL_TCP", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL, + optval, optlen); + break; + case TCP_INFO: + if (optval && optlen && (*optlen == sizeof (struct tcp_info))) + { + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), " + "SOL_TCP, TCP_INFO, optval %p, " + "optlen %d: #LDP-NOP#", + getpid (), fd, fd, sid, sid, + optval, *optlen); + memset (optval, 0, *optlen); + rv = VPPCOM_OK; + } + else + rv = -EFAULT; + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_TCP, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_IPV6: + switch (optname) + { + case IPV6_V6ONLY: + func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY, + optval, optlen); + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_IPV6, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_SOCKET: + switch (optname) + { + case SO_ACCEPTCONN: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN, + optval, optlen); + break; + case SO_KEEPALIVE: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE, + optval, optlen); + break; + case SO_PROTOCOL: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL, + optval, optlen); + *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM; + break; + case SO_SNDBUF: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), optlen %d", + getpid (), fd, fd, func_str, sid, sid, buflen); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN, + optval, optlen); + break; + case SO_RCVBUF: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), optlen %d", + getpid (), fd, fd, func_str, sid, sid, *optlen); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN, + optval, optlen); + break; + case SO_REUSEADDR: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR, + optval, optlen); + break; + case SO_BROADCAST: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST, + optval, optlen); + break; + case SO_ERROR: + func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR, + optval, optlen); + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_SOCKET, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + default: + break; + } - if (is_vcom_socket_fd (__fd)) - { - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - rv = vcom_accept4 (__fd, __addr, __addr_len, __flags); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] accept4: VCL " - "'%04d'='%04d', '%p', '%p', '%04x'\n", - pid, rv, __fd, __addr, __addr_len, __flags); - if (VCOM_DEBUG > 0) - vcom_socket_main_show (); - if (rv < 0) + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; } - return rv; } - fprintf (stderr, - "[%d] accept4: libc " - "'%04d'='%04d', '%p', '%p', '%04x'\n", - pid, rv, __fd, __addr, __addr_len, __flags); + else + { + func_str = "libc_getsockopt"; - return libc_accept4 (__fd, __addr, __addr_len, __flags); -} + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " + "optname %d, optval %p, optlen %d", + getpid (), fd, fd, func_str, level, optname, + optval, optlen); -/* - * Shut down all or part of the connection open on socket FD. - * HOW determines what to shut down: - * SHUT_RD = No more receptions; - * SHUT_WR = No more transmissions; - * SHUT_RDWR = No more receptions or transmissions. - * Returns 0 on success, -1 for errors. - * */ -int -vcom_shutdown (int __fd, int __how) -{ - if (vcom_init () != 0) + rv = libc_getsockopt (fd, level, optname, optval, optlen); + } + + if (VCOM_DEBUG > 1) { - return -1; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - return vcom_socket_shutdown (__fd, __how); + return rv; } int -shutdown (int __fd, int __how) +setsockopt (int fd, int level, int optname, + const void *optval, socklen_t optlen) { int rv; - pid_t pid = getpid (); + const char *func_str = __func__; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (is_vcom_socket_fd (__fd)) + if (sid != INVALID_SESSION_ID) { - rv = vcom_shutdown (__fd, __how); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] shutdown: " - "'%04d'='%04d', '%04d'\n", pid, rv, __fd, __how); - if (rv != 0) + rv = -EOPNOTSUPP; + + switch (level) + { + case SOL_TCP: + switch (optname) + { + case TCP_NODELAY: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY, + (void *) optval, &optlen); + break; + case TCP_MAXSEG: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS, + (void *) optval, &optlen); + break; + case TCP_KEEPIDLE: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, + (void *) optval, &optlen); + break; + case TCP_KEEPINTVL: + func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x), SOL_TCP", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, + (void *) optval, &optlen); + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_TCP, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_IPV6: + switch (optname) + { + case IPV6_V6ONLY: + func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY, + (void *) optval, &optlen); + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_IPV6, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + case SOL_SOCKET: + switch (optname) + { + case SO_KEEPALIVE: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE, + (void *) optval, &optlen); + break; + case SO_REUSEADDR: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR, + (void *) optval, &optlen); + break; + case SO_BROADCAST: + func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): " + "sid %u (0x%x)", + getpid (), fd, fd, func_str, sid, sid); + rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST, + (void *) optval, &optlen); + break; + default: + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): " + "sid %u (0x%x), SOL_SOCKET, " + "optname %d unsupported!", + getpid (), fd, fd, func_str, sid, sid, optname); + break; + } + break; + default: + break; + } + + if (rv != VPPCOM_OK) { errno = -rv; - return -1; + rv = -1; } - return 0; } - return libc_shutdown (__fd, __how); -} + else + { + func_str = "libc_setsockopt"; -int -vcom_epoll_create (int __size) -{ + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, " + "optname %d, optval %p, optlen %d", + getpid (), fd, fd, func_str, level, optname, + optval, optlen); - if (vcom_init () != 0) - { - return -1; + rv = libc_setsockopt (fd, level, optname, optval, optlen); } - if (__size <= 0) + if (VCOM_DEBUG > 1) { - return -EINVAL; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } - - /* __size argument is ignored "thereafter" */ - return vcom_epoll_create1 (0); + return rv; } -/* - * __size argument is ignored, but must be greater than zero - */ int -epoll_create (int __size) +listen (int fd, int n) { - int rv = 0; - pid_t pid = getpid (); + int rv; + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); - rv = vcom_epoll_create (__size); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_create: " "'%04d'='%04d'\n", pid, rv, __size); - if (rv < 0) - { - errno = -rv; - return -1; - } - return rv; -} + if ((errno = -vcom_init ())) + return -1; -int -vcom_epoll_create1 (int __flags) -{ - if (vcom_init () != 0) + if (sid != INVALID_SESSION_ID) { - return -1; - } + func_str = "vppcom_session_listen"; - if (__flags < 0) - { - return -EINVAL; + if (VCOM_DEBUG > 0) + clib_warning + ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d", + getpid (), fd, fd, func_str, sid, sid, n); + + rv = vppcom_session_listen (sid, n); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } } - if (__flags & ~EPOLL_CLOEXEC) + else { - return -EINVAL; - } - /* __flags can be either zero or EPOLL_CLOEXEC */ - /* implementation */ - return vcom_socket_epoll_create1 (__flags); -} + func_str = "libc_listen"; -/* - * __flags can be either zero or EPOLL_CLOEXEC - * */ -int -epoll_create1 (int __flags) -{ - int rv = 0; - pid_t pid = getpid (); + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d", + getpid (), fd, fd, func_str, n); + + rv = libc_listen (fd, n); + } - rv = vcom_epoll_create1 (__flags); if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_create: " "'%04d'='%08x'\n", pid, rv, __flags); - if (rv < 0) { - errno = -rv; - return -1; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } return rv; } static inline int -ep_op_has_event (int op) +vcom_accept4 (int listen_fd, __SOCKADDR_ARG addr, + socklen_t * __restrict addr_len, int flags) { - return op != EPOLL_CTL_DEL; -} + int rv; + const char *func_str; + u32 listen_sid = vcom_sid_from_fd (listen_fd); + int accept_sid; -int -vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) -{ - if (vcom_init () != 0) - { - return -1; - } + if ((errno = -vcom_init ())) + return -1; - /* - * the requested operation __op is not supported - * by this interface */ - if (!((__op == EPOLL_CTL_ADD) || - (__op == EPOLL_CTL_MOD) || (__op == EPOLL_CTL_DEL))) + if (listen_sid != INVALID_SESSION_ID) { - return -EINVAL; - } + vppcom_endpt_t ep; + u8 src_addr[sizeof (struct sockaddr_in6)]; + ep.ip = src_addr; + + func_str = "vppcom_session_accept"; + + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "listen sid %u (0x%x), ep %p, flags 0x%x", + getpid (), listen_fd, listen_fd, func_str, + listen_sid, listen_sid, ep, flags); - /* op is ADD or MOD but event parameter is NULL */ - if ((ep_op_has_event (__op) && !__event)) + accept_sid = vppcom_session_accept (listen_sid, &ep, flags); + if (accept_sid < 0) + { + errno = -accept_sid; + rv = -1; + } + else + { + rv = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep); + if (rv != VPPCOM_OK) + { + (void) vppcom_session_close ((u32) accept_sid); + errno = -rv; + rv = -1; + } + else + { + func_str = "vcom_fd_from_sid"; + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "accept sid %u (0x%x), ep %p, flags 0x%x", + getpid (), listen_fd, listen_fd, + func_str, accept_sid, accept_sid, ep, flags); + rv = vcom_fd_from_sid ((u32) accept_sid); + if (rv < 0) + { + (void) vppcom_session_close ((u32) accept_sid); + errno = -rv; + rv = -1; + } + } + } + } + else { - return -EFAULT; + func_str = "libc_accept4"; + + if (VCOM_DEBUG > 0) + clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): " + "addr %p, addr_len %p, flags 0x%x", + getpid (), listen_fd, listen_fd, func_str, + addr, addr_len, flags); + + rv = libc_accept4 (listen_fd, addr, addr_len, flags); } - /* fd is same as epfd */ - /* do not permit adding an epoll file descriptor inside itself */ - if (__epfd == __fd) + if (VCOM_DEBUG > 0) { - return -EINVAL; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), listen_fd, + listen_fd, func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)", + getpid (), listen_fd, listen_fd, rv, rv); } - - /* implementation */ - return vcom_socket_epoll_ctl (__epfd, __op, __fd, __event); + return rv; } -/* - * implement the controller interface for epoll - * that enables the insertion/removal/change of - * file descriptors inside the interest set. - */ int -epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event) +accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len, + int flags) { - int rv; - pid_t pid = getpid (); + return vcom_accept4 (fd, addr, addr_len, flags); +} - rv = vcom_epoll_ctl (__epfd, __op, __fd, __event); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_ctl: " - "'%04d'='%04d', '%04d', '%04d'\n", pid, rv, __epfd, __op, __fd); - if (rv != 0) - { - errno = -rv; - return -1; - } - return 0; +int +accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len) +{ + return vcom_accept4 (fd, addr, addr_len, 0); } int -epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout) +shutdown (int fd, int how) { int rv; - pid_t pid = getpid (); + const char *func_str; + u32 sid = vcom_sid_from_fd (fd); + + if ((errno = -vcom_init ())) + return -1; - if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS) + if (sid != INVALID_SESSION_ID) { - fprintf (stderr, "[%d] ERROR: epoll_wait() invalid maxevents %d\n", - pid, __maxevents); - errno = EINVAL; - return -1; + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; + rv = -1; + } + else + { + func_str = "libc_shutdown"; + + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d", + getpid (), fd, fd, func_str, how); + + rv = libc_shutdown (fd, how); } - rv = - vcom_socket_epoll_pwait (__epfd, __events, __maxevents, __timeout, NULL); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] epoll_wait: " - "'%04d'='%04d', '%p', " - "'%04d', '%04d'\n", - pid, rv, __epfd, __events, __maxevents, __timeout); - if (rv < 0) + if (VCOM_DEBUG > 1) { - errno = -rv; - return -1; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } return rv; } - int -epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, const __sigset_t * __ss) +epoll_create1 (int flags) { + const char *func_str; int rv; - pid_t pid = getpid (); - if (__maxevents <= 0 || __maxevents > EP_MAX_EVENTS) + if ((errno = -vcom_init ())) + return -1; + + func_str = "vppcom_epoll_create"; + + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: calling %s()", getpid (), func_str); + + rv = vppcom_epoll_create (); + + if (PREDICT_FALSE (rv < 0)) { - errno = EINVAL; - return -1; + errno = -rv; + rv = -1; } + else + rv = vcom_fd_from_sid ((u32) rv); - if (is_vcom_epfd (__epfd)) + if (VCOM_DEBUG > 1) { - rv = - vcom_socket_epoll_pwait (__epfd, __events, __maxevents, __timeout, - __ss); - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] epoll_pwait: " - "'%04d'='%04d', '%p', " - "'%04d', '%04d', " - "'%p'\n", - pid, rv, __epfd, __events, __maxevents, __timeout, __ss); if (rv < 0) { - errno = -rv; - return -1; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", + getpid (), func_str, rv, errno_val); + errno = errno_val; } - return rv; - } - else - { - errno = EINVAL; - return -1; + else + clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv); } - - return 0; + return rv; } -/* Poll the file descriptors described by the NFDS structures starting at - FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for - an event to occur; if TIMEOUT is -1, block until an event occurs. - Returns the number of file descriptors with events, zero if timed out, - or -1 for errors. - - This function is a cancellation point and therefore not marked with - __THROW. */ +int +epoll_create (int size) +{ + return epoll_create1 (0); +} int -vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) +epoll_ctl (int epfd, int op, int fd, struct epoll_event *event) { - int rv = 0; - pid_t pid = getpid (); + int rv; + const char *func_str; + u32 vep_idx = vcom_sid_from_fd (epfd); + + if ((errno = -vcom_init ())) + return -1; + + if (vep_idx != INVALID_SESSION_ID) + { + u32 sid = vcom_sid_from_fd (fd); + + if (sid != INVALID_SESSION_ID) + { + func_str = "vppcom_epoll_create"; - struct rlimit nofile_limit; - struct pollfd vcom_fds[MAX_POLL_NFDS_DEFAULT]; - nfds_t fds_idx = 0; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p", + getpid (), epfd, epfd, func_str, vep_idx, vep_idx, + sid, sid, event); - /* actual set of file descriptors to be monitored */ - nfds_t libc_nfds = 0; - nfds_t vcom_nfds = 0; + rv = vppcom_epoll_ctl (vep_idx, op, sid, event); + if (rv != VPPCOM_OK) + { + errno = -rv; + rv = -1; + } + } + else + { + int epfd; + u32 size = sizeof (epfd); - /* ready file descriptors - * - * number of structures which have nonzero revents fields - * in other words, descriptors with events or errors reported. - * */ - /* after call to libc_poll () */ - int rlibc_nfds = 0; - /* after call to vcom_socket_poll () */ - int rvcom_nfds = 0; + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, + 0, 0); + if (!epfd) + { + func_str = "libc_epoll_create1"; + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC", + getpid (), func_str); - /* timeout value in units of timespec */ - struct timespec timeout_ts; - struct timespec start_time, now, end_time; + epfd = libc_epoll_create1 (EPOLL_CLOEXEC); + if (epfd < 0) + { + rv = epfd; + goto done; + } + func_str = "vppcom_session_attr[SET_LIBC_EPFD]"; + rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD, + &epfd, &size); + if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + } + else if (PREDICT_FALSE (epfd < 0)) + { + errno = -epfd; + rv = -1; + goto done; + } - /* get start_time */ - rv = clock_gettime (CLOCK_MONOTONIC, &start_time); - if (rv == -1) + rv = libc_epoll_ctl (epfd, op, fd, event); + } + } + else { - rv = -errno; - goto poll_done; + func_str = "libc_epoll_ctl"; + + if (VCOM_DEBUG > 1) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "op %d, fd %d (0x%x), event %p", + getpid (), epfd, epfd, func_str, op, fd, fd, event); + + rv = libc_epoll_ctl (epfd, op, fd, event); } - /* set timeout_ts & end_time */ - if (__timeout >= 0) +done: + if (VCOM_DEBUG > 1) { - /* set timeout_ts */ - timeout_ts.tv_sec = __timeout / MSEC_PER_SEC; - timeout_ts.tv_nsec = (__timeout % MSEC_PER_SEC) * NSEC_PER_MSEC; - set_normalized_timespec (&timeout_ts, - timeout_ts.tv_sec, timeout_ts.tv_nsec); - /* set end_time */ - if (__timeout) + if (rv < 0) { - end_time = timespec_add (start_time, timeout_ts); + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), fd, fd, + func_str, rv, errno_val); + errno = errno_val; } else - { - end_time = start_time; - } + clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)", + getpid (), fd, fd, rv, rv); } + return rv; +} - if (vcom_init () != 0) - { - rv = -1; - goto poll_done; - } +static inline int +vcom_epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + const char *func_str; + int rv; + double time_to_wait = (double) 0; + double time_out, now = 0; + u32 vep_idx = vcom_sid_from_fd (epfd); + int libc_epfd; - /* validate __fds */ - if (!__fds) - { - rv = -EFAULT; - goto poll_done; - } + if ((errno = -vcom_init ())) + return -1; - /* validate __nfds */ - /*TBD: call getrlimit once when vcl-ldpreload library is init */ - rv = getrlimit (RLIMIT_NOFILE, &nofile_limit); - if (rv != 0) - { - rv = -errno; - goto poll_done; - } - if (__nfds >= nofile_limit.rlim_cur) + if (PREDICT_FALSE (!events || (timeout < -1))) { - rv = -EINVAL; - goto poll_done; + errno = EFAULT; + return -1; } - /* - * for the POC, it's fair to assume that nfds is less than 1024 - * */ - if (__nfds >= MAX_POLL_NFDS_DEFAULT) + if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID)) { - rv = -EINVAL; - goto poll_done; + clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!", + getpid (), epfd, epfd, vep_idx, vep_idx); + errno = EBADFD; + return -1; } - /* set revents field (output parameter) - * to zero - * */ - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0); + time_out = clib_time_now (&vcom->clib_time) + time_to_wait; + + func_str = "vppcom_session_attr[GET_LIBC_EPFD]"; + libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); + if (PREDICT_FALSE (libc_epfd < 0)) { - __fds[fds_idx].revents = 0; + errno = -libc_epfd; + rv = -1; + goto done; } -#if 0 - /* set revents field (output parameter) - * to zero for user ignored fds - * */ - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) + if (VCOM_DEBUG > 2) + clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), " + "libc_epfd %d (0x%x), events %p, maxevents %d, " + "timeout %d, sigmask %p", getpid (), epfd, epfd, + vep_idx, vep_idx, libc_epfd, libc_epfd, events, + maxevents, timeout, sigmask); + do { - /* - * if negative fd, ignore events field - * and set output parameter (revents field) to zero */ - if (__fds[fds_idx].fd < 0) + if (!vcom->epoll_wait_vcl) { - __fds[fds_idx].revents = 0; - } - } -#endif + func_str = "vppcom_epoll_wait"; - /* - * 00. prepare __fds and vcom_fds for polling - * copy __fds to vcom_fds - * 01. negate all except libc fds in __fds, - * ignore user negated fds - * 02. negate all except vcom_fds in vocm fds, - * ignore user negated fds - * ignore fd 0 by setting it to negative number - * */ - memcpy (vcom_fds, __fds, sizeof (*__fds) * __nfds); - libc_nfds = 0; - vcom_nfds = 0; - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - /* - * 00. ignore vcom fds in __fds - * 01. ignore libc fds in vcom_fds, - * ignore fd 0 by setting it to negative number. - * as fd 0 cannot be ignored. - */ - if (is_vcom_socket_fd (__fds[fds_idx].fd) || - is_vcom_epfd (__fds[fds_idx].fd)) - { - __fds[fds_idx].fd = -__fds[fds_idx].fd; - vcom_nfds++; + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "vep_idx %d (0x%x), events %p, maxevents %d", + getpid (), epfd, epfd, func_str, + vep_idx, vep_idx, events, maxevents); + + rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0); + if (rv > 0) + { + vcom->epoll_wait_vcl = 1; + goto done; + } + else if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } } else + vcom->epoll_wait_vcl = 0; + + if (libc_epfd > 0) { - libc_nfds++; - /* ignore fd 0 by setting it to negative number */ - if (!vcom_fds[fds_idx].fd) - { - vcom_fds[fds_idx].fd = -1; - } - vcom_fds[fds_idx].fd = -vcom_fds[fds_idx].fd; + func_str = "libc_epoll_pwait"; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): " + "libc_epfd %d (0x%x), events %p, " + "maxevents %d, sigmask %p", + getpid (), epfd, epfd, func_str, + libc_epfd, libc_epfd, events, maxevents, sigmask); + + rv = libc_epoll_pwait (epfd, events, maxevents, 1, sigmask); + if (rv != 0) + goto done; } + + if (timeout != -1) + now = clib_time_now (&vcom->clib_time); } + while (now < time_out); - /* - * polling loop - * - * poll on libc fds and vcom fds - * - * specifying a timeout of zero causes libc_poll() and - * vcom_socket_poll() to return immediately, even if no - * file descriptors are ready - * */ - do +done: + if (VCOM_DEBUG > 3) { - rlibc_nfds = 0; - rvcom_nfds = 0; + if (rv < 0) + { + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! " + "rv %d, errno = %d", getpid (), epfd, epfd, + func_str, rv, errno_val); + errno = errno_val; + } + else + clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)", + getpid (), epfd, epfd, rv, rv); + } + return rv; +} + +int +epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + return vcom_epoll_pwait (epfd, events, maxevents, timeout, sigmask); +} + +int +epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + return vcom_epoll_pwait (epfd, events, maxevents, timeout, NULL); +} + +int +poll (struct pollfd *fds, nfds_t nfds, int timeout) +{ + const char *func_str = __func__; + int rv, i, n_libc_fds, n_revents; + u32 sid; + vcl_poll_t *vp; + double wait_for_time; - /* - * timeout parameter for libc_poll () set to zero - * to poll on libc fds - * */ + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d", + getpid (), fds, nfds, timeout); - /* poll on libc fds */ - if (libc_nfds) + if (timeout >= 0) + wait_for_time = (f64) timeout / 1000; + else + wait_for_time = -1; + + n_libc_fds = 0; + for (i = 0; i < nfds; i++) + { + if (fds[i].fd >= 0) { - /* - * a timeout of zero causes libc_poll() - * to return immediately - * */ - rlibc_nfds = libc_poll (__fds, __nfds, 0); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] poll libc: " - "'%04d'='%08lu'\n", pid, rlibc_nfds, __nfds); + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, " + ".revents = 0x%x", getpid (), i, fds[i].fd, + fds[i].fd, fds[i].events, fds[i].revents); - if (rlibc_nfds < 0) + sid = vcom_sid_from_fd (fds[i].fd); + if (sid != INVALID_SESSION_ID) { - rv = -errno; - goto poll_done_update_nfds; + fds[i].fd = -fds[i].fd; + vec_add2 (vcom->vcl_poll, vp, 1); + vp->fds_ndx = i; + vp->sid = sid; + vp->events = fds[i].events; +#ifdef __USE_XOPEN2K + if (fds[i].events & POLLRDNORM) + vp->events |= POLLIN; + if (fds[i].events & POLLWRNORM) + vp->events |= POLLOUT; +#endif + vp->revents = &fds[i].revents; } + else + n_libc_fds++; } + } - /* - * timeout parameter for vcom_socket_poll () set to zero - * to poll on vcom fds - * */ - - /* poll on vcom fds */ - if (vcom_nfds) + n_revents = 0; + do + { + if (vec_len (vcom->vcl_poll)) { - /* - * a timeout of zero causes vcom_socket_poll() - * to return immediately - * */ - rvcom_nfds = vcom_socket_poll (vcom_fds, __nfds, 0); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] poll vcom: " - "'%04d'='%08lu'\n", pid, rvcom_nfds, __nfds); - if (rvcom_nfds < 0) + func_str = "vppcom_poll"; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: calling %s(): " + "vcl_poll %p, n_sids %u (0x%x): " + "n_libc_fds %u", + getpid (), func_str, vcom->vcl_poll, + vec_len (vcom->vcl_poll), vec_len (vcom->vcl_poll), + n_libc_fds); + + rv = vppcom_poll (vcom->vcl_poll, vec_len (vcom->vcl_poll), 0); + if (rv < 0) { - rv = rvcom_nfds; - goto poll_done_update_nfds; + errno = -rv; + rv = -1; + goto done; } + else + n_revents += rv; } - /* check if any file descriptors changed status */ - if ((libc_nfds && rlibc_nfds > 0) || (vcom_nfds && rvcom_nfds > 0)) + if (n_libc_fds) { - /* something interesting happened */ - rv = rlibc_nfds + rvcom_nfds; - goto poll_done_update_nfds; + func_str = "libc_poll"; + + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u", + getpid (), fds, nfds, vec_len (vcom->vcl_poll)); + + rv = libc_poll (fds, nfds, 0); + if (rv < 0) + goto done; + else + n_revents += rv; } - rv = clock_gettime (CLOCK_MONOTONIC, &now); - if (rv == -1) + if (n_revents) { - rv = -errno; - goto poll_done_update_nfds; + rv = n_revents; + goto done; } } - - /* block indefinitely || timeout elapsed */ - while ((__timeout < 0) || timespec_compare (&now, &end_time) < 0); - - /* timeout expired before anything interesting happened */ + while ((wait_for_time == -1) || + (clib_time_now (&vcom->clib_time) < wait_for_time)); rv = 0; -poll_done_update_nfds: - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) +done: + vec_foreach (vp, vcom->vcl_poll) + { + fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd; +#ifdef __USE_XOPEN2K + if ((fds[vp->fds_ndx].revents & POLLIN) && + (fds[vp->fds_ndx].events & POLLRDNORM)) + fds[vp->fds_ndx].revents |= POLLRDNORM; + if ((fds[vp->fds_ndx].revents & POLLOUT) && + (fds[vp->fds_ndx].events & POLLWRNORM)) + fds[vp->fds_ndx].revents |= POLLWRNORM; +#endif + } + vec_reset_length (vcom->vcl_poll); + + if (VCOM_DEBUG > 3) { - /* ignore negative fds in vcom_fds - * 00. user negated fds - * 01. libc fds - * */ - if (vcom_fds[fds_idx].fd < 0) + if (rv < 0) { - continue; + int errno_val = errno; + perror (func_str); + clib_warning ("LDP<%d>: ERROR: %s() failed! " + "rv %d, errno = %d", getpid (), + func_str, rv, errno_val); + errno = errno_val; } - - /* from here on handle positive vcom fds */ - /* - * restore vcom fds to positive number in __fds - * and update revents in __fds with the events - * that actually occurred in vcom fds - * */ - __fds[fds_idx].fd = -__fds[fds_idx].fd; - if (rvcom_nfds) + else { - __fds[fds_idx].revents = vcom_fds[fds_idx].revents; + clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, " + "n_libc_fds %d", getpid (), rv, rv, + vec_len (vcom->vcl_poll), n_libc_fds); + + for (i = 0; i < nfds; i++) + { + if (fds[i].fd >= 0) + { + if (VCOM_DEBUG > 3) + clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), " + ".events = 0x%x, .revents = 0x%x", + getpid (), i, fds[i].fd, fds[i].fd, + fds[i].events, fds[i].revents); + } + } } } -poll_done: - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vpoll: " "'%04d'='%08lu'\n", pid, rv, __nfds); - return rv; -} - -/* - * 00. The field __fds[i].fd contains a file descriptor for an - * open file. - * If this field is negative, then the corresponding - * events field is ignored and the revents field returns zero. - * The field __fds[i].events is an input parameter. - * The field __fds[i].revents is an output parameter. - * 01. Specifying a negative value in timeout - * means an infinite timeout. - * Specifying a timeout of zero causes poll() to return - * immediately, even if no file descriptors are ready. - * - * NOTE: observed __nfds is less than 128 from kubecon strace files - */ - - -int -poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) -{ - int rv = 0; - pid_t pid = getpid (); - - - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] poll1: " "'%04d'='%08lu, %d, 0x%x'\n", - pid, rv, __nfds, __fds[0].fd, __fds[0].events); - rv = vcom_poll (__fds, __nfds, __timeout); - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] poll2: " "'%04d'='%08lu, %d, 0x%x'\n", - pid, rv, __nfds, __fds[0].fd, __fds[0].revents); - if (rv < 0) - { - errno = -rv; - return -1; - } return rv; } -#ifdef __USE_GNU -/* Like poll, but before waiting the threads signal mask is replaced - with that specified in the fourth parameter. For better usability, - the timeout value is specified using a TIMESPEC object. - - This function is a cancellation point and therefore not marked with - __THROW. */ +#ifdef USE_GNU int -vcom_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss) +ppoll (struct pollfd *fds, nfds_t nfds, + const struct timespec *timeout, const sigset_t * sigmask) { - if (vcom_init () != 0) - { - return -1; - } + if ((errno = -vcom_init ())) + return -1; - return -EOPNOTSUPP; -} + clib_warning ("LDP<%d>: LDP-TBD", getpid ()); + errno = ENOSYS; -int -ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss) -{ - int rv = 0; - errno = EOPNOTSUPP; - rv = -1; - return rv; + return -1; } #endif @@ -3283,20 +3398,18 @@ void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void); void DESTRUCTOR_ATTRIBUTE vcom_destructor (void); +/* + * This function is called when the library is loaded + */ void vcom_constructor (void) { - pid_t pid = getpid (); - swrap_constructor (); if (vcom_init () != 0) - { - printf ("\n[%d] vcom_constructor...failed!\n", pid); - } + fprintf (stderr, "\nLDP<%d>: ERROR: vcom_constructor: failed!\n", + getpid ()); else - { - printf ("\n[%d] vcom_constructor...done!\n", pid); - } + clib_warning ("LDP<%d>: VCOM constructor: done!\n", getpid ()); } /* @@ -3305,11 +3418,18 @@ vcom_constructor (void) void vcom_destructor (void) { - pid_t pid = getpid (); - - vcom_destroy (); swrap_destructor (); - printf ("\n[%d] vcom_destructor...done!\n", pid); + if (vcom->init) + { + vppcom_app_destroy (); + vcom->init = 0; + } + + /* Don't use clib_warning() here because that calls writev() + * which will call vcom_init(). + */ + printf ("%s:%d: LDP<%d>: VCOM destructor: done!\n", + __func__, __LINE__, getpid ()); } diff --git a/src/vcl/vcom.h b/src/vcl/vcom.h index e945c8a5d08..0dd86c1c000 100644 --- a/src/vcl/vcom.h +++ b/src/vcl/vcom.h @@ -18,183 +18,23 @@ #if (CLIB_DEBUG > 0) /* Set VCOM_DEBUG 2 for connection debug, 3 for read/write debug output */ -#define VCOM_DEBUG 1 +#define VCOM_DEBUG_INIT 1 #else -#define VCOM_DEBUG 0 +#define VCOM_DEBUG_INIT 0 #endif #include #include #include -#define MAX_VCOM_APP_NAME 256 +#define VCOM_ENV_DEBUG "VCOM_DEBUG" +#define VCOM_ENV_APP_NAME "VCOM_APP_NAME" +#define VCOM_ENV_SID_BIT "VCOM_SID_BIT" -/* Returns 0 on success or -1 on error. */ -extern int vcom_set_app_name (char *__app_name); - -/* - * - * File descriptor based APIs - * - */ - -/* - * vpp implementation of glibc APIs from - */ -extern int vcom_close (int __fd); - -extern ssize_t __wur vcom_read (int __fd, void *__buf, size_t __nbytes); - -extern ssize_t __wur vcom_write (int __fd, const void *__buf, size_t __n); - -extern ssize_t __wur vcom_readv (int __fd, const struct iovec *__iov, - int __iovcnt); - -extern ssize_t __wur vcom_writev (int __fd, const struct iovec *__iov, - int __iovcnt); - -/* - * vpp implementation of glibc APIs from - */ -extern int vcom_fcntl (int __fd, int __cmd, ...); - -/* - * VPP implementation of glibc APIs ioctl - */ -extern int vcom_ioctl (int __fd, unsigned long int __cmd, ...); - -/* - * vpp implementation of glibc APIs from - */ -extern int -vcom_select (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - struct timeval *__restrict __timeout); - -#ifdef __USE_XOPEN2K -extern int -vcom_pselect (int __nfds, fd_set * __restrict __readfds, - fd_set * __restrict __writefds, - fd_set * __restrict __exceptfds, - const struct timespec *__restrict __timeout, - const __sigset_t * __restrict __sigmask); -#endif - -/* - * vpp implementation of glibc APIs from - */ -extern int __THROW vcom_socket (int __domain, int __type, int __protocol); - -/* On Linux, the only supported domain for this call is AF_UNIX -* (or synonymously, AF_LOCAL). Most implementations have the -* same restriction. -* vpp does not implement AF_UNIX domain in this release. -* */ -extern int __THROW -vcom_socketpair (int __domain, int __type, int __protocol, int __fds[2]); - -extern int __THROW -vcom_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -extern int __THROW -vcom_getsockname (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len); - -extern int -vcom_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -extern int __THROW -vcom_getpeername (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len); - -extern ssize_t -vcom_sendfile (int __out_fd, int __in_fd, off_t * __offset, int __len); - -extern ssize_t vcom_recv (int __fd, void *__buf, size_t __n, int __flags); - -extern ssize_t -vcom_sendto (int __fd, const void *__buf, size_t __n, - int __flags, __CONST_SOCKADDR_ARG __addr, socklen_t __addr_len); - -extern ssize_t -vcom_recvfrom (int __fd, void *__restrict __buf, - size_t __n, int __flags, - __SOCKADDR_ARG __addr, socklen_t * __restrict __addr_len); - -extern ssize_t -vcom_sendmsg (int __fd, const struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -extern int -sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags); -#endif - -extern ssize_t vcom_recvmsg (int __fd, struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -extern int -vcom_recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, struct timespec *__tmo); -#endif - -extern int __THROW -vcom_getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, socklen_t * __restrict __optlen); - -extern int __THROW -vcom_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen); - -extern int __THROW vcom_listen (int __fd, int __n); - -extern int -vcom_accept (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len); - -#ifdef __USE_GNU -/* - * Similar to 'accept' but takes an additional parameter to specify - * flags. - * */ -/* TBD: implemented later */ -extern int -vcom_accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags); -#endif - -extern int __THROW vcom_shutdown (int __fd, int __how); - -extern int __THROW vcom_epoll_create (int __size); - -extern int __THROW vcom_epoll_create1 (int __flags); - -extern int __THROW -vcom_epoll_ctl (int __epfd, int __op, int __fd, struct epoll_event *__event); - -extern int -vcom_epoll_wait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout); - -extern int -vcom_epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, const __sigset_t * __ss); - -/* - * NOTE: observed __nfds is less than 128 from kubecon strace files - * for the POC, it's fair to assume that nfds is less than 1024. - * TBD: make it thread safe and design to scale. - * */ -#define MAX_POLL_NFDS_DEFAULT 1024 -extern int vcom_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); - -#ifdef __USE_GNU -extern int -vcom_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss); -#endif +#define VCOM_SID_BIT_MIN 9 +#define VCOM_SID_BIT_MAX 30 +#define VCOM_APP_NAME_MAX 256 #endif /* included_vcom_h */ diff --git a/src/vcl/vcom_socket.c b/src/vcl/vcom_socket.c deleted file mode 100644 index 13e008cc6c0..00000000000 --- a/src/vcl/vcom_socket.c +++ /dev/null @@ -1,3733 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#define __need_IOV_MAX -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#ifndef IOV_MAX -#define IOV_MAX __IOV_MAX -#endif - -/* - * VCOM_SOCKET Private definitions and functions. - */ - -typedef struct vcom_socket_main_t_ -{ - u8 init; - clib_time_t clib_time; - pid_t my_pid; - - /* vcom_socket pool */ - vcom_socket_t *vsockets; - - /* Hash table for socketidx to fd mapping */ - uword *sockidx_by_fd; - - /* vcom_epoll pool */ - vcom_epoll_t *vepolls; - - /* Hash table for epollidx to epfd mapping */ - uword *epollidx_by_epfd; - - /* common epitem poll for all epfd */ - /* TBD: epitem poll per epfd */ - /* vcom_epitem pool */ - vcom_epitem_t *vepitems; - - /* Hash table for epitemidx to epfdfd mapping */ - uword *epitemidx_by_epfdfd; - - /* Hash table - key:epfd, value:vec of epitemidx */ - uword *epitemidxs_by_epfd; - /* Hash table - key:fd, value:vec of epitemidx */ - uword *epitemidxs_by_fd; - - u8 *io_buffer; -} vcom_socket_main_t; - -vcom_socket_main_t vcom_socket_main; - - -static int -vcom_socket_open_socket (int domain, int type, int protocol) -{ - int rv = -1; - - /* handle domains implemented by vpp */ - switch (domain) - { - case AF_INET: - case AF_INET6: - /* get socket type and - * handle the socket types supported by vpp */ - switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) - { - case SOCK_STREAM: - case SOCK_DGRAM: - /* the type argument serves a second purpose, - * in addition to specifying a socket type, - * it may include the bitwise OR of any of - * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify - * the behavior of socket. */ - rv = libc_socket (domain, type, protocol); - if (rv == -1) - rv = -errno; - break; - - default: - break; - } - - break; - - default: - break; - } - - return rv; -} - -static int -vcom_socket_open_epoll (int flags) -{ - int rv = -1; - - if (flags < 0) - { - return -EINVAL; - } - if (flags && (flags & ~EPOLL_CLOEXEC)) - { - return -EINVAL; - } - - /* flags can be either zero or EPOLL_CLOEXEC */ - rv = libc_epoll_create1 (flags); - if (rv == -1) - rv = -errno; - - return rv; -} - -static int -vcom_socket_close_socket (int fd) -{ - int rv; - - rv = libc_close (fd); - if (rv == -1) - rv = -errno; - - return rv; -} - -static int -vcom_socket_close_epoll (int epfd) -{ - int rv; - - rv = libc_close (epfd); - if (rv == -1) - rv = -errno; - - return rv; -} - -/* - * Public API functions - */ - - -int -vcom_socket_is_vcom_fd (int fd) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, fd); - - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND) - return 1; - } - return 0; -} - -int -vcom_socket_is_vcom_epfd (int epfd) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_epoll_t *vepoll; - - p = hash_get (vsm->epollidx_by_epfd, epfd); - - if (p) - { - vepoll = pool_elt_at_index (vsm->vepolls, p[0]); - if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND) - return 1; - } - return 0; -} - -static inline int -vcom_socket_get_sid (int fd) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, fd); - - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND) - return vsock->sid; - } - return INVALID_SESSION_ID; -} - -static inline int -vcom_socket_get_vep_idx (int epfd) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_epoll_t *vepoll; - - p = hash_get (vsm->epollidx_by_epfd, epfd); - - if (p) - { - vepoll = pool_elt_at_index (vsm->vepolls, p[0]); - if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND) - return vepoll->vep_idx; - } - return INVALID_VEP_IDX; -} - -static inline int -vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, fd); - - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND) - { - *vsockp = vsock; - return vsock->sid; - } - } - return INVALID_SESSION_ID; -} - -static inline int -vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_epoll_t *vepoll; - - p = hash_get (vsm->epollidx_by_epfd, epfd); - - if (p) - { - vepoll = pool_elt_at_index (vsm->vepolls, p[0]); - if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND) - { - *vepollp = vepoll; - return vepoll->vep_idx; - } - } - return INVALID_VEP_IDX; -} - - -static int -vcom_socket_close_vepoll (int epfd) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_epoll_t *vepoll; - - p = hash_get (vsm->epollidx_by_epfd, epfd); - if (!p) - return -EBADF; - - vepoll = pool_elt_at_index (vsm->vepolls, p[0]); - if (!vepoll) - return -EBADF; - - if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (vepoll->count) - { - if (!vepoll->close) - { - vepoll->close = 1; - return 0; - } - else - { - return -EBADF; - } - } - - /* count is zero */ - rv = vppcom_session_close (vepoll->vep_idx); - rv = vcom_socket_close_epoll (vepoll->epfd); - - vepoll_init (vepoll); - hash_unset (vsm->epollidx_by_epfd, epfd); - pool_put (vsm->vepolls, vepoll); - - return rv; -} - -static int -vcom_socket_close_vsock (int fd) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - vcom_epitem_t *vepitem; - - i32 *vepitemidxs = 0; - i32 *vepitemidxs_var = 0; - - p = hash_get (vsm->sockidx_by_fd, fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - rv = vppcom_session_close (vsock->sid); - rv = vcom_socket_close_socket (vsock->fd); - - vsocket_init (vsock); - hash_unset (vsm->sockidx_by_fd, fd); - pool_put (vsm->vsockets, vsock); - - /* - * NOTE: - * Before calling close(), user should remove - * this fd from the epoll-set of all epoll instances, - * otherwise resource(epitems) leaks ensues. - */ - - /* - * 00. close all epoll instances that are marked as "close" - * of which this fd is the "last" remaining member. - * 01. epitems associated with this fd are intentionally - * not removed, see NOTE: above. - * */ - - /* does this fd participate in epoll */ - p = hash_get (vsm->epitemidxs_by_fd, fd); - if (p) - { - vepitemidxs = *(i32 **) p; - vec_foreach (vepitemidxs_var, vepitemidxs) - { - vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]); - if (vepitem && vepitem->fd == fd && - vepitem->type == FD_TYPE_VCOM_SOCKET) - { - i32 vep_idx; - vcom_epoll_t *vepoll; - if ((vep_idx = - vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd, - &vepoll)) != - INVALID_VEP_IDX) - { - if (vepoll->close) - { - if (vepoll->count == 1) - { - /* - * force count to zero and - * close this epoll instance - * */ - vepoll->count = 0; - vcom_socket_close_vepoll (vepoll->epfd); - } - else - { - vepoll->count -= 1; - } - } - } - } - - } - } - - return rv; -} - -int -vcom_socket_close (int __fd) -{ - int rv; - - if (vcom_socket_is_vcom_fd (__fd)) - { - rv = vcom_socket_close_vsock (__fd); - } - else if (vcom_socket_is_vcom_epfd (__fd)) - { - rv = vcom_socket_close_vepoll (__fd); - } - else - { - rv = -EBADF; - } - - return rv; -} - -ssize_t -vcom_socket_read (int __fd, void *__buf, size_t __nbytes) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (!__buf) - { - return -EINVAL; - } - - rv = vcom_fcntl (__fd, F_GETFL, 0); - if (rv < 0) - { - return rv; - - } - - /* is blocking */ - if (!(rv & O_NONBLOCK)) - { - do - { - rv = vppcom_session_read (vsock->sid, __buf, __nbytes); - } - /* coverity[CONSTANT_EXPRESSION_RESULT] */ - while (rv == -EAGAIN || rv == -EWOULDBLOCK); - return rv; - } - /* The file descriptor refers to a socket and has been - * marked nonblocking(O_NONBLOCK) and the read would - * block. - * */ - /* is non blocking */ - rv = vppcom_session_read (vsock->sid, __buf, __nbytes); - return rv; -} - -ssize_t -vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt) -{ - int rv; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - ssize_t total = 0, len = 0; - int i; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) - return -EINVAL; - - /* Sanity check */ - for (i = 0; i < __iovcnt; ++i) - { - if (SSIZE_MAX - len < __iov[i].iov_len) - return -EINVAL; - len += __iov[i].iov_len; - } - - rv = vcom_fcntl (__fd, F_GETFL, 0); - if (rv < 0) - { - return rv; - } - - /* is blocking */ - if (!(rv & O_NONBLOCK)) - { - do - { - for (i = 0; i < __iovcnt; ++i) - { - rv = vppcom_session_read (vsock->sid, __iov[i].iov_base, - __iov[i].iov_len); - if (rv < 0) - break; - else - { - total += rv; - if (rv < __iov[i].iov_len) - /* Read less than buffer provided, no point to continue */ - break; - } - } - } - /* coverity[CONSTANT_EXPRESSION_RESULT] */ - while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0); - return total; - } - - /* is non blocking */ - for (i = 0; i < __iovcnt; ++i) - { - rv = vppcom_session_read (vsock->sid, __iov[i].iov_base, - __iov[i].iov_len); - if (rv < 0) - { - if (total > 0) - break; - else - { - errno = rv; - return rv; - } - } - else - { - total += rv; - if (rv < __iov[i].iov_len) - /* Read less than buffer provided, no point to continue */ - break; - } - } - return total; -} - -ssize_t -vcom_socket_write (int __fd, const void *__buf, size_t __n) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - if (!__buf) - { - return -EINVAL; - } - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - rv = vppcom_session_write (vsock->sid, (void *) __buf, __n); - return rv; -} - -ssize_t -vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt) -{ - int rv = -1; - ssize_t total = 0; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - int i; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX) - return -EINVAL; - - for (i = 0; i < __iovcnt; ++i) - { - rv = vppcom_session_write (vsock->sid, __iov[i].iov_base, - __iov[i].iov_len); - if (rv < 0) - { - if (total > 0) - break; - else - return rv; - } - else - total += rv; - } - return total; -} - -/* - * RETURN: 0 - invalid cmd - * 1 - cmd not handled by vcom and vppcom - * 2 - cmd handled by vcom socket resource - * 3 - cmd handled by vppcom - * */ -/* TBD: incomplete list of cmd */ -static int -vcom_socket_check_fcntl_cmd (int __cmd) -{ - switch (__cmd) - { - /*cmd not handled by vcom and vppcom */ - /* Fallthrough */ - case F_DUPFD: - case F_DUPFD_CLOEXEC: - return 1; - - /* cmd handled by vcom socket resource */ - /* Fallthrough */ - case F_GETFD: - case F_SETFD: - case F_GETLK: - case F_SETLK: - case F_SETLKW: - case F_GETOWN: - case F_SETOWN: - return 2; - - /* cmd handled by vcom and vppcom */ - case F_SETFL: - case F_GETFL: - return 3; - - /* cmd not handled by vcom and vppcom */ - default: - return 1; - } - return 0; -} - -static inline int -vcom_session_fcntl_va (int __sid, int __cmd, va_list __ap) -{ - int flags = va_arg (__ap, int); - int rv = -EOPNOTSUPP; - uint32_t size; - - size = sizeof (flags); - if (__cmd == F_SETFL) - { - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size); - } - else if (__cmd == F_GETFL) - { - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size); - if (rv == VPPCOM_OK) - rv = flags; - } - - return rv; -} - -int -vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap) -{ - int rv = -EBADF; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - switch (vcom_socket_check_fcntl_cmd (__cmd)) - { - /* invalid cmd */ - case 0: - rv = -EBADF; - break; - /*cmd not handled by vcom and vppcom */ - case 1: - rv = libc_vfcntl (vsock->fd, __cmd, __ap); - break; - /* cmd handled by vcom socket resource */ - case 2: - rv = libc_vfcntl (vsock->fd, __cmd, __ap); - break; - /* cmd handled by vppcom */ - case 3: - rv = vcom_session_fcntl_va (vsock->sid, __cmd, __ap); - break; - - default: - rv = -EINVAL; - break; - } - - return rv; -} - -/* - * RETURN: 0 - invalid cmd - * 1 - cmd not handled by vcom and vppcom - * 2 - cmd handled by vcom socket resource - * 3 - cmd handled by vppcom - */ -static int -vcom_socket_check_ioctl_cmd (unsigned long int __cmd) -{ - int rc; - - switch (__cmd) - { - /* cmd handled by vppcom */ - case FIONREAD: - rc = 3; - break; - - /* cmd not handled by vcom and vppcom */ - default: - rc = 1; - break; - } - return rc; -} - -static inline int -vcom_session_ioctl_va (int __sid, int __cmd, va_list __ap) -{ - int rv; - - switch (__cmd) - { - case FIONREAD: - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0); - break; - - case FIONBIO: - { - u32 flags = va_arg (__ap, int) ? O_NONBLOCK : 0; - u32 len = sizeof (flags); - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &len); - } - break; - - default: - rv = -EOPNOTSUPP; - break; - } - return rv; -} - -int -vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap) -{ - int rv = -EBADF; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - switch (vcom_socket_check_ioctl_cmd (__cmd)) - { - /* Not supported cmd */ - case 0: - rv = -EOPNOTSUPP; - break; - - /* cmd not handled by vcom and vppcom */ - case 1: - rv = libc_vioctl (vsock->fd, __cmd, __ap); - break; - - /* cmd handled by vcom socket resource */ - case 2: - rv = libc_vioctl (vsock->fd, __cmd, __ap); - break; - - /* cmd handled by vppcom */ - case 3: - rv = vcom_session_ioctl_va (vsock->sid, __cmd, __ap); - break; - - default: - rv = -EINVAL; - break; - } - - return rv; -} - -static inline int -vcom_socket_fds_2_sid_fds ( - /* dest */ - int *vcom_nsid_fds, - fd_set * __restrict vcom_rd_sid_fds, - fd_set * __restrict vcom_wr_sid_fds, - fd_set * __restrict vcom_ex_sid_fds, - /* src */ - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds) -{ - int rv = 0; - int fd; - int sid; - /* invalid max_sid is -1 */ - int max_sid = -1; - int nsid = 0; - - /* - * set sid in sid sets corresponding to fd's in fd sets - * compute nsid and vcom_nsid_fds from sid sets - */ - - for (fd = 0; fd < vcom_nfds; fd++) - { - /* - * F fd set, src - * S sid set, dest - */ -#define _(S,F) \ - if ((F) && (S) && FD_ISSET (fd, (F))) \ - { \ - sid = vcom_socket_get_sid (fd); \ - if (sid != INVALID_SESSION_ID) \ - { \ - FD_SET (sid, (S)); \ - if (sid > max_sid) \ - { \ - max_sid = sid; \ - } \ - ++nsid; \ - } \ - else \ - { \ - rv = -EBADFD; \ - goto done; \ - } \ - } - - - _(vcom_rd_sid_fds, vcom_readfds); - _(vcom_wr_sid_fds, vcom_writefds); - _(vcom_ex_sid_fds, vcom_exceptfds); -#undef _ - } - - *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0; - rv = nsid; - -done: - return rv; -} - -/* - * PRE: 00. sid sets were derived from fd sets - * 01. sid sets were updated with sids that actually changed - * status - * 02. fd sets still has watched fds - * - * This function will modify in place fd sets to indicate which fd's - * actually changed status(inferred from sid sets) - */ -static inline int -vcom_socket_sid_fds_2_fds ( - /* dest */ - int *new_vcom_nfds, - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, - /* src */ - int vcom_nsid_fds, - fd_set * __restrict vcom_rd_sid_fds, - fd_set * __restrict vcom_wr_sid_fds, - fd_set * __restrict vcom_ex_sid_fds) -{ - int rv = 0; - int fd; - int sid; - /* invalid max_fd is -1 */ - int max_fd = -1; - int nfd = 0; - - - /* - * modify in place fd sets to indicate which fd's - * actually changed status(inferred from sid sets) - */ - for (fd = 0; fd < vcom_nfds; fd++) - { - /* - * F fd set, dest - * S sid set, src - */ -#define _(S,F) \ - if ((F) && (S) && FD_ISSET (fd, (F))) \ - { \ - sid = vcom_socket_get_sid (fd); \ - if (sid != INVALID_SESSION_ID) \ - { \ - if (!FD_ISSET (sid, (S))) \ - { \ - FD_CLR(fd, (F)); \ - } \ - } \ - else \ - { \ - rv = -EBADFD; \ - goto done; \ - } \ - } - - - _(vcom_rd_sid_fds, vcom_readfds); - _(vcom_wr_sid_fds, vcom_writefds); - _(vcom_ex_sid_fds, vcom_exceptfds); -#undef _ - } - - /* - * compute nfd and new_vcom_nfds from fd sets - */ - for (fd = 0; fd < vcom_nfds; fd++) - { - -#define _(F) \ - if ((F) && FD_ISSET (fd, (F))) \ - { \ - if (fd > max_fd) \ - { \ - max_fd = fd; \ - } \ - ++nfd; \ - } - - - _(vcom_readfds); - _(vcom_writefds); - _(vcom_exceptfds); -#undef _ - - } - - *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0; - rv = nfd; - -done: - return rv; -} - -/* - * PRE: - * vom_socket_select is always called with - * timeout->tv_sec and timeout->tv_usec set to zero. - * hence vppcom_select return immediately. - */ -/* - * TBD: do{body;} while(timeout conditional); timeout loop - */ -int -vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, - struct timeval *__restrict timeout) -{ - static unsigned long vcom_nsid_fds = 0; - int vcom_nsid = 0; - int rv = -EBADF; - - int new_vcom_nfds = 0; - int new_vcom_nfd = 0; - - /* vcom sid fds */ - fd_set vcom_rd_sid_fds; - fd_set vcom_wr_sid_fds; - fd_set vcom_ex_sid_fds; - - /* in seconds eg. 3.123456789 seconds */ - double time_to_wait = (double) 0; - - /* validate inputs */ - if (vcom_nfds < 0) - { - return -EINVAL; - } - - /* convert timeval timeout to double time_to_wait */ - if (timeout) - { - if (timeout->tv_sec == 0 && timeout->tv_usec == 0) - { - /* polling: vppcom_select returns immediately */ - time_to_wait = (double) 0; - } - else - { - /*TBD: use timeval api */ - time_to_wait = (double) timeout->tv_sec + - (double) timeout->tv_usec / (double) 1000000 + - (double) (timeout->tv_usec % 1000000) / (double) 1000000; - } - } - else - { - /* - * no timeout: vppcom_select can block indefinitely - * waiting for a file descriptor to become ready - * */ - /* set to a phantom value */ - time_to_wait = ~0; - } - - /* zero the sid_sets */ - /* - * F fd set - * S sid set - */ -#define _(S,F) \ - if ((F)) \ - { \ - FD_ZERO ((S)); \ - } - - - _(&vcom_rd_sid_fds, vcom_readfds); - _(&vcom_wr_sid_fds, vcom_writefds); - _(&vcom_ex_sid_fds, vcom_exceptfds); -#undef _ - - if (vcom_nfds == 0) - { - if (time_to_wait > 0) - { - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_socket_select called to " - "emulate delay_ns()!\n", getpid ()); - rv = vppcom_select (0, NULL, NULL, NULL, time_to_wait); - } - else - { - fprintf (stderr, "[%d] vcom_socket_select called vcom_nfds = 0 " - "and invalid time_to_wait (%f)!\n", - getpid (), time_to_wait); - } - return 0; - } - - /* populate read, write and except sid_sets */ - vcom_nsid = vcom_socket_fds_2_sid_fds ( - /* dest */ - vcom_readfds || vcom_writefds - || vcom_exceptfds ? (int *) - &vcom_nsid_fds : NULL, - vcom_readfds ? &vcom_rd_sid_fds : - NULL, - vcom_writefds ? &vcom_wr_sid_fds : - NULL, - vcom_exceptfds ? &vcom_ex_sid_fds : - NULL, - /* src */ - vcom_nfds, - vcom_readfds, - vcom_writefds, vcom_exceptfds); - if (vcom_nsid < 0) - { - return vcom_nsid; - } - - rv = vppcom_select (vcom_nsid_fds, - vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds : - NULL, - vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds : - NULL, - vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds : - NULL, time_to_wait); - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] called vppcom_select(): " - "'%04d'='%04d'\n", getpid (), rv, (int) vcom_nsid_fds); - - /* check if any file descriptors changed status */ - if (rv > 0) - { - /* - * on exit, sets are modified in place to indicate which - * file descriptors actually changed status - * */ - - /* - * comply with pre-condition - * do not clear vcom fd sets befor calling - * vcom_socket_sid_fds_2_fds - */ - new_vcom_nfd = vcom_socket_sid_fds_2_fds ( - /* dest */ - &new_vcom_nfds, - vcom_nfds, - vcom_readfds, - vcom_writefds, - vcom_exceptfds, - /* src */ - vcom_nsid_fds, - vcom_readfds ? - &vcom_rd_sid_fds : NULL, - vcom_writefds ? - &vcom_wr_sid_fds : NULL, - vcom_exceptfds ? - &vcom_ex_sid_fds : NULL); - if (new_vcom_nfd < 0) - { - return new_vcom_nfd; - } - if (new_vcom_nfds < 0) - { - return -EINVAL; - } - rv = new_vcom_nfd; - } - return rv; -} - - -int -vcom_socket_socket (int __domain, int __type, int __protocol) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_socket_t *vsock; - - i32 fd; - i32 sid; - i32 sockidx; - u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0; - int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC); - - fd = vcom_socket_open_socket (__domain, __type, __protocol); - if (fd < 0) - { - rv = fd; - goto out; - } - - sid = vppcom_session_create (VPPCOM_VRF_DEFAULT, - (type == SOCK_DGRAM) ? - VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP, - is_nonblocking); - if (sid < 0) - { - rv = sid; - goto out_close_socket; - } - - pool_get (vsm->vsockets, vsock); - vsocket_init (vsock); - - sockidx = vsock - vsm->vsockets; - hash_set (vsm->sockidx_by_fd, fd, sockidx); - - vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND); - return fd; - -out_close_socket: - vcom_socket_close_socket (fd); -out: - return rv; -} - -int -vcom_socket_socketpair (int __domain, int __type, int __protocol, - int __fds[2]) -{ -/* TBD: */ - return 0; -} - -int -vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - vppcom_endpt_t ep; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (!__addr) - { - return -EINVAL; - } - - ep.vrf = VPPCOM_VRF_DEFAULT; - switch (__addr->sa_family) - { - case AF_INET: - if (__len != sizeof (struct sockaddr_in)) - { - return -EINVAL; - } - ep.is_ip4 = VPPCOM_IS_IP4; - ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr; - ep.port = (u16) ((const struct sockaddr_in *) __addr)->sin_port; - break; - - case AF_INET6: - if (__len != sizeof (struct sockaddr_in6)) - { - return -EINVAL; - } - ep.is_ip4 = VPPCOM_IS_IP6; - ep.ip = (u8 *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr; - ep.port = (u16) ((const struct sockaddr_in6 *) __addr)->sin6_port; - break; - - default: - return -1; - break; - } - - rv = vppcom_session_bind (vsock->sid, &ep); - return rv; -} - -static inline int -vcom_socket_copy_ep_to_sockaddr (__SOCKADDR_ARG __addr, - socklen_t * __restrict __len, - vppcom_endpt_t * ep) -{ - int rv = 0; - int sa_len, copy_len; - - __addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6; - switch (__addr->sa_family) - { - case AF_INET: - ((struct sockaddr_in *) __addr)->sin_port = ep->port; - if (*__len > sizeof (struct sockaddr_in)) - *__len = sizeof (struct sockaddr_in); - sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr); - copy_len = *__len - sa_len; - if (copy_len > 0) - memcpy (&((struct sockaddr_in *) __addr)->sin_addr, ep->ip, copy_len); - break; - - case AF_INET6: - ((struct sockaddr_in6 *) __addr)->sin6_port = ep->port; - if (*__len > sizeof (struct sockaddr_in6)) - *__len = sizeof (struct sockaddr_in6); - sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr); - copy_len = *__len - sa_len; - if (copy_len > 0) - memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr. - __in6_u.__u6_addr8, ep->ip, copy_len); - break; - - default: - /* Not possible */ - rv = -EAFNOSUPPORT; - break; - } - - return rv; -} - -int -vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - vppcom_endpt_t ep; - u8 addr_buf[sizeof (struct in6_addr)]; - uint32_t size = sizeof (ep); - - if (!__addr || !__len) - return -EFAULT; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - ep.ip = addr_buf; - rv = vppcom_session_attr (vsock->sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size); - if (rv == VPPCOM_OK) - rv = vcom_socket_copy_ep_to_sockaddr (__addr, __len, &ep); - - return rv; -} - -int -vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - vppcom_endpt_t ep; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - - ep.vrf = VPPCOM_VRF_DEFAULT; - switch (__addr->sa_family) - { - case AF_INET: - ep.is_ip4 = VPPCOM_IS_IP4; - ep.ip = - (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr; - ep.port = - (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port; - break; - - case AF_INET6: - ep.is_ip4 = VPPCOM_IS_IP6; - ep.ip = - (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr; - ep.port = - (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port; - break; - - default: - return -1; - break; - } - - rv = vppcom_session_connect (vsock->sid, &ep); - } - return rv; -} - -static inline int -vcom_session_getpeername (int sid, vppcom_endpt_t * ep) -{ - int rv; - uint32_t size = sizeof (*ep); - - rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size); - return rv; -} - -int -vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - u8 src_addr[sizeof (struct sockaddr_in6)]; - vppcom_endpt_t ep; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (!__addr || !__len) - return -EFAULT; - - ep.ip = src_addr; - rv = vcom_session_getpeername (vsock->sid, &ep); - if (rv == 0) - rv = vcom_socket_copy_ep_to_sockaddr (__addr, __len, &ep); - - return rv; -} - -ssize_t -vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags) -{ - return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0); -} - -/* NOTE: this function is not thread safe or 32-bit friendly */ -ssize_t -vcom_socket_sendfile (int __out_fd, int __in_fd, off_t * __offset, - size_t __len) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - size_t n_bytes_left = __len; - u32 out_sockidx, out_sid = ~0; - size_t bytes_to_read; - int nbytes; - int rv, errno_val; - ssize_t results = 0; - u8 eagain = 0; - - if (VCOM_DEBUG > 2) - clib_warning ("[%d] __out_fd %d, __in_fd %d, __offset %p, __len %lu", - getpid (), __out_fd, __in_fd, __offset, __len); - - p = hash_get (vsm->sockidx_by_fd, __out_fd); - if (!p) - { - clib_warning ("[%d] ERROR: invalid __out_fd (%d), fd lookup failed!", - getpid (), __len); - return -EBADF; - } - out_sockidx = p[0]; - vsock = pool_elt_at_index (vsm->vsockets, out_sockidx); - if (!vsock) - { - clib_warning ("[%d] ERROR: invalid __out_fd (%d) / out_sockidx %u, " - "missing vsock pool element!", - getpid (), __len, out_sockidx); - return -ENOTSOCK; - } - out_sid = vsock->sid; - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - { - clib_warning ("[%d] ERROR: __out_fd (%d), socket (sid %u) " - "is not VCL bound!", getpid (), __out_fd, out_sid); - return -EINVAL; - } - - if (__offset) - { - off_t offset = lseek (__in_fd, *__offset, SEEK_SET); - if (offset == -1) - { - errno_val = errno; - perror ("lseek()"); - clib_warning ("[%d] ERROR: lseek SEEK_SET failed: " - "in_fd %d, offset %p (%ld), rv %ld, errno %d", - getpid (), __in_fd, __offset, *__offset, offset, - errno_val); - return -errno_val; - } - - ASSERT (offset == *__offset); - } - - do - { - rv = vppcom_session_attr (out_sid, VPPCOM_ATTR_GET_NWRITE, 0, 0); - if (rv < 0) - { - clib_warning ("[%d] ERROR: vppcom_session_attr (out_sid (%u), " - "VPPCOM_ATTR_GET_NWRITE, 0, 0) returned %d (%s)!", - getpid (), out_sid, rv, vppcom_retval_str (rv)); - vec_reset_length (vsm->io_buffer); - return rv; - } - - bytes_to_read = (size_t) rv; - if (VCOM_DEBUG > 2) - clib_warning ("[%d] results %ld, n_bytes_left %lu, " - "bytes_to_read %lu", getpid (), results, - n_bytes_left, bytes_to_read); - if (bytes_to_read == 0) - { - u32 flags, flags_len = sizeof (flags); - rv = vppcom_session_attr (out_sid, VPPCOM_ATTR_GET_FLAGS, &flags, - &flags_len); - ASSERT (rv == VPPCOM_OK); - - if (flags & O_NONBLOCK) - { - if (!results) - { - if (VCOM_DEBUG > 2) - clib_warning ("[%d] EAGAIN", getpid ()); - eagain = 1; - } - goto update_offset; - } - else - continue; - } - bytes_to_read = clib_min (n_bytes_left, bytes_to_read); - vec_validate (vsm->io_buffer, bytes_to_read); - nbytes = libc_read (__in_fd, vsm->io_buffer, bytes_to_read); - if (nbytes < 0) - { - errno_val = errno; - perror ("read()"); - clib_warning ("[%d] ERROR: libc_read (__in_fd (%d), " - "io_buffer %p, bytes_to_read %lu) returned " - "errno %d", - getpid (), __in_fd, vsm->io_buffer, - bytes_to_read, errno_val); - if (results == 0) - { - vec_reset_length (vsm->io_buffer); - return -errno_val; - } - goto update_offset; - } - rv = vppcom_session_write (out_sid, vsm->io_buffer, nbytes); - if (rv < 0) - { - clib_warning ("[%d] ERROR: vppcom_session_write (" - "out_sid %u, io_buffer %p, nbytes %d) " - "returned %d (%s)", - getpid (), out_sid, vsm->io_buffer, nbytes, - rv, vppcom_retval_str (rv)); - if (results == 0) - { - vec_reset_length (vsm->io_buffer); - return rv; - } - goto update_offset; - } - - results += nbytes; - ASSERT (n_bytes_left >= nbytes); - n_bytes_left = n_bytes_left - nbytes; - } - while (n_bytes_left > 0); - -update_offset: - if (__offset) - { - off_t offset = lseek (__in_fd, *__offset, SEEK_SET); - if (offset == -1) - { - errno_val = errno; - perror ("lseek()"); - clib_warning ("[%d] ERROR: lseek (__in_fd %d, __offset %p " - "(%ld), SEEK_SET) returned errno %d", - getpid (), __in_fd, __offset, *__offset, errno_val); - vec_reset_length (vsm->io_buffer); - return -errno_val; - } - - *__offset += results + 1; - } - - vec_reset_length (vsm->io_buffer); - return eagain ? -EAGAIN : results; -} - -ssize_t -vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags) -{ - int rv = -1; - rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0); - return rv; -} - -/* - * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET), - * 0 otherwise - * */ -int -vcom_socket_is_connection_mode_socket (int __fd) -{ - int rv = -1; - /* TBD define new vppcom api */ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - int type; - socklen_t optlen; - - p = hash_get (vsm->sockidx_by_fd, __fd); - - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND) - { - optlen = sizeof (type); - rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen); - if (rv != 0) - { - return 0; - } - /* get socket type */ - switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) - { - case SOCK_STREAM: - case SOCK_SEQPACKET: - return 1; - break; - - default: - return 0; - break; - } - } - } - return 0; -} - -static inline ssize_t -vcom_session_sendto (int __sid, void *__buf, size_t __n, - int __flags, __CONST_SOCKADDR_ARG __addr, - socklen_t __addr_len) -{ - vppcom_endpt_t *ep = 0; - vppcom_endpt_t _ep; - - if (__addr) - { - ep = &_ep; - ep->vrf = VPPCOM_VRF_DEFAULT; - switch (__addr->sa_family) - { - case AF_INET: - ep->is_ip4 = VPPCOM_IS_IP4; - ep->ip = - (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr; - ep->port = - (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port; - break; - - case AF_INET6: - ep->is_ip4 = VPPCOM_IS_IP6; - ep->ip = - (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr; - ep->port = - (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port; - break; - - default: - return -EAFNOSUPPORT; - } - } - - return vppcom_session_sendto (__sid, __buf, __n, __flags, ep);; -} - -ssize_t -vcom_socket_sendto (int __fd, const void *__buf, size_t __n, - int __flags, __CONST_SOCKADDR_ARG __addr, - socklen_t __addr_len) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - if (!__buf) - { - return -EINVAL; - } - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - { - return -EINVAL; - } - - if (vcom_socket_is_connection_mode_socket (__fd)) - { - /* ignore __addr and _addr_len */ - /* and EISCONN may be returned when they are not NULL and 0 */ - if ((__addr != NULL) || (__addr_len != 0)) - { - return -EISCONN; - } - } - else - { - if (!__addr) - { - return -EDESTADDRREQ; - } - /* not a vppcom supported address family */ - if (!((__addr->sa_family == AF_INET) || - (__addr->sa_family == AF_INET6))) - { - return -EINVAL; - } - } - - return vcom_session_sendto (vsock->sid, (void *) __buf, (int) __n, - __flags, __addr, __addr_len); -} - -static inline ssize_t -vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n, - int __flags, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len) -{ - int rv; - vppcom_endpt_t ep; - u8 src_addr[sizeof (struct sockaddr_in6)]; - - if (__addr) - { - ep.ip = src_addr; - rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, &ep); - - if (rv > 0) - rv = vcom_socket_copy_ep_to_sockaddr (__addr, __addr_len, &ep); - } - else - rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, NULL); - - return rv; -} - -ssize_t -vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - if (__addr && !__addr_len) - return -EINVAL; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - { - return -EINVAL; - } - - rv = vcom_session_recvfrom (vsock->sid, __buf, __n, - __flags, __addr, __addr_len); - return rv; -} - -/* TBD: move it to vppcom */ -static inline ssize_t -vcom_session_sendmsg (int __sid, const struct msghdr *__message, int __flags) -{ - int rv = -1; - /* rv = vppcom_session_write (__sid, (void *) __message->__buf, - (int)__n); */ - return rv; -} - -ssize_t -vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vcom_socket_is_connection_mode_socket (__fd)) - { - /* ignore __addr and _addr_len */ - /* and EISCONN may be returned when they are not NULL and 0 */ - if ((__message->msg_name != NULL) || (__message->msg_namelen != 0)) - { - return -EISCONN; - } - } - else - { - /* TBD: validate __message->msg_name and __message->msg_namelen - * and return -EINVAL on validation error - * */ - ; - } - - rv = vcom_session_sendmsg (vsock->sid, __message, __flags); - - return rv; -} - -#ifdef __USE_GNU -int -vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags) -{ - - /* TBD: define a new vppcom api */ - return 0; -} -#endif - -/* TBD: move it to vppcom */ -static inline ssize_t -vcom_session_recvmsg (int __sid, struct msghdr *__message, int __flags) -{ - int rv = -1; - /* rv = vppcom_session_read (__sid, (void *) __message->__buf, - (int)__n); */ - rv = -EOPNOTSUPP; - return rv; -} - -ssize_t -vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - if (!__message) - { - return -EINVAL; - } - - /* validate __flags */ - - rv = vcom_session_recvmsg (vsock->sid, __message, __flags); - return rv; -} - -#ifdef __USE_GNU -int -vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, - struct timespec *__tmo) -{ - /* TBD: define a new vppcom api */ - return 0; -} -#endif - -/* TBD: move it to vppcom */ -static inline int -vcom_session_get_sockopt (int __sid, int __level, int __optname, - void *__restrict __optval, - socklen_t * __restrict __optlen) -{ - int rv = 0; - - /* 1. for socket level options that are NOT socket attributes - * and that has corresponding vpp options get from vppcom */ - switch (__level) - { - case SOL_SOCKET: - switch (__optname) - { - case SO_ERROR: - *(int *) __optval = 0; - break; - default: - break; - } - default: - break; - } - /* 2. unhandled options */ - return rv; -} - -int -vcom_socket_getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, - socklen_t * __restrict __optlen) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - if (!__optval || !__optlen) - return -EINVAL; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - switch (__level) - { - case SOL_SOCKET: - switch (__optname) - { -/* - * 1. for socket level options that are socket attributes, - * get from libc_getsockopt. - * 2. for socket level options that are NOT socket - * attributes and that has corresponding vpp options - * get from vppcom. - * 3. for socket level options unimplemented - * return -ENOPROTOOPT */ - case SO_DEBUG: - case SO_DONTROUTE: - case SO_BROADCAST: - case SO_SNDBUF: - case SO_RCVBUF: - case SO_REUSEADDR: - case SO_REUSEPORT: - case SO_KEEPALIVE: - case SO_TYPE: - case SO_PROTOCOL: - case SO_DOMAIN: - case SO_OOBINLINE: - case SO_NO_CHECK: - case SO_PRIORITY: - case SO_LINGER: - case SO_BSDCOMPAT: - case SO_TIMESTAMP: - case SO_TIMESTAMPNS: - case SO_TIMESTAMPING: - case SO_RCVTIMEO: - case SO_SNDTIMEO: - case SO_RCVLOWAT: - case SO_SNDLOWAT: - case SO_PASSCRED: - case SO_PEERCRED: - case SO_PEERNAME: - case SO_ACCEPTCONN: - case SO_PASSSEC: - case SO_PEERSEC: - case SO_MARK: - case SO_RXQ_OVFL: - case SO_WIFI_STATUS: - case SO_PEEK_OFF: - case SO_NOFCS: - case SO_BINDTODEVICE: - case SO_GET_FILTER: - case SO_LOCK_FILTER: - case SO_BPF_EXTENSIONS: - case SO_SELECT_ERR_QUEUE: -#ifdef CONFIG_NET_RX_BUSY_POLL - case SO_BUSY_POLL: -#endif - case SO_MAX_PACING_RATE: -#ifdef SO_INCOMING_CPU - case SO_INCOMING_CPU: -#endif - rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen); - if (rv != 0) - { - rv = -errno; - return rv; - } - break; - - case SO_ERROR: - rv = vcom_session_get_sockopt (vsock->sid, __level, __optname, - __optval, __optlen); - break; - - default: - /* We implement the SO_SNDLOWAT etc to not be settable - * (1003.1g 7). - */ - return -ENOPROTOOPT; - } - - break; - - default: - /* 1. handle options that are NOT socket level options, - * but have corresponding vpp otions. */ - rv = vcom_session_get_sockopt (vsock->sid, __level, __optname, - __optval, __optlen); - break; - } - - return rv; -} - -/* TBD: move it to vppcom */ -static inline int -vcom_session_setsockopt (int __sid, int __level, int __optname, - const void *__optval, socklen_t __optlen) -{ - int rv = -EOPNOTSUPP; - - switch (__level) - { - case SOL_TCP: - switch (__optname) - { - case TCP_KEEPIDLE: - rv = - vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, 0, 0); - break; - case TCP_KEEPINTVL: - rv = - vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, 0, 0); - break; - default: - break; - } - break; - case SOL_IPV6: - switch (__optname) - { - case IPV6_V6ONLY: - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0); - break; - default: - break; - } - break; - case SOL_SOCKET: - switch (__optname) - { - case SO_KEEPALIVE: - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_KEEPALIVE, 0, 0); - break; - case SO_REUSEADDR: - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0); - break; - case SO_BROADCAST: - rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0); - break; - default: - break; - } - break; - default: - break; - } - - return rv; -} - -int -vcom_socket_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (!p) - return -EBADF; - - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - if (!vsock) - return -ENOTSOCK; - - if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND) - return -EINVAL; - - /* - * Options without arguments - */ - - if (__optname == SO_BINDTODEVICE) - { - rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen); - if (rv != 0) - { - rv = -errno; - } - return rv; - } - - if (!__optval) - return -EFAULT; - - if (__optlen < sizeof (int)) - return -EINVAL; - - switch (__level) - { - case SOL_IPV6: - switch (__optname) - { - case IPV6_V6ONLY: - rv = vcom_session_setsockopt (vsock->sid, __level, __optname, - __optval, __optlen); - break; - default: - return -EOPNOTSUPP; - } - break; - case SOL_TCP: - switch (__optname) - { - case TCP_NODELAY: - return 0; - case TCP_KEEPIDLE: - case TCP_KEEPINTVL: - rv = vcom_session_setsockopt (vsock->sid, __level, __optname, - __optval, __optlen); - break; - default: - return -EOPNOTSUPP; - } - break; - /* handle options at socket level */ - case SOL_SOCKET: - switch (__optname) - { - case SO_REUSEADDR: - case SO_BROADCAST: - case SO_KEEPALIVE: - rv = vcom_session_setsockopt (vsock->sid, __level, __optname, - __optval, __optlen); - break; - - /* - * 1. for socket level options that are socket attributes, - * set it from libc_getsockopt - * 2. for socket level options that are NOT socket - * attributes and that has corresponding vpp options - * set it from vppcom - * 3. for socket level options unimplemented - * return -ENOPROTOOPT */ - case SO_DEBUG: - case SO_DONTROUTE: - case SO_SNDBUF: - case SO_RCVBUF: - case SO_REUSEPORT: - case SO_TYPE: - case SO_PROTOCOL: - case SO_DOMAIN: - case SO_ERROR: - case SO_OOBINLINE: - case SO_NO_CHECK: - case SO_PRIORITY: - case SO_LINGER: - case SO_BSDCOMPAT: - case SO_TIMESTAMP: - case SO_TIMESTAMPNS: - case SO_TIMESTAMPING: - case SO_RCVTIMEO: - case SO_SNDTIMEO: - case SO_RCVLOWAT: - case SO_SNDLOWAT: - case SO_PASSCRED: - case SO_PEERCRED: - case SO_PEERNAME: - case SO_ACCEPTCONN: - case SO_PASSSEC: - case SO_PEERSEC: - case SO_MARK: - case SO_RXQ_OVFL: - case SO_WIFI_STATUS: - case SO_PEEK_OFF: - case SO_NOFCS: - /* - * SO_BINDTODEVICE already handled as - * "Options without arguments" */ - /* case SO_BINDTODEVICE: */ - case SO_GET_FILTER: - case SO_LOCK_FILTER: - case SO_BPF_EXTENSIONS: - case SO_SELECT_ERR_QUEUE: -#ifdef CONFIG_NET_RX_BUSY_POLL - case SO_BUSY_POLL: -#endif - case SO_MAX_PACING_RATE: -#ifdef SO_INCOMING_CPU - case SO_INCOMING_CPU: -#endif - rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen); - if (rv != 0) - { - rv = -errno; - return rv; - } - break; - - default: - /* We implement the SO_SNDLOWAT etc to not be settable - * (1003.1g 7). - */ - return -ENOPROTOOPT; - } - - break; - - default: - return -ENOPROTOOPT; - } - - return rv; -} - -int -vcom_socket_listen (int __fd, int __n) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - - /* TBD vppcom to accept __n parameter */ - rv = vppcom_session_listen (vsock->sid, __n); - } - - return rv; -} - -static int -vcom_socket_connected_socket (int __fd, int __sid, - int *__domain, - int *__type, int *__protocol, int flags) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_socket_t *vsock; - - i32 fd; - i32 sockidx; - - socklen_t optlen; - - optlen = sizeof (*__domain); - rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen); - if (rv != 0) - { - rv = -errno; - goto out; - } - - optlen = sizeof (*__type); - rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen); - if (rv != 0) - { - rv = -errno; - goto out; - } - - optlen = sizeof (*__protocol); - rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen); - if (rv != 0) - { - rv = -errno; - goto out; - } - - fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol); - if (fd < 0) - { - rv = fd; - goto out; - } - - pool_get (vsm->vsockets, vsock); - vsocket_init (vsock); - - sockidx = vsock - vsm->vsockets; - hash_set (vsm->sockidx_by_fd, fd, sockidx); - - vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND); - return fd; - -out: - return rv; -} - -/* If flag is 0, then accept4() is the same as accept(). - * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags - */ -static int -vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int flags) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - int fd; - int sid; - int domain; - int type; - int protocol; - - uint8_t addr8[sizeof (struct in6_addr)]; - vppcom_endpt_t ep; - - ep.ip = addr8; - - /* validate flags */ - - /* - * for documentation - * switch (flags) - * { - * case 0: - * case SOCK_NONBLOCK: - * case SOCK_CLOEXEC: - * case SOCK_NONBLOCK | SOCK_CLOEXEC: - * break; - * - * default: - * return -1; - * } - */ - /* flags can be 0 or can be bitwise OR - * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */ - - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_accept_flags: " - "fd = %d, __addr = %p, __addr_len = %p flags = %d (0x%x)\n", - getpid (), __fd, __addr, __addr_len, flags, flags); - - if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC)))) - { - /* TBD: return proper error code */ - fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " - "invalid flags = %d (0x%x)\n", getpid (), flags, flags); - - return -1; - } - - /* TBD: return proper error code */ - - if (!vcom_socket_is_connection_mode_socket (__fd)) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " - "connection mode socket support TBD!\n", getpid ()); - return -EOPNOTSUPP; - } - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - - - rv = vcom_fcntl (vsock->fd, F_GETFL, 0); - if (rv < 0) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " - "vcom_fcnt() returned %d!\n", getpid (), rv); - return rv; - } - - /* is blocking */ - if (!(rv & O_NONBLOCK)) - { - /* socket is not marked as nonblocking - * and no pending connections are present - * on the queue, accept () blocks the caller - * until a connection is present. - */ - rv = vppcom_session_accept (vsock->sid, &ep, flags, - -1.0 /* wait forever */ ); - } - else - { - /* The file descriptor refers to a socket and has been - * marked nonblocking(O_NONBLOCK) and the accept would - * block. - * */ - /* is non blocking */ - rv = vppcom_session_accept (vsock->sid, &ep, flags, 0); - /* If the socket is marked nonblocking and - * no pending connections are present on the - * queue, accept fails with the error - * EAGAIN or EWOULDBLOCK - */ - if (rv == VPPCOM_ETIMEDOUT) - { - rv = VPPCOM_EAGAIN; - } - } - if (rv < 0) - { - if (rv != VPPCOM_EAGAIN) - fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " - "vppcom_session_accept() returned %d!", getpid (), rv); - return rv; - } - - sid = rv; - - /* create a new connected socket resource and set flags - * on the new file descriptor. - * update vsockets and sockidx_by_fd table - * */ - fd = vcom_socket_connected_socket (__fd, sid, - &domain, &type, &protocol, flags); - if (fd < 0) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: " - "vcom_socket_connected_socket() returned %d!", - getpid (), rv); - return fd; - } - - rv = fd; - - /* TBD populate __addr and __addr_len */ - /* TBD: The returned address is truncated if the buffer - * provided is too small, in this case, __addr_len will - * return a value greater than was supplied to the call.*/ - if (__addr) - { - if (ep.is_cut_thru) - { - /* TBD populate __addr and __addr_len */ - switch (domain) - { - case AF_INET: - ((struct sockaddr_in *) __addr)->sin_family = AF_INET; - ((struct sockaddr_in *) __addr)->sin_port = ep.port; - memcpy (&((struct sockaddr_in *) __addr)->sin_addr, - addr8, sizeof (struct in_addr)); - /* TBD: populate __addr_len */ - if (__addr_len) - { - *__addr_len = sizeof (struct sockaddr_in); - } - break; - - case AF_INET6: - ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port; - memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr. - __in6_u.__u6_addr8, addr8, - sizeof (struct in6_addr)); - /* TBD: populate __addr_len */ - if (__addr_len) - { - *__addr_len = sizeof (struct sockaddr_in6); - } - break; - - default: - return -EAFNOSUPPORT; - } - } - else - { - switch (ep.is_ip4) - { - case VPPCOM_IS_IP4: - ((struct sockaddr_in *) __addr)->sin_family = AF_INET; - ((struct sockaddr_in *) __addr)->sin_port = ep.port; - memcpy (&((struct sockaddr_in *) __addr)->sin_addr, - addr8, sizeof (struct in_addr)); - /* TBD: populate __addr_len */ - if (__addr_len) - { - *__addr_len = sizeof (struct sockaddr_in); - } - break; - - case VPPCOM_IS_IP6: - ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port; - memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr. - __in6_u.__u6_addr8, addr8, - sizeof (struct in6_addr)); - /* TBD: populate __addr_len */ - if (__addr_len) - { - *__addr_len = sizeof (struct sockaddr_in6); - } - break; - - default: - return -EAFNOSUPPORT; - } - } - } - } - - return rv; -} - -int -vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len) -{ - /* set flags to 0 for accept() */ - return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0); -} - -int -vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags) -{ - /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */ - return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags); -} - -/* TBD: move it to vppcom */ -static inline int -vcom_session_shutdown (int __fd, int __how) -{ - return 0; -} - -int -vcom_socket_shutdown (int __fd, int __how) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - uword *p; - vcom_socket_t *vsock; - - p = hash_get (vsm->sockidx_by_fd, __fd); - if (p) - { - vsock = pool_elt_at_index (vsm->vsockets, p[0]); - switch (__how) - { - case SHUT_RD: - case SHUT_WR: - case SHUT_RDWR: - rv = vcom_session_shutdown (vsock->sid, __how); - return rv; - break; - - default: - return -EINVAL; - break; - } - } - - return rv; -} - -int -vcom_socket_epoll_create1 (int __flags) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_epoll_t *vepoll; - - i32 epfd; - i32 vep_idx; - i32 epollidx; - - epfd = vcom_socket_open_epoll (__flags); - if (epfd < 0) - { - rv = epfd; - goto out; - } - - vep_idx = vppcom_epoll_create (); - if (vep_idx < 0) - { - rv = vep_idx; - goto out_close_epoll; - } - - pool_get (vsm->vepolls, vepoll); - vepoll_init (vepoll); - - epollidx = vepoll - vsm->vepolls; - hash_set (vsm->epollidx_by_epfd, epfd, epollidx); - - vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0); - - return epfd; - -out_close_epoll: - vcom_socket_close_epoll (epfd); -out: - return rv; -} - -/* - * PRE: vppcom_epoll_ctl() is successful - * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put - */ -int -vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd, - struct epoll_event *__event, - i32 vep_idx, vcom_epoll_t * vepoll, - i32 vfd_id, void *vfd, vcom_fd_type_t type, - int free_vepitem_on_del) -{ - int rv = -1; - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_epitem_t *vepitem; - - vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd }; - uword *p; - i32 vepitemidx; - - i32 *vepitemidxs = 0; - - struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD }; - - i32 vec_idx; - - /* perform control operations on the epoll instance */ - switch (__op) - { - case EPOLL_CTL_ADD: - /* - * supplied file descriptor is already - * registered with this epoll instance - * */ - /* vepitem exists */ - p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key); - if (p) - { - rv = -EEXIST; - goto out; - } - - /* add a new vepitem */ - pool_get (vsm->vepitems, vepitem); - vepitem_init (vepitem); - - vepitemidx = vepitem - vsm->vepitems; - hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx); - vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent); - - /* update epitemidxs */ - /* by_epfd */ - p = hash_get (vsm->epitemidxs_by_epfd, __epfd); - if (!p) /* not exist */ - { - vepitemidxs = 0; - vec_add1 (vepitemidxs, vepitemidx); - hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs); - } - else /* exists */ - { - vepitemidxs = *(i32 **) p; - vec_add1 (vepitemidxs, vepitemidx); - hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0); - } - /* update epitemidxs */ - /* by_fd */ - p = hash_get (vsm->epitemidxs_by_fd, __fd); - if (!p) /* not exist */ - { - vepitemidxs = 0; - vec_add1 (vepitemidxs, vepitemidx); - hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs); - } - else /* exists */ - { - vepitemidxs = *(i32 **) p; - vec_add1 (vepitemidxs, vepitemidx); - hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0); - } - - /* increment vepoll fd count by 1 */ - vepoll->count += 1; - - rv = 0; - goto out; - break; - - case EPOLL_CTL_MOD: - /* - * supplied file descriptor is not - * registered with this epoll instance - * */ - /* vepitem not exist */ - p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key); - if (!p) - { - rv = -ENOENT; - goto out; - } - vepitem = pool_elt_at_index (vsm->vepitems, p[0]); - if (vepitem) - { - vepitem->event = *__event; - vepitem->revent = revent; - } - - rv = 0; - goto out; - break; - - case EPOLL_CTL_DEL: - /* - * supplied file descriptor is not - * registered with this epoll instance - * */ - /* vepitem not exist */ - p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key); - if (!p) - { - rv = -ENOENT; - goto out; - } - vepitemidx = *(i32 *) p; - hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key); - - /* update epitemidxs */ - /* by_epfd */ - p = hash_get (vsm->epitemidxs_by_epfd, __epfd); - if (!p) /* not exist */ - { - rv = -ENOENT; - goto out; - } - else /* exists */ - { - vepitemidxs = *(i32 **) p; - vec_idx = vec_search (vepitemidxs, vepitemidx); - if (vec_idx != ~0) - { - vec_del1 (vepitemidxs, vec_idx); - if (!vec_len (vepitemidxs)) - { - vec_free (vepitemidxs); - hash_unset (vsm->epitemidxs_by_epfd, __epfd); - } - } - } - - /* update epitemidxs */ - /* by_fd */ - p = hash_get (vsm->epitemidxs_by_fd, __fd); - if (!p) /* not exist */ - { - rv = -ENOENT; - goto out; - } - else /* exists */ - { - vepitemidxs = *(i32 **) p; - vec_idx = vec_search (vepitemidxs, vepitemidx); - if (vec_idx != ~0) - { - vec_del1 (vepitemidxs, vec_idx); - if (!vec_len (vepitemidxs)) - { - vec_free (vepitemidxs); - hash_unset (vsm->epitemidxs_by_fd, __fd); - } - } - } - - /* pool put vepitem */ - vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx); - if (free_vepitem_on_del) - { - if (!vepitem) - { - rv = -ENOENT; - goto out; - } - vepitem_init (vepitem); - pool_put (vsm->vepitems, vepitem); - } - else - { - if (!vepitem) - { - vepitem_init (vepitem); - } - } - - /* decrement vepoll fd count by 1 */ - vepoll->count -= 1; - - rv = 0; - goto out; - break; - - default: - rv = -EINVAL; - goto out; - break; - } - -out: - return rv; -} - -/* - * PRE: 00. null pointer check on __event - * 01. all other parameters are validated - */ - -static int -vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd, - struct epoll_event *__event, - int free_vepitem_on_del) -{ - int rv = -1; - i32 cnt; - vcom_epoll_t *vepoll; - vcom_socket_t *vfd_vsock; - i32 vep_idx; - i32 sid; - - /* get vep_idx and vepoll */ - vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll); - if (vep_idx == INVALID_VEP_IDX) - { - return -EBADF; - } - - /* get vcom fd type, vfd_id and vfd */ - sid = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock); - if ((sid != INVALID_SESSION_ID) && - vcom_socket_type_is_vppcom_bound (vfd_vsock->type)) - { - rv = vppcom_epoll_ctl (vep_idx, __op, sid, __event); - if (rv == VPPCOM_OK) - { - cnt = ((__op == EPOLL_CTL_ADD) ? 1 : - (__op == EPOLL_CTL_DEL) ? -1 : 0); - vepoll->count += cnt; - vepoll->vcl_cnt += cnt; - } - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_socket_epoll_ctl_i: vppcom_epoll_ctl() " - "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d" - "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", - getpid (), rv, __epfd, vep_idx, __fd, sid, __op, - vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); - } - else - { - rv = libc_epoll_ctl (__epfd, __op, __fd, __event); - if (rv == 0) - { - cnt = ((__op == EPOLL_CTL_ADD) ? 1 : - (__op == EPOLL_CTL_DEL) ? -1 : 0); - vepoll->count += cnt; - vepoll->libc_cnt += cnt; - } - if (VCOM_DEBUG > 0) - fprintf (stderr, - "[%d] vcom_socket_epoll_ctl_i: libc_epoll_ctl() " - "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d" - "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", - getpid (), rv, __epfd, vep_idx, __fd, sid, __op, - vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); - } - - return rv; -} - -int -vcom_socket_epoll_ctl (int __epfd, int __op, int __fd, - struct epoll_event *__event) -{ - int rv = -1; - - rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1); - return rv; -} - -static int -vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd, - struct epoll_event *__event) -{ - int rv = -1; - - rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0); - return rv; -} - -int -vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, - const __sigset_t * __ss) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - int rv = -EBADF; - double time_to_wait = (double) 0; - double timeout, now = 0; - vcom_epoll_t *vepoll; - i32 vep_idx; - - /* validate __event */ - if (!__events || (__timeout < -1)) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: " - "Bad args __events %p, __timeout %d\n", getpid (), - __events, __timeout); - rv = -EFAULT; - goto out; - } - - time_to_wait = ((__timeout >= 0) ? (double) __timeout / (double) 1000 : 0); - - vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll); - if (vep_idx == INVALID_VEP_IDX) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: " - "Bad epoll fd %d\n", getpid (), __epfd); - return -EBADF; - } - - if (vepoll->count <= 0) - { - fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: No events" - " in epfd!\n\tcount %d, vcl_cnt %d, libc_cnt %d\n", - getpid (), vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt); - rv = -EINVAL; - goto out; - } - - if (vepoll->libc_cnt == 0) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: libc_cnt = 0, " - "calling vppcom_epoll_wait() time_to_wait = %f\n", - getpid (), time_to_wait); - rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait); - } - else if (vepoll->vcl_cnt == 0) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = 0, " - "calling libc_epoll_pwait()\n", getpid ()); - rv = libc_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss); - } - else - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = %d, " - "libc_cnt = %d -> mixed polling (time_to_wait = %f, " - "__timeout = %d)\n", - getpid (), vepoll->vcl_cnt, vepoll->libc_cnt, - time_to_wait, __timeout); - timeout = clib_time_now (&vsm->clib_time) + time_to_wait; - do - { - rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, 0); - if (rv > 0) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: " - "vppcom_epoll_wait() returned %d\n", getpid (), rv); - goto out; - } - else if (rv < 0) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: " - "vppcom_epoll_wait() returned %d\n", getpid (), rv); - - goto out; - } - rv = libc_epoll_pwait (__epfd, __events, __maxevents, 1, __ss); - if (rv > 0) - { - if (VCOM_DEBUG > 2) - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: " - "libc_epoll_pwait() returned %d\n", getpid (), rv); - goto out; - } - else if (rv < 0) - { - int errno_val = errno; - perror ("libc_epoll_wait"); - fprintf (stderr, "[%d] vcom_socket_epoll_pwait: " - "libc_epoll_wait() failed, errno %d\n", - getpid (), errno_val); - goto out; - } - if (__timeout != -1) - now = clib_time_now (&vsm->clib_time); - } - while (now < timeout); - } -out: - return rv; -} - -static inline void -vcom_pollfds_2_selectfds ( - /* src */ - struct pollfd *__fds, nfds_t __nfds, - /* dest */ - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds) -{ - nfds_t fds_idx = 0; - - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */ - FD_SET (__fds[fds_idx].fd, vcom_exceptfds); - - /* requested events */ - if (__fds[fds_idx].events) - { - if (__fds[fds_idx].events & POLLIN) - { - FD_SET (__fds[fds_idx].fd, vcom_readfds); - } - if (__fds[fds_idx].events & POLLPRI) - { - FD_SET (__fds[fds_idx].fd, vcom_readfds); - } - if (__fds[fds_idx].events & POLLOUT) - { - FD_SET (__fds[fds_idx].fd, vcom_writefds); - } -#if defined __USE_XOPEN || defined __USE_XOPEN2K8 - if (__fds[fds_idx].events & POLLRDNORM) - { - FD_SET (__fds[fds_idx].fd, vcom_readfds); - } - if (__fds[fds_idx].events & POLLRDBAND) - { - FD_SET (__fds[fds_idx].fd, vcom_readfds); - } - if (__fds[fds_idx].events & POLLWRNORM) - { - FD_SET (__fds[fds_idx].fd, vcom_writefds); - } - if (__fds[fds_idx].events & POLLWRBAND) - { - FD_SET (__fds[fds_idx].fd, vcom_writefds); - } -#endif - } - } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */ -} - -static inline void -vcom_selectfds_2_pollfds ( - /* dest */ - struct pollfd *__fds, nfds_t __nfds, int *nfd, - /* src */ - int vcom_nfds, - fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds) -{ - nfds_t fds_idx = 0; - - - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - __fds[fds_idx].revents = 0; - } - - /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */ - if (FD_ISSET (__fds[fds_idx].fd, vcom_exceptfds)) - { - /* - * TBD: for now any select exception - * is flagged as POLLERR - * */ - __fds[fds_idx].revents |= POLLERR; - } - - /* requested events */ - if (__fds[fds_idx].events & POLLIN) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) - { - __fds[fds_idx].revents |= POLLIN; - } - } - if (__fds[fds_idx].events & POLLPRI) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) - { - __fds[fds_idx].revents |= POLLIN; - } - } - if (__fds[fds_idx].events & POLLOUT) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) - { - __fds[fds_idx].revents |= POLLOUT; - } - } -#if defined __USE_XOPEN || defined __USE_XOPEN2K8 - if (__fds[fds_idx].events & POLLRDNORM) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) - { - __fds[fds_idx].revents |= POLLRDNORM; - } - } - if (__fds[fds_idx].events & POLLRDBAND) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds)) - { - __fds[fds_idx].revents |= POLLRDBAND; - } - } - if (__fds[fds_idx].events & POLLWRNORM) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) - { - __fds[fds_idx].revents |= POLLWRNORM; - } - } - if (__fds[fds_idx].events & POLLWRBAND) - { - if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds)) - { - __fds[fds_idx].revents |= POLLWRBAND; - } - } -#endif - } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */ - - /* - * nfd: - * the number of structures which have nonzero revents fields - * (in other words, those descriptors with events or - * errors reported) - * */ - *nfd = 0; - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - if (__fds[fds_idx].revents) - { - (*nfd)++; - } - } -} - -/* - * PRE: parameters are validated, - * vcom_socket_poll is always called with __timeout set to zero - * hence returns immediately - * - * ACTION: handle non negative validated vcom fds and ignore rest - */ - -/* - * implements vcom_socket_poll () interface - * - * internally uses vcom_socket_select () - * to realize the behavior - * */ -int -vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds, - int __timeout) -{ - int rv; - - nfds_t fds_idx = 0; - int nfd = 0; - - /* vcom */ - int vcom_nfds = 0; - fd_set vcom_readfds; - fd_set vcom_writefds; - fd_set vcom_exceptfds; - int vcom_nfd = -1; - /* invalid max_vcom_fd is -1 */ - int max_vcom_fd = -1; - - /* __timeout is zero to get ready events and return immediately */ - struct timeval tv = {.tv_sec = 0,.tv_usec = 0 }; - - /* validate __nfds from select perspective */ - if (__nfds > FD_SETSIZE) - { - rv = -EINVAL; - goto poll_done; - } - - /* zero vcom fd sets */ - /* - * V vcom fd set - */ -#define _(V) \ - FD_ZERO ((V)) - - _(&vcom_readfds); - _(&vcom_writefds); - _(&vcom_exceptfds); -#undef _ - - vcom_nfds = 0; - vcom_nfd = -1; - - - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - /* non negative validated vcom fds */ - if (__fds[fds_idx].fd > FD_SETSIZE) - { - rv = -EINVAL; - goto poll_done; - } - - /* max_vcom_fd and vcom_nfd */ - if (__fds[fds_idx].fd > max_vcom_fd) - { - /* requested events */ - if (__fds[fds_idx].events) - { - max_vcom_fd = __fds[fds_idx].fd; - } - } - ++vcom_nfd; - } - - vcom_nfds = max_vcom_fd != -1 ? max_vcom_fd + 1 : 0; - - if (!vcom_nfds) - { - rv = vcom_nfds; - goto poll_done; - } - - vcom_pollfds_2_selectfds ( - /* src */ - __fds, __nfds, - /* dest */ - vcom_nfds, - &vcom_readfds, &vcom_writefds, &vcom_exceptfds); - - /* select on vcom fds */ - vcom_nfd = vcom_socket_select (vcom_nfds, - &vcom_readfds, - &vcom_writefds, &vcom_exceptfds, &tv); - if (VCOM_DEBUG > 2) - fprintf (stderr, - "[%d] vcom_socket_select: " - "'%04d'='%04d'\n", getpid (), vcom_nfd, vcom_nfds); - - if (vcom_nfd < 0) - { - rv = vcom_nfd; - goto poll_done; - } - - vcom_selectfds_2_pollfds ( - /* dest */ - __fds, __nfds, &nfd, - /* src */ - vcom_nfds, - &vcom_readfds, &vcom_writefds, &vcom_exceptfds); - - rv = nfd; - -poll_done: - return rv; -} - -/* - * TBD: remove this static function once vppcom - * has an implementation in place - * - * ACTION: - */ -static int -vppcom_poll (struct pollfd *__fds, nfds_t __nfds, double time_to_wait) -{ - return -EOPNOTSUPP; -} - -int -vcom_socket_poll_vppcom_impl (struct pollfd *__fds, nfds_t __nfds, - int __timeout) -{ - nfds_t fds_idx = 0; - - /* in seconds eg. 3.123456789 seconds */ - double time_to_wait = (double) 0; - - i32 sid; - i32 vep_idx; - - /* replace vcom fd with session idx */ - for (fds_idx = 0; fds_idx < __nfds; fds_idx++) - { - /* ignore negative fds */ - if (__fds[fds_idx].fd < 0) - { - continue; - } - - /* non negative validated vcom fds */ - sid = vcom_socket_get_sid (__fds[fds_idx].fd); - if (sid != INVALID_SESSION_ID) - { - __fds[fds_idx].fd = sid; - } - else - { - /* get vep_idx */ - vep_idx = vcom_socket_get_vep_idx (__fds[fds_idx].fd); - if (vep_idx != INVALID_VEP_IDX) - { - __fds[fds_idx].fd = vep_idx; - } - else - { - return -EBADF; - } - } - } - - /* validate __timeout */ - if (__timeout > 0) - { - time_to_wait = (double) __timeout / (double) 1000; - } - else if (__timeout == 0) - { - time_to_wait = (double) 0; - } - else - { - time_to_wait = ~0; - } - - return vppcom_poll (__fds, __nfds, time_to_wait); -} - -int -vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) -{ - /* select an implementation */ - - /* return vcom_socket_poll_vppcom_impl (__fds, __nfds, __timeout); */ - return vcom_socket_poll_select_impl (__fds, __nfds, __timeout); -} - -#ifdef __USE_GNU -int -vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss) -{ - return -EOPNOTSUPP; -} -#endif - -int -vcom_socket_main_init (void) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - - if (VCOM_DEBUG > 0) - printf ("vcom_socket_main_init\n"); - - if (!vsm->init) - { - /* TBD: define FD_MAXSIZE and use it here */ - pool_alloc (vsm->vsockets, FD_SETSIZE); - vsm->sockidx_by_fd = hash_create (0, sizeof (i32)); - - pool_alloc (vsm->vepolls, FD_SETSIZE); - vsm->epollidx_by_epfd = hash_create (0, sizeof (i32)); - - pool_alloc (vsm->vepitems, FD_SETSIZE); - vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32)); - - vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *)); - vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *)); - - clib_time_init (&vsm->clib_time); - - vsm->init = 1; - } - - return 0; -} - - -void -vcom_socket_main_show (void) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_socket_t *vsock; - - vcom_epoll_t *vepoll; - - vcom_epitem_t *vepitem; - - i32 epfd; - i32 fd; - i32 *vepitemidxs, *vepitemidxs_var; - - if (vsm->init) - { - /* from active list of vsockets show vsock */ - - /* *INDENT-OFF* */ - pool_foreach (vsock, vsm->vsockets, - ({ - printf( - "fd='%04d', sid='%08x',type='%-30s'\n", - vsock->fd, vsock->sid, - vcom_socket_type_str (vsock->type)); - })); - /* *INDENT-ON* */ - - /* from active list of vepolls, show vepoll */ - - /* *INDENT-OFF* */ - pool_foreach (vepoll, vsm->vepolls, - ({ - printf( - "epfd='%04d', vep_idx='%08x', " - "type='%-30s', " - "flags='%d', count='%d', close='%d'\n", - vepoll->epfd, vepoll->vep_idx, - vcom_socket_epoll_type_str (vepoll->type), - vepoll->flags, vepoll->count, vepoll->close); - })); - /* *INDENT-ON* */ - - /* from active list of vepitems, show vepitem */ - - /* *INDENT-OFF* */ - pool_foreach (vepitem, vsm->vepitems, - ({ - printf( - "epfd='%04d', fd='%04d', " - "next_fd='%04d', prev_fd='%04d', " - "type='%-30s', " - "events='%04x', revents='%04x'\n", - vepitem->epfd, vepitem->fd, - vepitem->next_fd, vepitem->prev_fd, - vcom_socket_vcom_fd_type_str (vepitem->type), - vepitem->event.events, vepitem->revent.events); - })); - - /* *INDENT-ON* */ - - /* show epitemidxs for epfd */ - /* *INDENT-OFF* */ - hash_foreach (epfd, vepitemidxs, - vsm->epitemidxs_by_epfd, - ({ - printf("\n[ '%04d': ", epfd); - vec_foreach (vepitemidxs_var,vepitemidxs) - { - printf("'%04d' ", (int)vepitemidxs_var[0]); - } - printf("]\n"); - })); - /* *INDENT-ON* */ - - /* show epitemidxs for fd */ - /* *INDENT-OFF* */ - hash_foreach (fd, vepitemidxs, - vsm->epitemidxs_by_fd, - ({ - printf("\n{ '%04d': ", fd); - vec_foreach (vepitemidxs_var,vepitemidxs) - { - printf("'%04d' ", (int)vepitemidxs_var[0]); - } - printf("}\n"); - })); - /* *INDENT-ON* */ - - } -} - -void -vcom_socket_main_destroy (void) -{ - vcom_socket_main_t *vsm = &vcom_socket_main; - vcom_socket_t *vsock; - - vcom_epoll_t *vepoll; - - vcom_epitem_t *vepitem; - - i32 epfd; - i32 fd; - i32 *vepitemidxs; - - - if (VCOM_DEBUG > 0) - printf ("vcom_socket_main_destroy\n"); - - if (vsm->init) - { - - /* - * from active list of vepitems, - * remove all "vepitem" elements from the pool in a safe way - * */ - - /* *INDENT-OFF* */ - pool_flush (vepitem, vsm->vepitems, - ({ - if ((vepitem->type == FD_TYPE_EPOLL) || - (vepitem->type == FD_TYPE_VCOM_SOCKET)) - { - vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL, - vepitem->fd, NULL); - vepitem_init (vepitem); - } - })); - /* *INDENT-ON* */ - - pool_free (vsm->vepitems); - hash_free (vsm->epitemidx_by_epfdfd); - - /* free vepitemidxs for each epfd */ - /* *INDENT-OFF* */ - hash_foreach (epfd, vepitemidxs, - vsm->epitemidxs_by_epfd, - ({ - vec_free (vepitemidxs); - })); - /* *INDENT-ON* */ - hash_free (vsm->epitemidxs_by_epfd); - - /* free vepitemidxs for each fd */ - /* *INDENT-OFF* */ - hash_foreach (fd, vepitemidxs, - vsm->epitemidxs_by_fd, - ({ - vec_free (vepitemidxs); - })); - /* *INDENT-ON* */ - hash_free (vsm->epitemidxs_by_fd); - - - /* - * from active list of vsockets, - * close socket and vppcom session - * */ - - /* *INDENT-OFF* */ - pool_foreach (vsock, vsm->vsockets, - ({ - if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND) - { - vppcom_session_close (vsock->sid); - vcom_socket_close_socket (vsock->fd); - vsocket_init (vsock); - } - })); - /* *INDENT-ON* */ - - /* - * return vsocket element to the pool - * */ - - /* *INDENT-OFF* */ - pool_flush (vsock, vsm->vsockets, - ({ - // vsocket_init(vsock); - ; - })); - /* *INDENT-ON* */ - - pool_free (vsm->vsockets); - hash_free (vsm->sockidx_by_fd); - - /* - * from active list of vepolls, - * close epoll and vppcom_epoll - * */ - - /* *INDENT-OFF* */ - pool_foreach (vepoll, vsm->vepolls, - ({ - if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND) - { - vppcom_session_close (vepoll->vep_idx); - vcom_socket_close_epoll (vepoll->epfd); /* TBD: */ - vepoll_init (vepoll); - } - })); - /* *INDENT-ON* */ - - /* - * return vepoll element to the pool - * */ - - /* *INDENT-OFF* */ - pool_flush (vepoll, vsm->vepolls, - ({ - // vepoll_init(vepoll); - ; - })); - /* *INDENT-ON* */ - - pool_free (vsm->vepolls); - hash_free (vsm->epollidx_by_epfd); - - vsm->init = 0; - } -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vcom_socket.h b/src/vcl/vcom_socket.h deleted file mode 100644 index 2ce11c021a1..00000000000 --- a/src/vcl/vcom_socket.h +++ /dev/null @@ -1,475 +0,0 @@ -/* - * 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. - */ - -#ifndef included_vcom_socket_h -#define included_vcom_socket_h - -#include - -#include -#include -#include - -#define INVALID_SESSION_ID (~0) -#define INVALID_FD (~0) - -#define INVALID_VEP_IDX INVALID_SESSION_ID -#define INVALID_EPFD INVALID_FD - -typedef enum -{ - SOCKET_TYPE_UNBOUND = 0, - SOCKET_TYPE_KERNEL_BOUND, - SOCKET_TYPE_VPPCOM_BOUND -} vcom_socket_type_t; - -typedef enum -{ - EPOLL_TYPE_UNBOUND = 0, - EPOLL_TYPE_KERNEL_BOUND, - EPOLL_TYPE_VPPCOM_BOUND -} vcom_epoll_type_t; - -typedef enum -{ - FD_TYPE_INVALID = 0, - FD_TYPE_KERNEL, - FD_TYPE_EPOLL, - FD_TYPE_VCOM_SOCKET, - /* add new types here */ - /* FD_TYPE_MAX should be the last entry */ - FD_TYPE_MAX -} vcom_fd_type_t; - -typedef struct -{ - /* file descriptor - - * fd 0, 1, 2 have special meaning and are reserved, - * -1 denote invalid fd */ - i32 fd; - - /* session id - -1 denote invalid sid */ - i32 sid; - - /* socket type */ - vcom_socket_type_t type; - - /* vcom socket attributes here */ - -} vcom_socket_t; - -typedef struct -{ - /* epoll file descriptor - - * epfd 0, 1, 2 have special meaning and are reserved, - * -1 denote invalid epfd */ - i32 epfd; - - /* vep idx - -1 denote invalid vep_idx */ - i32 vep_idx; - - /* epoll type */ - vcom_epoll_type_t type; - - /* flags - 0 or EPOLL_CLOEXEC */ - i32 flags; - - /* vcom epoll attributes here */ - - /* - * 00. count of file descriptors currently registered - * on this epoll instance. - * 01. number of file descriptors in the epoll set. - * 02. EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL - * update the count. - * 03. cached for frequent access. - * */ - i32 count; - i32 vcl_cnt; - i32 libc_cnt; - - /* close( ) called on this epoll instance */ - /* 0 - close ( ) not called, 1 - close( ) called. */ - u32 close; - -} vcom_epoll_t; - -typedef struct -{ - /* "container" of this item */ - i32 epfd; - - /* fd - file descriptor information this item refers to */ - i32 fd; - /* next and prev fd in the "epoll set" of epfd */ - i32 next_fd; - i32 prev_fd; - - /* vcom fd type */ - vcom_fd_type_t type; - - /* interested events and the source fd */ - struct epoll_event event; - - /* ready events and the source fd */ - struct epoll_event revent; - - /* epitem attributes here */ - -} vcom_epitem_t; - -typedef union vcom_epitem_key -{ - struct - { - i32 fd; - i32 epfd; - }; - i64 key; -} __EPOLL_PACKED vcom_epitem_key_t; - -static inline char * -vcom_socket_type_str (vcom_socket_type_t t) -{ - switch (t) - { - case SOCKET_TYPE_UNBOUND: - return "SOCKET_TYPE_UNBOUND"; - - case SOCKET_TYPE_KERNEL_BOUND: - return "SOCKET_TYPE_KERNEL_BOUND"; - - case SOCKET_TYPE_VPPCOM_BOUND: - return "SOCKET_TYPE_VPPCOM_BOUND"; - - default: - return "SOCKET_TYPE_UNKNOWN"; - } -} - -static inline char * -vcom_socket_epoll_type_str (vcom_epoll_type_t t) -{ - switch (t) - { - case EPOLL_TYPE_UNBOUND: - return "EPOLL_TYPE_UNBOUND"; - - case EPOLL_TYPE_KERNEL_BOUND: - return "EPOLL_TYPE_KERNEL_BOUND"; - - case EPOLL_TYPE_VPPCOM_BOUND: - return "EPOLL_TYPE_VPPCOM_BOUND"; - - default: - return "EPOLL_TYPE_UNKNOWN"; - } -} - -static inline char * -vcom_socket_vcom_fd_type_str (vcom_fd_type_t t) -{ - switch (t) - { - case FD_TYPE_KERNEL: - return "FD_TYPE_KERNEL"; - - case FD_TYPE_EPOLL: - return "FD_TYPE_EPOLL"; - - case FD_TYPE_VCOM_SOCKET: - return "FD_TYPE_VCOM_SOCKET"; - - default: - return "FD_TYPE_UNKNOWN"; - } -} - -static inline int -vcom_socket_type_is_vppcom_bound (vcom_socket_type_t t) -{ - return t == SOCKET_TYPE_VPPCOM_BOUND; -} - -static inline int -vcom_socket_epoll_type_is_vppcom_bound (vcom_epoll_type_t t) -{ - return t == EPOLL_TYPE_VPPCOM_BOUND; -} - -static inline void -vsocket_init (vcom_socket_t * vsock) -{ - memset (vsock, 0, sizeof (*vsock)); - - vsock->fd = INVALID_FD; - vsock->sid = INVALID_SESSION_ID; - vsock->type = SOCKET_TYPE_UNBOUND; - /* vcom socket attributes init here */ -} - -static inline void -vepoll_init (vcom_epoll_t * vepoll) -{ - memset (vepoll, 0, sizeof (*vepoll)); - - vepoll->epfd = INVALID_EPFD; - vepoll->vep_idx = INVALID_VEP_IDX; - vepoll->type = EPOLL_TYPE_UNBOUND; - vepoll->flags = 0; - - vepoll->count = 0; - vepoll->close = 0; - /* vcom epoll attributes init here */ -} - -static inline void -vepitem_init (vcom_epitem_t * vepitem) -{ - struct epoll_event event = {.events = 0,.data.fd = INVALID_FD }; - - memset (vepitem, 0, sizeof (*vepitem)); - - vepitem->epfd = INVALID_EPFD; - - vepitem->fd = INVALID_FD; - vepitem->next_fd = INVALID_FD; - vepitem->prev_fd = INVALID_FD; - - vepitem->type = FD_TYPE_INVALID; - - vepitem->event = event; - vepitem->revent = event; - /* vepoll attributes init here */ -} - -static inline void -vepitemkey_init (vcom_epitem_key_t * epfdfd) -{ - memset (epfdfd, 0, sizeof (*epfdfd)); - - epfdfd->epfd = INVALID_EPFD; - epfdfd->fd = INVALID_FD; -} - -static inline void -vsocket_set (vcom_socket_t * vsock, i32 fd, i32 sid, vcom_socket_type_t type) -{ - vsock->fd = fd; - vsock->sid = sid; - vsock->type = type; - /* vcom socket attributes set here */ -} - -static inline void -vepoll_set (vcom_epoll_t * vepoll, - i32 epfd, i32 vep_idx, - vcom_epoll_type_t type, i32 flags, i32 count, u32 close) -{ - vepoll->epfd = epfd; - vepoll->vep_idx = vep_idx; - vepoll->type = type; - vepoll->flags = flags; - - vepoll->count = count; - vepoll->close = close; - /* vcom epoll attributes set here */ -} - -static inline void -vepitem_set (vcom_epitem_t * vepitem, - i32 epfd, - i32 fd, i32 next_fd, i32 prev_fd, - vcom_fd_type_t type, - struct epoll_event event, struct epoll_event revent) -{ - vepitem->epfd = epfd; - - vepitem->fd = fd; - vepitem->next_fd = next_fd; - vepitem->prev_fd = prev_fd; - - vepitem->type = type; - - vepitem->event = event; - vepitem->revent = revent; - /* vcom epitem attributes set here */ -} - -static inline void -vepitemkey_set (vcom_epitem_key_t * epfdfd, i32 epfd, i32 fd) -{ - epfdfd->epfd = epfd; - epfdfd->fd = fd; -} - -static inline int -vsocket_is_vppcom_bound (vcom_socket_t * vsock) -{ - return vcom_socket_type_is_vppcom_bound (vsock->type); -} - -static inline int -vepoll_is_vppcom_bound (vcom_epoll_t * vepoll) -{ - return vcom_socket_epoll_type_is_vppcom_bound (vepoll->type); -} - -int vcom_socket_main_init (void); - -void vcom_socket_main_destroy (void); - -void vcom_socket_main_show (void); - -int vcom_socket_is_vcom_fd (int fd); - -int vcom_socket_is_vcom_epfd (int epfd); - -int vcom_socket_close (int __fd); - -ssize_t vcom_socket_read (int __fd, void *__buf, size_t __nbytes); - -ssize_t vcom_socket_readv (int __fd, const struct iovec *__iov, int __iovcnt); - -ssize_t vcom_socket_write (int __fd, const void *__buf, size_t __n); - -ssize_t vcom_socket_writev (int __fd, const struct iovec *__iov, - int __iovcnt); - -int vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap); - -int vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap); - -int -vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds, - fd_set * __restrict vcom_writefds, - fd_set * __restrict vcom_exceptfds, - struct timeval *__restrict timeout); - - -int vcom_socket_socket (int __domain, int __type, int __protocol); - -int -vcom_socket_socketpair (int __domain, int __type, int __protocol, - int __fds[2]); - -int vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -int -vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len); - -int -vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); - -int -vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __len); - -ssize_t -vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags); - -ssize_t vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags); - -ssize_t -vcom_socket_sendfile (int __out_fd, int __in_fd, off_t * __offset, - size_t __len); - -/* - * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET), - * 0 otherwise - * */ -int vcom_socket_is_connection_mode_socket (int __fd); - -ssize_t -vcom_socket_sendto (int __fd, const void *__buf, size_t __n, - int __flags, __CONST_SOCKADDR_ARG __addr, - socklen_t __addr_len); - -ssize_t -vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n, - int __flags, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len); - -ssize_t -vcom_socket_sendmsg (int __fd, const struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -int -vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags); -#endif - -ssize_t vcom_socket_recvmsg (int __fd, struct msghdr *__message, int __flags); - -#ifdef __USE_GNU -int -vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages, - unsigned int __vlen, int __flags, - struct timespec *__tmo); -#endif - -int -vcom_socket_getsockopt (int __fd, int __level, int __optname, - void *__restrict __optval, - socklen_t * __restrict __optlen); - -int -vcom_socket_setsockopt (int __fd, int __level, int __optname, - const void *__optval, socklen_t __optlen); - -int vcom_socket_listen (int __fd, int __n); - -int -vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len); - -int -vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr, - socklen_t * __restrict __addr_len, int __flags); - -int vcom_socket_shutdown (int __fd, int __how); - -int vcom_socket_epoll_create1 (int __flags); - -int -vcom_socket_epoll_ctl (int __epfd, int __op, int __fd, - struct epoll_event *__event); - -int -vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events, - int __maxevents, int __timeout, - const __sigset_t * __ss); - -/* - * handle only vcom fds - */ -int vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); - -#ifdef __USE_GNU -int -vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, const __sigset_t * __ss); -#endif - -#endif /* included_vcom_socket_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index aff81f5351e..28dc6070572 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -98,12 +98,47 @@ typedef struct ip46_address_t ip46; } vppcom_ip46_t; +enum +{ + VCL_SESS_ATTR_SERVER, + VCL_SESS_ATTR_CUT_THRU, + VCL_SESS_ATTR_VEP, + VCL_SESS_ATTR_VEP_SESSION, + VCL_SESS_ATTR_LISTEN, // SOL_SOCKET,SO_ACCEPTCONN + VCL_SESS_ATTR_NONBLOCK, // fcntl,O_NONBLOCK + VCL_SESS_ATTR_REUSEADDR, // SOL_SOCKET,SO_REUSEADDR + VCL_SESS_ATTR_REUSEPORT, // SOL_SOCKET,SO_REUSEPORT + VCL_SESS_ATTR_BROADCAST, // SOL_SOCKET,SO_BROADCAST + VCL_SESS_ATTR_V6ONLY, // SOL_TCP,IPV6_V6ONLY + VCL_SESS_ATTR_KEEPALIVE, // SOL_SOCKET,SO_KEEPALIVE + VCL_SESS_ATTR_TCP_NODELAY, // SOL_TCP,TCP_NODELAY + VCL_SESS_ATTR_TCP_KEEPIDLE, // SOL_TCP,TCP_KEEPIDLE + VCL_SESS_ATTR_TCP_KEEPINTVL, // SOL_TCP,TCP_KEEPINTVL + VCL_SESS_ATTR_MAX +} vppcom_session_attr_t; + +#define VCL_SESS_ATTR_SET(ATTR, VAL) \ +do { \ + (ATTR) |= 1 << (VAL); \ + } while (0) + +#define VCL_SESS_ATTR_CLR(ATTR, VAL) \ +do { \ + (ATTR) &= ~(1 << (VAL)); \ + } while (0) + +#define VCL_SESS_ATTR_TEST(ATTR, VAL) \ + ((ATTR) & (1 << (VAL)) ? 1 : 0) + typedef struct { volatile session_state_t state; svm_fifo_t *server_rx_fifo; svm_fifo_t *server_tx_fifo; + u32 sndbuf_size; // VPP-TBD: Hack until support setsockopt(SO_SNDBUF) + u32 rcvbuf_size; // VPP-TBD: Hack until support setsockopt(SO_RCVBUF) + u32 user_mss; // VPP-TBD: Hack until support setsockopt(TCP_MAXSEG) u8 *segment_name; u32 sm_seg_index; u32 client_context; @@ -111,15 +146,17 @@ typedef struct svm_queue_t *vpp_event_queue; /* Socket configuration state */ - /* TBD: covert 'is_*' vars to bit in u8 flags; */ + /* TBD: covert 'is_*' vars to bit in session->attr; */ u8 is_server; u8 is_listen; u8 is_cut_thru; u8 is_nonblocking; u8 is_vep; u8 is_vep_session; + u32 attr; u32 wait_cont_idx; vppcom_epoll_t vep; + int libc_epfd; u32 vrf; vppcom_ip46_t lcl_addr; vppcom_ip46_t peer_addr; @@ -214,17 +251,17 @@ static vppcom_main_t _vppcom_main = { static vppcom_main_t *vcm = &_vppcom_main; -#define VCL_LOCK_AND_GET_SESSION(I, S) \ -do { \ - clib_spinlock_lock (&vcm->sessions_lockp); \ - rv = vppcom_session_at_index (I, S); \ - if (PREDICT_FALSE (rv)) \ - { \ - clib_spinlock_unlock (&vcm->sessions_lockp); \ - clib_warning ("[%s] ERROR: Invalid ##I (%u)!", \ - getpid (), I); \ - goto done; \ - } \ +#define VCL_LOCK_AND_GET_SESSION(I, S) \ +do { \ + clib_spinlock_lock (&vcm->sessions_lockp); \ + rv = vppcom_session_at_index (I, S); \ + if (PREDICT_FALSE (rv)) \ + { \ + clib_spinlock_unlock (&vcm->sessions_lockp); \ + clib_warning ("VCL<%d>: ERROR: Invalid ##I (%u)!", \ + getpid (), I); \ + goto done; \ + } \ } while (0) static const char * @@ -311,7 +348,7 @@ vppcom_session_at_index (u32 session_index, session_t * volatile *sess) if (PREDICT_FALSE ((session_index == ~0) || pool_is_free_index (vcm->sessions, session_index))) { - clib_warning ("[%d] invalid session, sid (%u) has been closed!", + clib_warning ("VCL<%d>: invalid session, sid (%u) has been closed!", getpid (), session_index); return VPPCOM_EBADFD; } @@ -339,15 +376,15 @@ vppcom_session_table_lookup_listener (u64 listener_handle) p = hash_get (vcm->session_index_by_vpp_handles, handle); if (!p) { - clib_warning ("[%d] couldn't find listen session: unknown vpp " + clib_warning ("VCL<%d>: couldn't find listen session: unknown vpp " "listener handle %llx", getpid (), listener_handle); return 0; } if (pool_is_free_index (vcm->sessions, p[0])) { if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] invalid listen session, sid (%u)", getpid (), - p[0]); + clib_warning ("VCL<%d>: invalid listen session, sid (%u)", + getpid (), p[0]); return 0; } @@ -390,22 +427,20 @@ vppcom_connect_to_vpp (char *app_name) int rv = VPPCOM_OK; if (VPPCOM_DEBUG > 0) - printf ("\nConnecting to VPP api..."); + clib_warning ("VCL<%d>: app (%s) connecting to VPP api...", + getpid (), app_name); + if (vl_client_connect_to_vlib ("/vpe-api", app_name, vcm->cfg.vpp_api_q_length) < 0) { - clib_warning ("[%d] connect to vpp (%s) failed!", getpid (), app_name); + clib_warning ("VCL<%d>: app (%s) connect failed!", getpid (), app_name); rv = VPPCOM_ECONNREFUSED; } else { - vcm->vl_input_queue = am->shmem_hdr->vl_input_queue; vcm->my_client_index = am->my_client_index; vcm->app_state = STATE_APP_CONN_VPP; - - if (VPPCOM_DEBUG > 0) - printf (" connected!\n"); } if (VPPCOM_DEBUG > 0) @@ -437,6 +472,8 @@ vppcom_connect_to_vpp (char *app_name) /* *INDENT-ON* */ } + clib_warning ("VCL<%d>: app (%s) is connected to VPP!", + getpid (), app_name); return rv; } @@ -478,7 +515,7 @@ vppcom_wait_for_app_state_change (app_state_t app_state) return VPPCOM_OK; } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] timeout waiting for state %s (%d)", getpid (), + clib_warning ("VCL<%d>: timeout waiting for state %s (%d)", getpid (), vppcom_app_state_str (app_state), app_state); if (VPPCOM_DEBUG > 0) @@ -537,7 +574,7 @@ vppcom_wait_for_session_state_change (u32 session_index, while (clib_time_now (&vcm->clib_time) < timeout); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] timeout waiting for state 0x%x (%s)", getpid (), + clib_warning ("VCL<%d>: timeout waiting for state 0x%x (%s)", getpid (), state, vppcom_session_state_str (state)); if (VPPCOM_DEBUG > 0) @@ -578,7 +615,8 @@ vppcom_wait_for_client_session_index (f64 wait_for_time) return VPPCOM_EAGAIN; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] timeout waiting for client_session_index", getpid ()); + clib_warning ("VCL<%d>: timeout waiting for client_session_index", + getpid ()); if (VPPCOM_DEBUG > 0) { @@ -631,7 +669,7 @@ vppcom_app_session_enable (void) if (PREDICT_FALSE (rv)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] application session enable timed out! " + clib_warning ("VCL<%d>: application session enable timed out! " "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv)); return rv; @@ -646,7 +684,7 @@ static void { if (mp->retval) { - clib_warning ("[%d] session_enable_disable failed: %U", getpid (), + clib_warning ("VCL<%d>: session_enable_disable failed: %U", getpid (), format_api_error, ntohl (mp->retval)); } else @@ -701,7 +739,8 @@ vppcom_app_attach (void) if (PREDICT_FALSE (rv)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] application attach timed out! returning %d (%s)", + clib_warning ("VCL<%d>: application attach timed out! " + "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv)); return rv; } @@ -732,14 +771,14 @@ vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t * memset (a, 0, sizeof (*a)); if (mp->retval) { - clib_warning ("[%d] attach failed: %U", getpid (), + clib_warning ("VCL<%d>: attach failed: %U", getpid (), format_api_error, ntohl (mp->retval)); return; } if (mp->segment_name_length == 0) { - clib_warning ("[%d] segment_name_length zero", getpid ()); + clib_warning ("VCL<%d>: segment_name_length zero", getpid ()); return; } @@ -753,8 +792,8 @@ vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t * vec_reset_length (a->new_segment_indices); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed", getpid (), - mp->segment_name); + clib_warning ("VCL<%d>: svm_fifo_segment_attach ('%s') failed", + getpid (), mp->segment_name); return; } @@ -769,7 +808,7 @@ vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t * mp) { if (mp->retval) - clib_warning ("[%d] detach failed: %U", getpid (), format_api_error, + clib_warning ("VCL<%d>: detach failed: %U", getpid (), format_api_error, ntohl (mp->retval)); vcm->app_state = STATE_APP_ENABLED; @@ -780,7 +819,7 @@ vl_api_disconnect_session_reply_t_handler (vl_api_disconnect_session_reply_t * mp) { if (mp->retval) - clib_warning ("[%d] vpp handle 0x%llx: disconnect session failed: %U", + clib_warning ("VCL<%d>: vpp handle 0x%llx: disconnect session failed: %U", getpid (), mp->handle, format_api_error, ntohl (mp->retval)); } @@ -800,12 +839,12 @@ vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp) vec_reset_length (a->new_segment_indices); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] svm_fifo_segment_attach ('%s') failed", + clib_warning ("VCL<%d>: svm_fifo_segment_attach ('%s') failed", getpid (), mp->segment_name); return; } if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] mapped new segment '%s' size %d", getpid (), + clib_warning ("VCL<%d>: mapped new segment '%s' size %d", getpid (), mp->segment_name, mp->segment_size); } @@ -825,7 +864,7 @@ vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp) session->state = STATE_CLOSE_ON_EMPTY; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "setting state to 0x%x (%s)", getpid (), mp->handle, session_index, session->state, vppcom_session_state_str (session->state)); @@ -834,12 +873,12 @@ vl_api_disconnect_session_t_handler (vl_api_disconnect_session_t * mp) done: if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "session lookup failed!", getpid (), mp->handle, session_index); } else - clib_warning ("[%d] vpp handle 0x%llx: session lookup by " + clib_warning ("VCL<%d>: vpp handle 0x%llx: session lookup by " "handle failed!", getpid (), mp->handle); } @@ -860,7 +899,7 @@ vl_api_reset_session_t_handler (vl_api_reset_session_t * mp) if (PREDICT_FALSE (rval)) { rv = VNET_API_ERROR_INVALID_VALUE_2; - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "session lookup failed! returning %d %U", getpid (), mp->handle, p[0], rv, format_api_error, rv); @@ -873,7 +912,7 @@ vl_api_reset_session_t_handler (vl_api_reset_session_t * mp) session->state = STATE_CLOSE_ON_EMPTY; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "state set to %d (%s)!", getpid (), mp->handle, p[0], session->state, vppcom_session_state_str (session->state)); @@ -883,7 +922,7 @@ vl_api_reset_session_t_handler (vl_api_reset_session_t * mp) else { rv = VNET_API_ERROR_INVALID_VALUE; - clib_warning ("[%d] ERROR: vpp handle 0x%llx: session lookup " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx: session lookup " "failed! returning %d %U", getpid (), mp->handle, rv, format_api_error, rv); } @@ -910,7 +949,7 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) done: if (mp->retval) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "connect failed! %U", getpid (), mp->handle, session_index, format_api_error, ntohl (mp->retval)); @@ -941,14 +980,14 @@ done: memset (a, 0, sizeof (*a)); a->segment_name = (char *) mp->segment_name; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] cut-thru segment: %s\n", + clib_warning ("VCL<%d>: cut-thru segment: %s\n", getpid (), a->segment_name); rv = svm_fifo_segment_attach (a); vec_reset_length (a->new_segment_indices); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] sm_fifo_segment_attach ('%s') failed", + clib_warning ("VCL<%d>: sm_fifo_segment_attach ('%s') failed", getpid (), a->segment_name); goto done_unlock; } @@ -979,7 +1018,7 @@ done: hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: connect succeeded!" + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect succeeded!" " session_rx_fifo %p, refcnt %d," " session_tx_fifo %p, refcnt %d", getpid (), mp->handle, session_index, @@ -1019,7 +1058,8 @@ vppcom_send_disconnect_session_reply (u64 vpp_handle, u32 session_index, vl_api_disconnect_session_reply_t *rmp; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " + "sending disconnect msg", getpid (), vpp_handle, session_index); rmp = vl_msg_api_alloc (sizeof (*rmp)); @@ -1037,7 +1077,8 @@ vppcom_send_disconnect_session (u64 vpp_handle, u32 session_index) vl_api_disconnect_session_t *dmp; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending disconnect msg", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " + "sending disconnect msg", getpid (), vpp_handle, session_index); dmp = vl_msg_api_alloc (sizeof (*dmp)); @@ -1059,9 +1100,10 @@ vl_api_bind_sock_reply_t_handler (vl_api_bind_sock_reply_t * mp) done: if (mp->retval) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: bind failed: %U", - getpid (), mp->handle, session_index, format_api_error, - ntohl (mp->retval)); + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, " + "sid %u: bind failed: %U", + getpid (), mp->handle, session_index, + format_api_error, ntohl (mp->retval)); rv = vppcom_session_at_index (session_index, &session); if (rv == VPPCOM_OK) { @@ -1087,7 +1129,7 @@ done: session->state = STATE_LISTEN; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: bind succeeded!", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: bind succeeded!", getpid (), mp->handle, mp->context); done_unlock: clib_spinlock_unlock (&vcm->sessions_lockp); @@ -1097,12 +1139,13 @@ static void vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp) { if (mp->retval) - clib_warning ("[%d] ERROR: sid %u: unbind failed: %U", + clib_warning ("VCL<%d>: ERROR: sid %u: unbind failed: %U", getpid (), mp->context, format_api_error, ntohl (mp->retval)); else if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] sid %u: unbind succeeded!", getpid (), mp->context); + clib_warning ("VCL<%d>: sid %u: unbind succeeded!", + getpid (), mp->context); } u8 * @@ -1212,7 +1255,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) clib_spinlock_lock (&vcm->sessions_lockp); if (!clib_fifo_free_elts (vcm->client_session_index_fifo)) { - clib_warning ("[%d] client session queue is full!", getpid ()); + clib_warning ("VCL<%d>: client session queue is full!", getpid ()); vppcom_send_accept_session_reply (mp->handle, mp->context, VNET_API_ERROR_QUEUE_FULL); clib_spinlock_unlock (&vcm->sessions_lockp); @@ -1222,8 +1265,9 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) listen_session = vppcom_session_table_lookup_listener (mp->listener_handle); if (!listen_session) { - clib_warning ("[%d] ERROR: couldn't find listen session: unknown vpp " - "listener handle %llx", getpid (), mp->listener_handle); + clib_warning ("VCL<%d>: ERROR: couldn't find listen session: " + "unknown vpp listener handle %llx", + getpid (), mp->listener_handle); clib_spinlock_unlock (&vcm->sessions_lockp); return; } @@ -1263,7 +1307,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: client accept " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: client accept " "request from %s address %U port %d queue %p!", getpid (), mp->handle, session_index, mp->is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->ip, mp->is_ip4, @@ -1366,7 +1410,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] client session queue is full!", getpid ()); + clib_warning ("VCL<%d>: client session queue is full!", getpid ()); /* TBD: Fix api to include vpp handle */ vppcom_send_connect_session_reply (0 /* session */ , 0 /* sid */ , @@ -1397,7 +1441,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) session->state = STATE_ACCEPT; clib_fifo_add1 (vcm->client_session_index_fifo, session_index); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] sid %u: Got a cut-thru connect request! " + clib_warning ("VCL<%d>: sid %u: Got a cut-thru connect request! " "clib_fifo_elts %u!\n", getpid (), session_index, clib_fifo_elts (vcm->client_session_index_fifo)); @@ -1483,7 +1527,7 @@ vppcom_session_unbind (u32 session_index) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "sending unbind msg! new state 0x%x (%s)", getpid (), vpp_handle, session_index, session->state, vppcom_session_state_str (session->state)); @@ -1532,8 +1576,8 @@ vppcom_session_disconnect (u32 session_index) if (VPPCOM_DEBUG > 1) { - clib_warning ("[%d] vpp handle 0x%llx, sid %u: %s state 0x%x (%s), " - "is_cut_thru %d, is_listen %d", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: %s " + "state 0x%x (%s), is_cut_thru %d, is_listen %d", getpid (), vpp_handle, session_index, is_server ? "server" : "client", state, vppcom_session_state_str (state), @@ -1542,7 +1586,7 @@ vppcom_session_disconnect (u32 session_index) if (PREDICT_FALSE (is_listen)) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "Cannot disconnect a listen socket!", getpid (), vpp_handle, session_index); rv = VPPCOM_EBADFD; @@ -1561,7 +1605,7 @@ vppcom_session_disconnect (u32 session_index) vppcom_send_disconnect_session_reply (vpp_handle, session_index, 0 /* rv */ ); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "sending disconnect REPLY...", getpid (), vpp_handle, session_index); } @@ -1571,7 +1615,7 @@ vppcom_session_disconnect (u32 session_index) else { if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "sending disconnect...", getpid (), vpp_handle, session_index); @@ -1594,7 +1638,7 @@ vppcom_session_disconnect (u32 session_index) VCL_LOCK_AND_GET_SESSION (session_index, &session); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] sid %d: freeing cut-thru fifos in " + clib_warning ("VCL<%d>: sid %d: freeing cut-thru fifos in " "sm_seg_index %d! " " server_rx_fifo %p, refcnt = %d" " server_tx_fifo %p, refcnt = %d", @@ -1754,7 +1798,7 @@ vppcom_cfg_heapsize (char *conf_fname) if (size == 0) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] parse error '%s %s', " + clib_warning ("VCL<%d>: parse error '%s %s', " "using default heapsize %lld (0x%llx)", getpid (), argv[i], argv[i + 1], vcl_cfg->heapsize, vcl_cfg->heapsize); @@ -1768,7 +1812,7 @@ vppcom_cfg_heapsize (char *conf_fname) else { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] parse error '%s %s', " + clib_warning ("VCL<%d>: parse error '%s %s', " "using default heapsize %lld (0x%llx)", getpid (), argv[i], argv[i + 1], vcl_cfg->heapsize, vcl_cfg->heapsize); @@ -1787,7 +1831,7 @@ defaulted: MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (vcl_mem == MAP_FAILED) { - clib_unix_error ("[%d] ERROR: mmap(0, %lld == 0x%llx, " + clib_unix_error ("VCL<%d>: ERROR: mmap(0, %lld == 0x%llx, " "PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, " "-1, 0) failed!", getpid (), vcl_cfg->heapsize, vcl_cfg->heapsize); @@ -1796,13 +1840,13 @@ defaulted: heap = clib_mem_init (vcl_mem, vcl_cfg->heapsize); if (!heap) { - clib_warning ("[%d] ERROR: clib_mem_init() failed!", getpid ()); + clib_warning ("VCL<%d>: ERROR: clib_mem_init() failed!", getpid ()); return; } vcl_mem = clib_mem_alloc (sizeof (_vppcom_main)); if (!vcl_mem) { - clib_warning ("[%d] ERROR: clib_mem_alloc() failed!", getpid ()); + clib_warning ("VCL<%d>: ERROR: clib_mem_alloc() failed!", getpid ()); return; } @@ -1810,7 +1854,7 @@ defaulted: vcm = vcl_mem; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] allocated VCL heap = %p, size %lld (0x%llx)", + clib_warning ("VCL<%d>: allocated VCL heap = %p, size %lld (0x%llx)", getpid (), heap, vcl_cfg->heapsize, vcl_cfg->heapsize); } @@ -1830,7 +1874,7 @@ vppcom_cfg_read (char *conf_fname) if (fd < 0) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] open configuration file '%s' failed!", + clib_warning ("VCL<%d>: open configuration file '%s' failed!", getpid (), conf_fname); goto file_done; } @@ -1838,14 +1882,15 @@ vppcom_cfg_read (char *conf_fname) if (fstat (fd, &s) < 0) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] failed to stat `%s'", getpid (), conf_fname); + clib_warning ("VCL<%d>: failed to stat `%s'", getpid (), conf_fname); goto file_done; } if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode))) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] not a regular file `%s'", getpid (), conf_fname); + clib_warning ("VCL<%d>: not a regular file `%s'", + getpid (), conf_fname); goto file_done; } @@ -1868,7 +1913,7 @@ vppcom_cfg_read (char *conf_fname) { vec_terminate_c_string (chroot_path); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured heapsize %s, " + clib_warning ("VCL<%d>: configured heapsize %s, " "actual heapsize %lld (0x%llx)", getpid (), chroot_path, vcl_cfg->heapsize, vcl_cfg->heapsize); @@ -1879,7 +1924,7 @@ vppcom_cfg_read (char *conf_fname) vec_terminate_c_string (chroot_path); vl_set_memory_root_path ((char *) chroot_path); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured api-prefix %s", + clib_warning ("VCL<%d>: configured api-prefix %s", getpid (), chroot_path); chroot_path = 0; /* Don't vec_free() it! */ } @@ -1887,7 +1932,7 @@ vppcom_cfg_read (char *conf_fname) { if (q_len < vcl_cfg->vpp_api_q_length) { - clib_warning ("[%d] ERROR: configured vpp-api-q-length " + clib_warning ("VCL<%d>: ERROR: configured vpp-api-q-length " "(%u) is too small! Using default: %u ", getpid (), q_len, vcl_cfg->vpp_api_q_length); } @@ -1896,7 +1941,7 @@ vppcom_cfg_read (char *conf_fname) vcl_cfg->vpp_api_q_length = q_len; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured vpp-api-q-length %u", + clib_warning ("VCL<%d>: configured vpp-api-q-length %u", getpid (), vcl_cfg->vpp_api_q_length); } } @@ -1904,26 +1949,26 @@ vppcom_cfg_read (char *conf_fname) { vl_set_memory_uid (uid); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured uid %d", getpid (), uid); + clib_warning ("VCL<%d>: configured uid %d", getpid (), uid); } else if (unformat (line_input, "gid %d", &gid)) { vl_set_memory_gid (gid); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured gid %d", getpid (), gid); + clib_warning ("VCL<%d>: configured gid %d", getpid (), gid); } else if (unformat (line_input, "segment-baseva 0x%lx", &vcl_cfg->segment_baseva)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured segment_baseva 0x%lx", + clib_warning ("VCL<%d>: configured segment_baseva 0x%lx", getpid (), vcl_cfg->segment_baseva); } else if (unformat (line_input, "segment-size 0x%lx", &vcl_cfg->segment_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured segment_size 0x%lx (%ld)", + clib_warning ("VCL<%d>: configured segment_size 0x%lx (%ld)", getpid (), vcl_cfg->segment_size, vcl_cfg->segment_size); } @@ -1931,7 +1976,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->segment_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured segment_size %ld (0x%lx)", + clib_warning ("VCL<%d>: configured segment_size %ld (0x%lx)", getpid (), vcl_cfg->segment_size, vcl_cfg->segment_size); } @@ -1940,7 +1985,7 @@ vppcom_cfg_read (char *conf_fname) { if (VPPCOM_DEBUG > 0) clib_warning - ("[%d] configured add_segment_size 0x%lx (%ld)", + ("VCL<%d>: configured add_segment_size 0x%lx (%ld)", getpid (), vcl_cfg->add_segment_size, vcl_cfg->add_segment_size); } @@ -1949,7 +1994,7 @@ vppcom_cfg_read (char *conf_fname) { if (VPPCOM_DEBUG > 0) clib_warning - ("[%d] configured add_segment_size %ld (0x%lx)", + ("VCL<%d>: configured add_segment_size %ld (0x%lx)", getpid (), vcl_cfg->add_segment_size, vcl_cfg->add_segment_size); } @@ -1957,7 +2002,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->preallocated_fifo_pairs)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured preallocated_fifo_pairs " + clib_warning ("VCL<%d>: configured preallocated_fifo_pairs " "%d (0x%x)", getpid (), vcl_cfg->preallocated_fifo_pairs, vcl_cfg->preallocated_fifo_pairs); @@ -1966,7 +2011,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->rx_fifo_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured rx_fifo_size 0x%lx (%ld)", + clib_warning ("VCL<%d>: configured rx_fifo_size 0x%lx (%ld)", getpid (), vcl_cfg->rx_fifo_size, vcl_cfg->rx_fifo_size); } @@ -1974,7 +2019,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->rx_fifo_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured rx_fifo_size %ld (0x%lx)", + clib_warning ("VCL<%d>: configured rx_fifo_size %ld (0x%lx)", getpid (), vcl_cfg->rx_fifo_size, vcl_cfg->rx_fifo_size); } @@ -1982,7 +2027,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->tx_fifo_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured tx_fifo_size 0x%lx (%ld)", + clib_warning ("VCL<%d>: configured tx_fifo_size 0x%lx (%ld)", getpid (), vcl_cfg->tx_fifo_size, vcl_cfg->tx_fifo_size); } @@ -1990,7 +2035,7 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->tx_fifo_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured tx_fifo_size %ld (0x%lx)", + clib_warning ("VCL<%d>: configured tx_fifo_size %ld (0x%lx)", getpid (), vcl_cfg->tx_fifo_size, vcl_cfg->tx_fifo_size); } @@ -1998,7 +2043,8 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->event_queue_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured event_queue_size 0x%lx (%ld)", + clib_warning ("VCL<%d>: configured event_queue_size " + "0x%lx (%ld)", getpid (), vcl_cfg->event_queue_size, vcl_cfg->event_queue_size); } @@ -2006,7 +2052,8 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->event_queue_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured event_queue_size %ld (0x%lx)", + clib_warning ("VCL<%d>: configured event_queue_size " + "%ld (0x%lx)", getpid (), vcl_cfg->event_queue_size, vcl_cfg->event_queue_size); } @@ -2014,7 +2061,8 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->listen_queue_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured listen_queue_size 0x%lx (%ld)", + clib_warning ("VCL<%d>: configured listen_queue_size " + "0x%lx (%ld)", getpid (), vcl_cfg->listen_queue_size, vcl_cfg->listen_queue_size); } @@ -2022,7 +2070,8 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->listen_queue_size)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured listen_queue_size %ld (0x%lx)", + clib_warning ("VCL<%d>: configured listen_queue_size " + "%ld (0x%lx)", getpid (), vcl_cfg->listen_queue_size, vcl_cfg->listen_queue_size); } @@ -2030,49 +2079,51 @@ vppcom_cfg_read (char *conf_fname) &vcl_cfg->app_timeout)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_timeout %f", + clib_warning ("VCL<%d>: configured app_timeout %f", getpid (), vcl_cfg->app_timeout); } else if (unformat (line_input, "session-timeout %f", &vcl_cfg->session_timeout)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured session_timeout %f", + clib_warning ("VCL<%d>: configured session_timeout %f", getpid (), vcl_cfg->session_timeout); } else if (unformat (line_input, "accept-timeout %f", &vcl_cfg->accept_timeout)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured accept_timeout %f", + clib_warning ("VCL<%d>: configured accept_timeout %f", getpid (), vcl_cfg->accept_timeout); } else if (unformat (line_input, "app-proxy-transport-tcp")) { vcl_cfg->app_proxy_transport_tcp = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_proxy_transport_tcp (%d)", + clib_warning ("VCL<%d>: configured " + "app_proxy_transport_tcp (%d)", getpid (), vcl_cfg->app_proxy_transport_tcp); } else if (unformat (line_input, "app-proxy-transport-udp")) { vcl_cfg->app_proxy_transport_udp = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_proxy_transport_udp (%d)", + clib_warning ("VCL<%d>: configured " + "app_proxy_transport_udp (%d)", getpid (), vcl_cfg->app_proxy_transport_udp); } else if (unformat (line_input, "app-scope-local")) { vcl_cfg->app_scope_local = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_scope_local (%d)", + clib_warning ("VCL<%d>: configured app_scope_local (%d)", getpid (), vcl_cfg->app_scope_local); } else if (unformat (line_input, "app-scope-global")) { vcl_cfg->app_scope_global = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_scope_global (%d)", + clib_warning ("VCL<%d>: configured app_scope_global (%d)", getpid (), vcl_cfg->app_scope_global); } else if (unformat (line_input, "namespace-secret %lu", @@ -2080,7 +2131,7 @@ vppcom_cfg_read (char *conf_fname) { if (VPPCOM_DEBUG > 0) clib_warning - ("[%d] configured namespace_secret %lu (0x%lx)", + ("VCL<%d>: configured namespace_secret %lu (0x%lx)", getpid (), vcl_cfg->namespace_secret, vcl_cfg->namespace_secret); } @@ -2094,20 +2145,20 @@ vppcom_cfg_read (char *conf_fname) { _vec_len (vcl_cfg->namespace_id) = max_nsid_vec_len; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured namespace_id is too long," - " truncated to %d characters!", getpid (), - max_nsid_vec_len); + clib_warning ("VCL<%d>: configured namespace_id is " + "too long, truncated to %d characters!", + getpid (), max_nsid_vec_len); } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured namespace_id %v", + clib_warning ("VCL<%d>: configured namespace_id %v", getpid (), vcl_cfg->namespace_id); } else if (unformat (line_input, "}")) { vc_cfg_input = 0; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] completed parsing vppcom config!", + clib_warning ("VCL<%d>: completed parsing vppcom config!", getpid ()); goto input_done; } @@ -2115,7 +2166,7 @@ vppcom_cfg_read (char *conf_fname) { if (line_input->buffer[line_input->index] != '#') { - clib_warning ("[%d] Unknown vppcom config option: '%s'", + clib_warning ("VCL<%d>: Unknown vppcom config option: '%s'", getpid (), (char *) &line_input->buffer[line_input->index]); } @@ -2154,14 +2205,14 @@ vppcom_app_create (char *app_name) { u32 tmp; if (sscanf (env_var_str, "%u", &tmp) != 1) - clib_warning ("[%d] Invalid debug level specified in " + clib_warning ("VCL<%d>: Invalid debug level specified in " "the environment variable " VPPCOM_ENV_DEBUG " (%s)!\n", getpid (), env_var_str); else { vcm->debug = tmp; - clib_warning ("[%d] configured debug level (%u) from " + clib_warning ("VCL<%d>: configured VCL debug level (%u) from " VPPCOM_ENV_DEBUG "!", getpid (), vcm->debug); } } @@ -2170,7 +2221,7 @@ vppcom_app_create (char *app_name) { conf_fname = VPPCOM_CONF_DEFAULT; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] getenv '%s' failed!", getpid (), + clib_warning ("VCL<%d>: getenv '%s' failed!", getpid (), VPPCOM_ENV_CONF); } vppcom_cfg_heapsize (conf_fname); @@ -2187,7 +2238,7 @@ vppcom_app_create (char *app_name) clib_memcpy (vcm->cfg.namespace_id, env_var_str, ns_id_vec_len); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured namespace_id (%v) from " + clib_warning ("VCL<%d>: configured namespace_id (%v) from " VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (), vcm->cfg.namespace_id); } @@ -2196,7 +2247,7 @@ vppcom_app_create (char *app_name) { u64 tmp; if (sscanf (env_var_str, "%lu", &tmp) != 1) - clib_warning ("[%d] Invalid namespace secret specified in " + clib_warning ("VCL<%d>: Invalid namespace secret specified in " "the environment variable " VPPCOM_ENV_APP_NAMESPACE_SECRET " (%s)!\n", getpid (), env_var_str); @@ -2204,32 +2255,32 @@ vppcom_app_create (char *app_name) { vcm->cfg.namespace_secret = tmp; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured namespace secret (%lu) from " - VPPCOM_ENV_APP_NAMESPACE_ID "!", getpid (), - vcm->cfg.namespace_secret); + clib_warning ("VCL<%d>: configured namespace secret " + "(%lu) from " VPPCOM_ENV_APP_NAMESPACE_ID "!", + getpid (), vcm->cfg.namespace_secret); } } if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP)) { vcm->cfg.app_proxy_transport_tcp = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_proxy_transport_tcp (%u) from " - VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP "!", getpid (), - vcm->cfg.app_proxy_transport_tcp); + clib_warning ("VCL<%d>: configured app_proxy_transport_tcp " + "(%u) from " VPPCOM_ENV_APP_PROXY_TRANSPORT_TCP + "!", getpid (), vcm->cfg.app_proxy_transport_tcp); } if (getenv (VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP)) { vcm->cfg.app_proxy_transport_udp = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_proxy_transport_udp (%u) from " - VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP "!", getpid (), - vcm->cfg.app_proxy_transport_udp); + clib_warning ("VCL<%d>: configured app_proxy_transport_udp " + "(%u) from " VPPCOM_ENV_APP_PROXY_TRANSPORT_UDP + "!", getpid (), vcm->cfg.app_proxy_transport_udp); } if (getenv (VPPCOM_ENV_APP_SCOPE_LOCAL)) { vcm->cfg.app_scope_local = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_scope_local (%u) from " + clib_warning ("VCL<%d>: configured app_scope_local (%u) from " VPPCOM_ENV_APP_SCOPE_LOCAL "!", getpid (), vcm->cfg.app_scope_local); } @@ -2237,7 +2288,7 @@ vppcom_app_create (char *app_name) { vcm->cfg.app_scope_global = 1; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] configured app_scope_global (%u) from " + clib_warning ("VCL<%d>: configured app_scope_global (%u) from " VPPCOM_ENV_APP_SCOPE_GLOBAL "!", getpid (), vcm->cfg.app_scope_global); } @@ -2256,42 +2307,44 @@ vppcom_app_create (char *app_name) svm_fifo_segment_init (vcl_cfg->segment_baseva, 20 /* timeout in secs */ ); clib_spinlock_init (&vcm->sessions_lockp); - vppcom_api_hookup (); } if (vcm->my_client_index == ~0) { + vppcom_api_hookup (); vcm->app_state = STATE_APP_START; rv = vppcom_connect_to_vpp (app_name); if (rv) { - clib_warning ("[%d] ERROR: couldn't connect to VPP!", getpid ()); + clib_warning ("VCL<%d>: ERROR: couldn't connect to VPP!", + getpid ()); return rv; } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sending session enable", getpid ()); + clib_warning ("VCL<%d>: sending session enable", getpid ()); rv = vppcom_app_session_enable (); if (rv) { - clib_warning ("[%d] ERROR: vppcom_app_session_enable() failed!", - getpid ()); + clib_warning ("VCL<%d>: ERROR: vppcom_app_session_enable() " + "failed!", getpid ()); return rv; } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sending app attach", getpid ()); + clib_warning ("VCL<%d>: sending app attach", getpid ()); rv = vppcom_app_attach (); if (rv) { - clib_warning ("[%d] ERROR: vppcom_app_attach() failed!", getpid ()); + clib_warning ("VCL<%d>: ERROR: vppcom_app_attach() failed!", + getpid ()); return rv; } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] app_name '%s', my_client_index %d (0x%x)", + clib_warning ("VCL<%d>: app_name '%s', my_client_index %d (0x%x)", getpid (), app_name, vcm->my_client_index, vcm->my_client_index); } @@ -2308,7 +2361,7 @@ vppcom_app_destroy (void) return; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] detaching from VPP, my_client_index %d (0x%x)", + clib_warning ("VCL<%d>: detaching from VPP, my_client_index %d (0x%x)", getpid (), vcm->my_client_index, vcm->my_client_index); if (VPPCOM_DEBUG > 0) @@ -2334,7 +2387,8 @@ vppcom_app_destroy (void) if (PREDICT_FALSE (rv)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] application detach timed out! returning %d (%s)", + clib_warning ("VCL<%d>: application detach timed out! " + "returning %d (%s)", getpid (), rv, vppcom_retval_str (rv)); } @@ -2366,7 +2420,7 @@ vppcom_session_create (u32 vrf, u8 proto, u8 is_nonblocking) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sid %u", getpid (), session_index); + clib_warning ("VCL<%d>: sid %u", getpid (), session_index); if (VPPCOM_DEBUG > 0) { @@ -2425,10 +2479,12 @@ vppcom_session_close (uint32_t session_index) if (VPPCOM_DEBUG > 0) { if (is_vep) - clib_warning ("[%d] vep_idx %u / sid %u: closing epoll session...", + clib_warning ("VCL<%d>: vep_idx %u / sid %u: " + "closing epoll session...", getpid (), session_index, session_index); else - clib_warning ("[%d] vpp handle 0x%llx, sid %d: closing session...", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %d: " + "closing session...", getpid (), vpp_handle, session_index); } @@ -2438,9 +2494,9 @@ vppcom_session_close (uint32_t session_index) { rv = vppcom_epoll_ctl (session_index, EPOLL_CTL_DEL, next_sid, 0); if ((VPPCOM_DEBUG > 0) && PREDICT_FALSE (rv < 0)) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL " - "vep_idx %u failed! rv %d (%s)", getpid (), - vpp_handle, next_sid, vep_idx, + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " + "EPOLL_CTL_DEL vep_idx %u failed! rv %d (%s)", + getpid (), vpp_handle, next_sid, vep_idx, rv, vppcom_retval_str (rv)); VCL_LOCK_AND_GET_SESSION (session_index, &session); @@ -2454,8 +2510,8 @@ vppcom_session_close (uint32_t session_index) { rv = vppcom_epoll_ctl (vep_idx, EPOLL_CTL_DEL, session_index, 0); if ((VPPCOM_DEBUG > 0) && (rv < 0)) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: EPOLL_CTL_DEL " - "vep_idx %u failed! rv %d (%s)", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " + "EPOLL_CTL_DEL vep_idx %u failed! rv %d (%s)", getpid (), vpp_handle, session_index, vep_idx, rv, vppcom_retval_str (rv)); } @@ -2468,7 +2524,7 @@ vppcom_session_close (uint32_t session_index) if (PREDICT_FALSE (rv < 0)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "listener unbind failed! rv %d (%s)", getpid (), vpp_handle, session_index, rv, vppcom_retval_str (rv)); @@ -2480,7 +2536,7 @@ vppcom_session_close (uint32_t session_index) { rv = vppcom_session_disconnect (session_index); if (PREDICT_FALSE (rv < 0)) - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "session disconnect failed! rv %d (%s)", getpid (), vpp_handle, session_index, rv, vppcom_retval_str (rv)); @@ -2501,10 +2557,10 @@ vppcom_session_close (uint32_t session_index) if (VPPCOM_DEBUG > 0) { if (is_vep) - clib_warning ("[%d] vep_idx %u / sid %u: epoll session removed.", + clib_warning ("VCL<%d>: vep_idx %u / sid %u: epoll session removed.", getpid (), session_index, session_index); else - clib_warning ("[%d] vpp handle 0x%llx, sid %u: session removed.", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session removed.", getpid (), vpp_handle, session_index); } done: @@ -2545,8 +2601,8 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) if (session->is_vep) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: sid %u: cannot bind to an epoll session!", - getpid (), session_index); + clib_warning ("VCL<%d>: ERROR: sid %u: cannot " + "bind to an epoll session!", getpid (), session_index); rv = VPPCOM_EBADFD; goto done; } @@ -2557,7 +2613,7 @@ vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep) session->lcl_port = ep->port; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] sid %u: binding to local %s address %U " + clib_warning ("VCL<%d>: sid %u: binding to local %s address %U " "port %u, proto %s", getpid (), session_index, session->lcl_addr.is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &session->lcl_addr.ip46, @@ -2612,7 +2668,7 @@ vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) if (listen_session->is_vep) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: sid %u: cannot listen on an " + clib_warning ("VCL<%d>: ERROR: sid %u: cannot listen on an " "epoll session!", getpid (), listen_session_index); rv = VPPCOM_EBADFD; goto done; @@ -2623,7 +2679,7 @@ vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "already in listen state!", getpid (), listen_vpp_handle, listen_session_index); rv = VPPCOM_OK; @@ -2631,7 +2687,8 @@ vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: sending bind request...", + clib_warning ("VCL<%d>: vpp handle 0x%llx, " + "sid %u: sending bind request...", getpid (), listen_vpp_handle, listen_session_index); vppcom_send_bind_sock (listen_session, listen_session_index); @@ -2644,7 +2701,7 @@ vppcom_session_listen (uint32_t listen_session_index, uint32_t q_len) if (PREDICT_FALSE (retval)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: bind failed! " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: bind failed! " "returning %d (%s)", getpid (), listen_session->vpp_handle, listen_session_index, retval, vppcom_retval_str (retval)); @@ -2661,7 +2718,7 @@ done: int vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, - uint32_t flags, double wait_for_time) + uint32_t flags) { session_t *listen_session = 0; session_t *client_session = 0; @@ -2676,7 +2733,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, if (listen_session->is_vep) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: sid %u: cannot accept on an " + clib_warning ("VCL<%d>: ERROR: sid %u: cannot accept on an " "epoll session!", getpid (), listen_session_index); rv = VPPCOM_EBADFD; goto done; @@ -2685,7 +2742,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, listen_vpp_handle = listen_session->vpp_handle; if (listen_session->state != STATE_LISTEN) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "not in listen state! state 0x%x (%s)", getpid (), listen_vpp_handle, listen_session_index, listen_session->state, @@ -2694,8 +2751,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, rv = VPPCOM_EBADFD; goto done; } - wait_for = ((listen_session->is_nonblocking) ? 0 : - (wait_for_time < 0) ? vcm->cfg.accept_timeout : wait_for_time); + wait_for = (listen_session->is_nonblocking) ? 0 : vcm->cfg.accept_timeout; clib_spinlock_unlock (&vcm->sessions_lockp); @@ -2705,11 +2761,11 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, if (rv) { if ((VPPCOM_DEBUG > 0)) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: accept failed! " - "returning %d (%s)", getpid (), + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " + "accept failed! returning %d (%s)", getpid (), listen_vpp_handle, listen_session_index, rv, vppcom_retval_str (rv)); - if ((wait_for == 0) || (wait_for_time > 0)) + if (wait_for == 0) goto done; } else @@ -2722,7 +2778,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, if (PREDICT_FALSE (rv)) { rv = VPPCOM_ECONNABORTED; - clib_warning ("[%d] vpp handle 0x%llx, sid %u: client sid %u " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: client sid %u " "lookup failed! returning %d (%s)", getpid (), listen_vpp_handle, listen_session_index, client_session_index, rv, vppcom_retval_str (rv)); @@ -2731,22 +2787,25 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, client_session->is_nonblocking = (flags & O_NONBLOCK) ? 1 : 0; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: Got a client request! " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: Got a client request! " "vpp handle 0x%llx, sid %u, flags %d, is_nonblocking %u", getpid (), listen_vpp_handle, listen_session_index, client_session->vpp_handle, client_session_index, flags, client_session->is_nonblocking); - ep->vrf = client_session->vrf; - ep->is_cut_thru = client_session->is_cut_thru; - ep->is_ip4 = client_session->peer_addr.is_ip4; - ep->port = client_session->peer_port; - if (client_session->peer_addr.is_ip4) - clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4, - sizeof (ip4_address_t)); - else - clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6, - sizeof (ip6_address_t)); + if (ep) + { + ep->vrf = client_session->vrf; + ep->is_cut_thru = client_session->is_cut_thru; + ep->is_ip4 = client_session->peer_addr.is_ip4; + ep->port = client_session->peer_port; + if (client_session->peer_addr.is_ip4) + clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip4, + sizeof (ip4_address_t)); + else + clib_memcpy (ep->ip, &client_session->peer_addr.ip46.ip6, + sizeof (ip6_address_t)); + } if (client_session->is_server && client_session->is_cut_thru) { @@ -2769,7 +2828,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, rv = svm_fifo_segment_create (a); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "client sid %u svm_fifo_segment_create ('%s') " "failed! rv %d", getpid (), listen_vpp_handle, listen_session_index, client_session_index, @@ -2797,7 +2856,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, if (PREDICT_FALSE (!client_session->server_rx_fifo)) { svm_fifo_segment_delete (seg); - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "client sid %u rx fifo alloc failed! " "size %ld (0x%lx)", getpid (), listen_vpp_handle, listen_session_index, client_session_index, @@ -2821,7 +2880,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, if (PREDICT_FALSE (!client_session->server_tx_fifo)) { svm_fifo_segment_delete (seg); - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "client sid %u tx fifo alloc failed! " "size %ld (0x%lx)", getpid (), listen_vpp_handle, listen_session_index, client_session_index, @@ -2840,7 +2899,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, client_session_index; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: client sid %u " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: client sid %u " "created segment '%s', rx_fifo %p, tx_fifo %p", getpid (), listen_vpp_handle, listen_session_index, client_session_index, client_session->segment_name, @@ -2877,7 +2936,7 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, } if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: accepted vpp handle " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: accepted vpp handle " "0x%llx, sid %u%sconnection to local %s address " "%U port %u", getpid (), listen_vpp_handle, listen_session_index, client_session->vpp_handle, @@ -2956,8 +3015,8 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) if (PREDICT_FALSE (session->is_vep)) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: sid %u: cannot connect on an epoll session!", - getpid (), session_index); + clib_warning ("VCL<%d>: ERROR: sid %u: cannot " + "connect on an epoll session!", getpid (), session_index); rv = VPPCOM_EBADFD; goto done; } @@ -2966,7 +3025,7 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) if (PREDICT_FALSE (session->is_server)) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: is in use " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: is in use " "as a server session!", getpid (), vpp_handle, session_index); rv = VPPCOM_EBADFD; @@ -2976,7 +3035,7 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) if (PREDICT_FALSE (session->state & CLIENT_STATE_OPEN)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: session already " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: session already " "connected to %s %U port %d proto %s, state 0x%x (%s)", getpid (), vpp_handle, session_index, session->peer_addr.is_ip4 ? "IPv4" : "IPv6", @@ -2996,7 +3055,7 @@ vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep) session->peer_port = server_ep->port; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: connecting to server " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connecting to server " "%s %U port %d proto %s", getpid (), vpp_handle, session_index, session->peer_addr.is_ip4 ? "IPv4" : "IPv6", @@ -3021,12 +3080,12 @@ done: { rv = retval; if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: connect failed! " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connect failed! " "returning %d (%s)", getpid (), vpp_handle, session_index, rv, vppcom_retval_str (rv)); } else if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: connected!", + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: connected!", getpid (), vpp_handle, session_index); return rv; @@ -3054,8 +3113,8 @@ vppcom_session_read_internal (uint32_t session_index, void *buf, int n, if (PREDICT_FALSE (session->is_vep)) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: sid %u: cannot read from an epoll session!", - getpid (), session_index); + clib_warning ("VCL<%d>: ERROR: sid %u: cannot " + "read from an epoll session!", getpid (), session_index); rv = VPPCOM_EBADFD; goto done; } @@ -3071,7 +3130,7 @@ vppcom_session_read_internal (uint32_t session_index, void *buf, int n, VPPCOM_ECONNRESET : VPPCOM_ENOTCONN); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: %s session is " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: %s session is " "not open! state 0x%x (%s), returning %d (%s)", getpid (), vpp_handle, session_index, is_server ? "server" : "client", state, @@ -3111,7 +3170,7 @@ vppcom_session_read_internal (uint32_t session_index, void *buf, int n, if (VPPCOM_DEBUG > 1) { - clib_warning ("[%d] vpp handle 0x%llx, sid %u: Empty fifo " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: Empty fifo " "with %s session state 0x%x (%s)!" " Setting state to 0x%x (%s), returning %d (%s)", getpid (), vpp_handle, session_index, @@ -3134,11 +3193,11 @@ vppcom_session_read_internal (uint32_t session_index, void *buf, int n, if (VPPCOM_DEBUG > 2) { if (rv > 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: read %d bytes " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: read %d bytes " "from %s (%p)", getpid (), vpp_handle, session_index, n_read, fifo_str, rx_fifo); else - clib_warning ("[%d] vpp handle 0x%llx, sid %u: nothing read! " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: nothing read! " "returning %d (%s)", getpid (), vpp_handle, session_index, rv, vppcom_retval_str (rv)); } @@ -3147,7 +3206,7 @@ done: } int -vppcom_session_read (uint32_t session_index, void *buf, int n) +vppcom_session_read (uint32_t session_index, void *buf, size_t n) { return (vppcom_session_read_internal (session_index, buf, n, 0)); } @@ -3172,7 +3231,7 @@ vppcom_session_read_ready (session_t * session, u32 session_index) /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ if (PREDICT_FALSE (session->is_vep)) { - clib_warning ("[%d] ERROR: sid %u: cannot read from an " + clib_warning ("VCL<%d>: ERROR: sid %u: cannot read from an " "epoll session!", getpid (), session_index); rv = VPPCOM_EBADFD; goto done; @@ -3188,7 +3247,7 @@ vppcom_session_read_ready (session_t * session, u32 session_index) VPPCOM_ENOTCONN); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: %s session is " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: %s session is " "not open! state 0x%x (%s), returning %d (%s)", getpid (), vpp_handle, session_index, is_server ? "server" : "client", @@ -3217,7 +3276,8 @@ vppcom_session_read_ready (session_t * session, u32 session_index) if (VPPCOM_DEBUG > 1) { - clib_warning ("[%d] vpp handle 0x%llx, sid %u: Empty fifo with" + clib_warning ("VCL<%d>: vpp handle 0x%llx, " + "sid %u: Empty fifo with" " %s session state 0x%x (%s)! Setting state to " "0x%x (%s), returning %d (%s)", getpid (), session_index, vpp_handle, @@ -3243,13 +3303,12 @@ vppcom_session_read_ready (session_t * session, u32 session_index) pthread_mutex_unlock (&vcm->app_event_queue->mutex); } - done: return rv; } int -vppcom_session_write (uint32_t session_index, void *buf, int n) +vppcom_session_write (uint32_t session_index, void *buf, size_t n) { session_t *session = 0; svm_fifo_t *tx_fifo; @@ -3270,7 +3329,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) if (PREDICT_FALSE (session->is_vep)) { clib_spinlock_unlock (&vcm->sessions_lockp); - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "cannot write to an epoll session!", getpid (), session->vpp_handle, session_index); @@ -3289,7 +3348,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "%s session is not open! state 0x%x (%s)", getpid (), vpp_handle, session_index, is_server ? "server" : "client", state, @@ -3305,7 +3364,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) do { - n_write = svm_fifo_enqueue_nowait (tx_fifo, n, buf); + n_write = svm_fifo_enqueue_nowait (tx_fifo, n, (void *) buf); } while (!is_nonblocking && (n_write <= 0)); @@ -3322,7 +3381,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ ); clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "added FIFO_EVENT_APP_TX to " "vpp_event_q %p, n_write %d", getpid (), vpp_handle, session_index, q, n_write); @@ -3344,7 +3403,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) if (VPPCOM_DEBUG > 1) { - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "Empty fifo with %s session state 0x%x (%s)!" " Setting state to 0x%x (%s), returning %d (%s)", getpid (), vpp_handle, session_index, @@ -3367,11 +3426,11 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) if (VPPCOM_DEBUG > 2) { if (n_write <= 0) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "FIFO-FULL %s (%p)", getpid (), vpp_handle, session_index, fifo_str, tx_fifo); else - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "wrote %d bytes to %s (%p)", getpid (), vpp_handle, session_index, n_write, fifo_str, tx_fifo); } @@ -3393,7 +3452,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) /* Assumes caller has acquired spinlock: vcm->sessions_lockp */ if (PREDICT_FALSE (session->is_vep)) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "cannot write to an epoll session!", getpid (), session->vpp_handle, session_index); rv = VPPCOM_EBADFD; @@ -3402,7 +3461,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) if (PREDICT_FALSE (session->is_listen)) { - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "cannot write to a listen session!", getpid (), session->vpp_handle, session_index); rv = VPPCOM_EBADFD; @@ -3416,7 +3475,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) rv = ((state == STATE_DISCONNECT) ? VPPCOM_ECONNRESET : VPPCOM_ENOTCONN); - clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: ERROR: vpp handle 0x%llx, sid %u: " "%s session is not open! state 0x%x (%s), " "returning %d (%s)", getpid (), session->vpp_handle, session_index, is_server ? "server" : "client", @@ -3433,7 +3492,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) ready = svm_fifo_max_enqueue (tx_fifo); if (VPPCOM_DEBUG > 3) - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "peek %s (%p), ready = %d", getpid (), session->vpp_handle, session_index, fifo_str, tx_fifo, ready); @@ -3452,7 +3511,7 @@ vppcom_session_write_ready (session_t * session, u32 session_index) if (VPPCOM_DEBUG > 1) { - clib_warning ("[%d] vpp handle 0x%llx, sid %u: " + clib_warning ("VCL<%d>: vpp handle 0x%llx, sid %u: " "Empty fifo with %s session " "state 0x%x (%s)! Setting state to 0x%x (%s), " "returning %d (%s)", getpid (), @@ -3487,20 +3546,25 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, if (n_bits && read_map) { clib_bitmap_validate (vcm->rd_bitmap, minbits); - clib_memcpy (vcm->rd_bitmap, read_map, vec_len (vcm->rd_bitmap)); - memset (read_map, 0, vec_len (vcm->rd_bitmap)); + clib_memcpy (vcm->rd_bitmap, read_map, + vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t)); + memset (read_map, 0, vec_len (vcm->rd_bitmap) * sizeof (clib_bitmap_t)); } if (n_bits && write_map) { clib_bitmap_validate (vcm->wr_bitmap, minbits); - clib_memcpy (vcm->wr_bitmap, write_map, vec_len (vcm->wr_bitmap)); - memset (write_map, 0, vec_len (vcm->wr_bitmap)); + clib_memcpy (vcm->wr_bitmap, write_map, + vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t)); + memset (write_map, 0, + vec_len (vcm->wr_bitmap) * sizeof (clib_bitmap_t)); } if (n_bits && except_map) { clib_bitmap_validate (vcm->ex_bitmap, minbits); - clib_memcpy (vcm->ex_bitmap, except_map, vec_len (vcm->ex_bitmap)); - memset (except_map, 0, vec_len (vcm->ex_bitmap)); + clib_memcpy (vcm->ex_bitmap, except_map, + vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t)); + memset (except_map, 0, + vec_len (vcm->ex_bitmap) * sizeof (clib_bitmap_t)); } do @@ -3518,7 +3582,7 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] session %d specified in " + clib_warning ("VCL<%d>: session %d specified in " "read_map is closed.", getpid (), session_index); bits_set = VPPCOM_EBADFD; @@ -3531,13 +3595,11 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, clib_bitmap_get (vcm->ex_bitmap, session_index) && (rv < 0)) { - // TBD: clib_warning clib_bitmap_set_no_check (except_map, session_index, 1); bits_set++; } else if (rv > 0) { - // TBD: clib_warning clib_bitmap_set_no_check (read_map, session_index, 1); bits_set++; } @@ -3554,7 +3616,7 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] session %d specified in " + clib_warning ("VCL<%d>: session %d specified in " "write_map is closed.", getpid (), session_index); bits_set = VPPCOM_EBADFD; @@ -3565,7 +3627,6 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, clib_spinlock_unlock (&vcm->sessions_lockp); if (write_map && (rv > 0)) { - // TBD: clib_warning clib_bitmap_set_no_check (write_map, session_index, 1); bits_set++; } @@ -3582,7 +3643,7 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] session %d specified in " + clib_warning ("VCL<%d>: session %d specified in " "except_map is closed.", getpid (), session_index); bits_set = VPPCOM_EBADFD; @@ -3593,7 +3654,6 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, clib_spinlock_unlock (&vcm->sessions_lockp); if (rv < 0) { - // TBD: clib_warning clib_bitmap_set_no_check (except_map, session_index, 1); bits_set++; } @@ -3602,7 +3662,7 @@ vppcom_select (unsigned long n_bits, unsigned long *read_map, } /* *INDENT-ON* */ } - while (clib_time_now (&vcm->clib_time) < timeout); + while ((time_to_wait == -1) || (clib_time_now (&vcm->clib_time) < timeout)); select_done: return (bits_set); @@ -3623,17 +3683,18 @@ vep_verify_epoll_chain (u32 vep_idx) rv = vppcom_session_at_index (vep_idx, &session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", getpid (), vep_idx); + clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", + getpid (), vep_idx); goto done; } if (PREDICT_FALSE (!session->is_vep)) { - clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!", getpid (), - vep_idx); + clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!", + getpid (), vep_idx); goto done; } vep = &session->vep; - clib_warning ("[%d] vep_idx (%u): Dumping epoll chain\n" + clib_warning ("VCL<%d>: vep_idx (%u): Dumping epoll chain\n" "{\n" " is_vep = %u\n" " is_vep_session = %u\n" @@ -3649,20 +3710,21 @@ vep_verify_epoll_chain (u32 vep_idx) rv = vppcom_session_at_index (sid, &session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: Invalid sid (%u)!", getpid (), sid); + clib_warning ("VCL<%d>: ERROR: Invalid sid (%u)!", getpid (), sid); goto done; } if (PREDICT_FALSE (session->is_vep)) - clib_warning ("[%d] ERROR: sid (%u) is a vep!", getpid (), vep_idx); + clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!", + getpid (), vep_idx); else if (PREDICT_FALSE (!session->is_vep_session)) { - clib_warning ("[%d] ERROR: session (%u) is not a vep session!", - getpid (), sid); + clib_warning ("VCL<%d>: ERROR: session (%u) " + "is not a vep session!", getpid (), sid); goto done; } vep = &session->vep; if (PREDICT_FALSE (vep->vep_idx != vep_idx)) - clib_warning ("[%d] ERROR: session (%u) vep_idx (%u) != " + clib_warning ("VCL<%d>: ERROR: session (%u) vep_idx (%u) != " "vep_idx (%u)!", getpid (), sid, session->vep.vep_idx, vep_idx); if (session->is_vep_session) @@ -3685,7 +3747,8 @@ vep_verify_epoll_chain (u32 vep_idx) } done: - clib_warning ("[%d] vep_idx (%u): Dump complete!\n", getpid (), vep_idx); + clib_warning ("VCL<%d>: vep_idx (%u): Dump complete!\n", + getpid (), vep_idx); } int @@ -3708,7 +3771,7 @@ vppcom_epoll_create (void) clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] Created vep_idx %u / sid %u!", + clib_warning ("VCL<%d>: Created vep_idx %u / sid %u!", getpid (), vep_idx, vep_idx); if (VPPCOM_DEBUG > 0) @@ -3748,7 +3811,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, if (vep_idx == session_index) { - clib_warning ("[%d] ERROR: vep_idx == session_index (%u)!", + clib_warning ("VCL<%d>: ERROR: vep_idx == session_index (%u)!", getpid (), vep_idx); return VPPCOM_EINVAL; } @@ -3757,12 +3820,12 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, rv = vppcom_session_at_index (vep_idx, &vep_session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: Invalid vep_idx (%u)!", vep_idx); + clib_warning ("VCL<%d>: ERROR: Invalid vep_idx (%u)!", vep_idx); goto done; } if (PREDICT_FALSE (!vep_session->is_vep)) { - clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!", + clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!", getpid (), vep_idx); rv = VPPCOM_EINVAL; goto done; @@ -3775,7 +3838,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, if (PREDICT_FALSE (rv)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] ERROR: Invalid session_index (%u)!", + clib_warning ("VCL<%d>: ERROR: Invalid session_index (%u)!", getpid (), session_index); goto done; } @@ -3791,7 +3854,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, case EPOLL_CTL_ADD: if (PREDICT_FALSE (!event)) { - clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: NULL pointer to " + clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: NULL pointer to " "epoll_event structure!", getpid ()); rv = VPPCOM_EINVAL; goto done; @@ -3803,7 +3866,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, &next_session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: EPOLL_CTL_ADD: Invalid " + clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_ADD: Invalid " "vep.next_sid (%u) on vep_idx (%u)!", getpid (), vep_session->vep.next_sid, vep_idx); goto done; @@ -3820,29 +3883,30 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, session->is_vep_session = 1; vep_session->vep.next_sid = session_index; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] EPOLL_CTL_ADD: vep_idx %u, sid %u, events 0x%x," - " data 0x%llx!", getpid (), vep_idx, session_index, + clib_warning ("VCL<%d>: EPOLL_CTL_ADD: vep_idx %u, " + "sid %u, events 0x%x, data 0x%llx!", + getpid (), vep_idx, session_index, event->events, event->data.u64); break; case EPOLL_CTL_MOD: if (PREDICT_FALSE (!event)) { - clib_warning ("[%d] ERROR: EPOLL_CTL_MOD: NULL pointer to " + clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_MOD: NULL pointer to " "epoll_event structure!", getpid ()); rv = VPPCOM_EINVAL; goto done; } else if (PREDICT_FALSE (!session->is_vep_session)) { - clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_MOD: " + clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: " "not a vep session!", getpid (), session_index); rv = VPPCOM_EINVAL; goto done; } else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx)) { - clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_MOD: " + clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_MOD: " "vep_idx (%u) != vep_idx (%u)!", getpid (), session_index, session->vep.vep_idx, vep_idx); @@ -3852,22 +3916,23 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, session->vep.et_mask = VEP_DEFAULT_ET_MASK; session->vep.ev = *event; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x," - " data 0x%llx!", getpid (), vep_idx, session_index, - event->events, event->data.u64); + clib_warning + ("VCL<%d>: EPOLL_CTL_MOD: vep_idx %u, sid %u, events 0x%x," + " data 0x%llx!", getpid (), vep_idx, session_index, event->events, + event->data.u64); break; case EPOLL_CTL_DEL: if (PREDICT_FALSE (!session->is_vep_session)) { - clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_DEL: " + clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: " "not a vep session!", getpid (), session_index); rv = VPPCOM_EINVAL; goto done; } else if (PREDICT_FALSE (session->vep.vep_idx != vep_idx)) { - clib_warning ("[%d] ERROR: sid %u EPOLL_CTL_DEL: " + clib_warning ("VCL<%d>: ERROR: sid %u EPOLL_CTL_DEL: " "vep_idx (%u) != vep_idx (%u)!", getpid (), session_index, session->vep.vep_idx, vep_idx); @@ -3887,7 +3952,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, rv = vppcom_session_at_index (session->vep.prev_sid, &prev_session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid " + clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid " "vep.prev_sid (%u) on sid (%u)!", getpid (), session->vep.prev_sid, session_index); goto done; @@ -3901,7 +3966,7 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, rv = vppcom_session_at_index (session->vep.next_sid, &next_session); if (PREDICT_FALSE (rv)) { - clib_warning ("[%d] ERROR: EPOLL_CTL_DEL: Invalid " + clib_warning ("VCL<%d>: ERROR: EPOLL_CTL_DEL: Invalid " "vep.next_sid (%u) on sid (%u)!", getpid (), session->vep.next_sid, session_index); goto done; @@ -3916,12 +3981,12 @@ vppcom_epoll_ctl (uint32_t vep_idx, int op, uint32_t session_index, session->vep.vep_idx = ~0; session->is_vep_session = 0; if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] EPOLL_CTL_DEL: vep_idx %u, sid %u!", + clib_warning ("VCL<%d>: EPOLL_CTL_DEL: vep_idx %u, sid %u!", getpid (), vep_idx, session_index); break; default: - clib_warning ("[%d] ERROR: Invalid operation (%d)!", getpid (), op); + clib_warning ("VCL<%d>: ERROR: Invalid operation (%d)!", getpid (), op); rv = VPPCOM_EINVAL; } @@ -3946,7 +4011,7 @@ vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events, if (PREDICT_FALSE (maxevents <= 0)) { - clib_warning ("[%d] ERROR: Invalid maxevents (%d)!", + clib_warning ("VCL<%d>: ERROR: Invalid maxevents (%d)!", getpid (), maxevents); return VPPCOM_EINVAL; } @@ -3960,7 +4025,7 @@ vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events, if (PREDICT_FALSE (!is_vep)) { - clib_warning ("[%d] ERROR: vep_idx (%u) is not a vep!", + clib_warning ("VCL<%d>: ERROR: vep_idx (%u) is not a vep!", getpid (), vep_idx); rv = VPPCOM_EINVAL; goto done; @@ -3968,7 +4033,7 @@ vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events, if (PREDICT_FALSE (vep_next_sid == ~0)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] WARNING: vep_idx (%u) is empty!", + clib_warning ("VCL<%d>: WARNING: vep_idx (%u) is empty!", getpid (), vep_idx); goto done; } @@ -4000,7 +4065,7 @@ vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events, if (PREDICT_FALSE (is_vep)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] ERROR: sid (%u) is a vep!", + clib_warning ("VCL<%d>: ERROR: sid (%u) is a vep!", getpid (), vep_idx); rv = VPPCOM_EINVAL; goto done; @@ -4008,14 +4073,14 @@ vppcom_epoll_wait (uint32_t vep_idx, struct epoll_event *events, if (PREDICT_FALSE (!is_vep_session)) { if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] ERROR: session (%u) is not " + clib_warning ("VCL<%d>: ERROR: session (%u) is not " "a vep session!", getpid (), sid); rv = VPPCOM_EINVAL; goto done; } if (PREDICT_FALSE (session_vep_idx != vep_idx)) { - clib_warning ("[%d] ERROR: session (%u) " + clib_warning ("VCL<%d>: ERROR: session (%u) " "vep_idx (%u) != vep_idx (%u)!", getpid (), sid, session->vep.vep_idx, vep_idx); rv = VPPCOM_EINVAL; @@ -4138,24 +4203,24 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, case VPPCOM_ATTR_GET_NREAD: rv = vppcom_session_read_ready (session, session_index); if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d", + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d", getpid (), rv); break; case VPPCOM_ATTR_GET_NWRITE: rv = vppcom_session_write_ready (session, session_index); if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d", + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d", getpid (), session_index, rv); break; case VPPCOM_ATTR_GET_FLAGS: - if (buffer && buflen && (*buflen >= sizeof (*flags))) + if (PREDICT_TRUE (buffer && buflen && (*buflen >= sizeof (*flags)))) { *flags = O_RDWR | ((session->is_nonblocking) ? O_NONBLOCK : 0); *buflen = sizeof (*flags); if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] VPPCOM_ATTR_GET_FLAGS: sid %u, " + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_FLAGS: sid %u, " "flags = 0x%08x, is_nonblocking = %u", getpid (), session_index, *flags, session->is_nonblocking); } @@ -4164,11 +4229,11 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, break; case VPPCOM_ATTR_SET_FLAGS: - if (buffer && buflen && (*buflen >= sizeof (*flags))) + if (PREDICT_TRUE (buffer && buflen && (*buflen == sizeof (*flags)))) { session->is_nonblocking = (*flags & O_NONBLOCK) ? 1 : 0; if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] VPPCOM_ATTR_SET_FLAGS: sid %u, " + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_FLAGS: sid %u, " "flags = 0x%08x, is_nonblocking = %u", getpid (), session_index, *flags, session->is_nonblocking); @@ -4178,7 +4243,8 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, break; case VPPCOM_ATTR_GET_PEER_ADDR: - if (buffer && buflen && (*buflen >= sizeof (*ep)) && ep->ip) + if (PREDICT_TRUE (buffer && buflen && + (*buflen >= sizeof (*ep)) && ep->ip)) { ep->vrf = session->vrf; ep->is_ip4 = session->peer_addr.is_ip4; @@ -4191,8 +4257,8 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, sizeof (ip6_address_t)); *buflen = sizeof (*ep); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = " - "%u, addr = %U, port %u", getpid (), + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_PEER_ADDR: sid %u, " + "is_ip4 = %u, addr = %U, port %u", getpid (), session_index, ep->is_ip4, format_ip46_address, &session->peer_addr.ip46, ep->is_ip4, clib_net_to_host_u16 (ep->port)); @@ -4202,7 +4268,8 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, break; case VPPCOM_ATTR_GET_LCL_ADDR: - if (buffer && buflen && (*buflen >= sizeof (*ep)) && ep->ip) + if (PREDICT_TRUE (buffer && buflen && + (*buflen >= sizeof (*ep)) && ep->ip)) { ep->vrf = session->vrf; ep->is_ip4 = session->lcl_addr.is_ip4; @@ -4215,8 +4282,8 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, sizeof (ip6_address_t)); *buflen = sizeof (*ep); if (VPPCOM_DEBUG > 1) - clib_warning ("[%d] VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = " - "%u, addr = %U port %d", getpid (), + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_LCL_ADDR: sid %u, " + "is_ip4 = %u, addr = %U port %d", getpid (), session_index, ep->is_ip4, format_ip46_address, &session->lcl_addr.ip46, ep->is_ip4, clib_net_to_host_u16 (ep->port)); @@ -4225,22 +4292,476 @@ vppcom_session_attr (uint32_t session_index, uint32_t op, rv = VPPCOM_EINVAL; break; + case VPPCOM_ATTR_GET_LIBC_EPFD: + rv = session->libc_epfd; + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_LIBC_EPFD: libc_epfd %d", + getpid (), rv); + break; + + case VPPCOM_ATTR_SET_LIBC_EPFD: + if (PREDICT_TRUE (buffer && buflen && + (*buflen == sizeof (session->libc_epfd)))) + { + session->libc_epfd = *(int *) buffer; + *buflen = sizeof (session->libc_epfd); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_LIBC_EPFD: libc_epfd %d, " + "buflen %d", getpid (), session->libc_epfd, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_PROTOCOL: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + *(int *) buffer = session->proto; + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_PROTOCOL: %d (%s), " + "buflen %d", getpid (), *(int *) buffer, + *(int *) buffer ? "UDP" : "TCP", *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_LISTEN: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_LISTEN); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_LISTEN: %d, " + "buflen %d", getpid (), *(int *) buffer, *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_ERROR: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + *(int *) buffer = 0; + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_ERROR: %d, " + "buflen %d, #VPP-TBD#", getpid (), + *(int *) buffer, *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_TX_FIFO_LEN: + if (buffer && buflen && (*buflen >= sizeof (u32))) + { + svm_fifo_t *tx_fifo; + + tx_fifo = ((!session->is_cut_thru || session->is_server) ? + session->server_tx_fifo : session->server_rx_fifo); + + /* VPP-TBD */ + *(size_t *) buffer = (session->sndbuf_size ? session->sndbuf_size : + tx_fifo ? tx_fifo->nitems : + vcm->cfg.tx_fifo_size); + *buflen = sizeof (u32); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_TX_FIFO_LEN: %u (0x%x), " + "buflen %d, #VPP-TBD#", getpid (), + *(size_t *) buffer, *(size_t *) buffer, *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_TX_FIFO_LEN: + if (buffer && buflen && (*buflen == sizeof (u32))) + { + /* VPP-TBD */ + session->sndbuf_size = *(u32 *) buffer; + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), " + "buflen %d, #VPP-TBD#", getpid (), + session->sndbuf_size, session->sndbuf_size, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_RX_FIFO_LEN: + if (buffer && buflen && (*buflen >= sizeof (u32))) + { + svm_fifo_t *rx_fifo; + + rx_fifo = ((!session->is_cut_thru || session->is_server) ? + session->server_rx_fifo : session->server_tx_fifo); + + /* VPP-TBD */ + *(size_t *) buffer = (session->rcvbuf_size ? session->rcvbuf_size : + rx_fifo ? rx_fifo->nitems : + vcm->cfg.rx_fifo_size); + *buflen = sizeof (u32); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_RX_FIFO_LEN: %u (0x%x), " + "buflen %d, #VPP-TBD#", getpid (), + *(size_t *) buffer, *(size_t *) buffer, *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_RX_FIFO_LEN: + if (buffer && buflen && (*buflen == sizeof (u32))) + { + /* VPP-TBD */ + session->rcvbuf_size = *(u32 *) buffer; + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TX_FIFO_LEN: %u (0x%x), " + "buflen %d, #VPP-TBD#", getpid (), + session->sndbuf_size, session->sndbuf_size, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_REUSEADDR: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_REUSEADDR); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_REUSEADDR: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + case VPPCOM_ATTR_SET_REUSEADDR: + if (buffer && buflen && (*buflen == sizeof (int)) && + !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN)) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEADDR); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEADDR); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_REUSEADDR: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_REUSEADDR), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_REUSEPORT: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_REUSEPORT); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_REUSEPORT: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_REUSEPORT: + if (buffer && buflen && (*buflen == sizeof (int)) && + !VCL_SESS_ATTR_TEST (session->attr, VCL_SESS_ATTR_LISTEN)) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_REUSEPORT); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_REUSEPORT); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_REUSEPORT: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_REUSEPORT), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_BROADCAST: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_BROADCAST); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_BROADCAST: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; break; case VPPCOM_ATTR_SET_BROADCAST: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_BROADCAST); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_BROADCAST); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_BROADCAST: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_BROADCAST), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_V6ONLY: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_V6ONLY); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_V6ONLY: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; break; case VPPCOM_ATTR_SET_V6ONLY: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_V6ONLY); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_V6ONLY); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_V6ONLY: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_V6ONLY), *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_KEEPALIVE: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_KEEPALIVE); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_KEEPALIVE: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; break; case VPPCOM_ATTR_SET_KEEPALIVE: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_KEEPALIVE); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_KEEPALIVE); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_KEEPALIVE: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_KEEPALIVE), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_TCP_NODELAY: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_NODELAY); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_TCP_NODELAY: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_TCP_NODELAY: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_NODELAY); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_NODELAY); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TCP_NODELAY: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_NODELAY), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_TCP_KEEPIDLE: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_KEEPIDLE); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPIDLE: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; break; case VPPCOM_ATTR_SET_TCP_KEEPIDLE: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPIDLE); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPIDLE: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_KEEPIDLE), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_TCP_KEEPINTVL: + if (buffer && buflen && (*buflen >= sizeof (int))) + { + /* VPP-TBD */ + *(int *) buffer = VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_KEEPINTVL); + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_TCP_KEEPINTVL: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; break; case VPPCOM_ATTR_SET_TCP_KEEPINTVL: + if (buffer && buflen && (*buflen == sizeof (int))) + { + /* VPP-TBD */ + if (*(int *) buffer) + VCL_SESS_ATTR_SET (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL); + else + VCL_SESS_ATTR_CLR (session->attr, VCL_SESS_ATTR_TCP_KEEPINTVL); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %d, " + "buflen %d, #VPP-TBD#", getpid (), + VCL_SESS_ATTR_TEST (session->attr, + VCL_SESS_ATTR_TCP_KEEPINTVL), + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_GET_TCP_USER_MSS: + if (buffer && buflen && (*buflen >= sizeof (u32))) + { + /* VPP-TBD */ + *(u32 *) buffer = session->user_mss; + *buflen = sizeof (int); + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_GET_TCP_USER_MSS: %d, " + "buflen %d, #VPP-TBD#", getpid (), *(int *) buffer, + *buflen); + } + else + rv = VPPCOM_EINVAL; + break; + + case VPPCOM_ATTR_SET_TCP_USER_MSS: + if (buffer && buflen && (*buflen == sizeof (u32))) + { + /* VPP-TBD */ + session->user_mss = *(u32 *) buffer; + + if (VPPCOM_DEBUG > 2) + clib_warning ("VCL<%d>: VPPCOM_ATTR_SET_TCP_KEEPINTVL: %u, " + "buflen %d, #VPP-TBD#", getpid (), + session->user_mss, *buflen); + } + else + rv = VPPCOM_EINVAL; break; default: @@ -4268,7 +4789,8 @@ vppcom_session_recvfrom (uint32_t session_index, void *buffer, { clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 0) - clib_warning ("[%d] invalid session, sid (%u) has been closed!", + clib_warning ("VCL<%d>: invalid session, " + "sid (%u) has been closed!", getpid (), session_index); rv = VPPCOM_EBADFD; clib_spinlock_unlock (&vcm->sessions_lockp); @@ -4292,7 +4814,8 @@ vppcom_session_recvfrom (uint32_t session_index, void *buffer, rv = vppcom_session_peek (session_index, buffer, buflen); else { - clib_warning ("[%d] Unsupport flags for recvfrom %d", getpid (), flags); + clib_warning ("VCL<%d>: Unsupport flags for recvfrom %d", + getpid (), flags); rv = VPPCOM_EAFNOSUPPORT; } @@ -4317,13 +4840,118 @@ vppcom_session_sendto (uint32_t session_index, void *buffer, { // TBD check the flags and do the right thing if (VPPCOM_DEBUG > 2) - clib_warning ("[%d] handling flags 0x%u (%d) not implemented yet.", - getpid (), flags, flags); + clib_warning ("VCL<%d>: handling flags 0x%u (%d) " + "not implemented yet.", getpid (), flags, flags); } return (vppcom_session_write (session_index, buffer, buflen)); } +int +vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, double wait_for_time) +{ + f64 timeout = clib_time_now (&vcm->clib_time) + wait_for_time; + u32 i, keep_trying = 1; + int rv, num_ev = 0; + + if (VPPCOM_DEBUG > 3) + clib_warning ("VCL<%d>: vp %p, nsids %u, wait_for_time %f", + getpid (), vp, n_sids, wait_for_time); + + if (!vp) + return VPPCOM_EFAULT; + + do + { + session_t *session; + + for (i = 0; i < n_sids; i++) + { + ASSERT (vp[i].revents); + + VCL_LOCK_AND_GET_SESSION (vp[i].sid, &session); + clib_spinlock_unlock (&vcm->sessions_lockp); + + if (*vp[i].revents) + *vp[i].revents = 0; + + if (POLLIN & vp[i].events) + { + VCL_LOCK_AND_GET_SESSION (vp[i].sid, &session); + rv = vppcom_session_read_ready (session, vp[i].sid); + clib_spinlock_unlock (&vcm->sessions_lockp); + if (rv > 0) + { + *vp[i].revents |= POLLIN; + num_ev++; + } + else if (rv < 0) + { + switch (rv) + { + case VPPCOM_ECONNRESET: + *vp[i].revents = POLLHUP; + break; + + default: + *vp[i].revents = POLLERR; + break; + } + num_ev++; + } + } + + if (POLLOUT & vp[i].events) + { + VCL_LOCK_AND_GET_SESSION (vp[i].sid, &session); + rv = vppcom_session_write_ready (session, vp[i].sid); + clib_spinlock_unlock (&vcm->sessions_lockp); + if (rv > 0) + { + *vp[i].revents |= POLLOUT; + num_ev++; + } + else if (rv < 0) + { + switch (rv) + { + case VPPCOM_ECONNRESET: + *vp[i].revents = POLLHUP; + break; + + default: + *vp[i].revents = POLLERR; + break; + } + num_ev++; + } + } + + if (0) + { + done: + *vp[i].revents = POLLNVAL; + num_ev++; + } + } + if (wait_for_time != -1) + keep_trying = (clib_time_now (&vcm->clib_time) <= timeout) ? 1 : 0; + } + while ((num_ev == 0) && keep_trying); + + if (VPPCOM_DEBUG > 3) + { + clib_warning ("VCL<%d>: returning %d", getpid (), num_ev); + for (i = 0; i < n_sids; i++) + { + clib_warning ("VCL<%d>: vp[%d].sid %d (0x%x), .events 0x%x, " + ".revents 0x%x", getpid (), i, vp[i].sid, vp[i].sid, + vp[i].events, *vp[i].revents); + } + } + return num_ev; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vcl/vppcom.h b/src/vcl/vppcom.h index 5511f046515..208b3717d03 100644 --- a/src/vcl/vppcom.h +++ b/src/vcl/vppcom.h @@ -18,6 +18,7 @@ #include #include +#include #include /* @@ -41,6 +42,26 @@ typedef enum VPPCOM_PROTO_UDP, } vppcom_proto_t; +static inline char * +vppcom_proto_str (vppcom_proto_t proto) +{ + char *proto_str; + + switch (proto) + { + case VPPCOM_PROTO_TCP: + proto_str = "VPPCOM_PROTO_TCP"; + break; + case VPPCOM_PROTO_UDP: + proto_str = "VPPCOM_PROTO_UDP"; + break; + default: + proto_str = "UNKNOWN"; + break; + } + return proto_str; +} + typedef enum { VPPCOM_IS_IP6 = 0, @@ -60,6 +81,7 @@ typedef enum { VPPCOM_OK = 0, VPPCOM_EAGAIN = -EAGAIN, + VPPCOM_EFAULT = -EFAULT, VPPCOM_ENOMEM = -ENOMEM, VPPCOM_EINVAL = -EINVAL, VPPCOM_EBADFD = -EBADFD, @@ -79,14 +101,43 @@ typedef enum VPPCOM_ATTR_SET_FLAGS, VPPCOM_ATTR_GET_LCL_ADDR, VPPCOM_ATTR_GET_PEER_ADDR, + VPPCOM_ATTR_GET_LIBC_EPFD, + VPPCOM_ATTR_SET_LIBC_EPFD, + VPPCOM_ATTR_GET_PROTOCOL, + VPPCOM_ATTR_GET_LISTEN, + VPPCOM_ATTR_GET_ERROR, + VPPCOM_ATTR_GET_TX_FIFO_LEN, + VPPCOM_ATTR_SET_TX_FIFO_LEN, + VPPCOM_ATTR_GET_RX_FIFO_LEN, + VPPCOM_ATTR_SET_RX_FIFO_LEN, + VPPCOM_ATTR_GET_REUSEADDR, VPPCOM_ATTR_SET_REUSEADDR, + VPPCOM_ATTR_GET_REUSEPORT, + VPPCOM_ATTR_SET_REUSEPORT, + VPPCOM_ATTR_GET_BROADCAST, VPPCOM_ATTR_SET_BROADCAST, + VPPCOM_ATTR_GET_V6ONLY, VPPCOM_ATTR_SET_V6ONLY, + VPPCOM_ATTR_GET_KEEPALIVE, VPPCOM_ATTR_SET_KEEPALIVE, + VPPCOM_ATTR_GET_TCP_NODELAY, + VPPCOM_ATTR_SET_TCP_NODELAY, + VPPCOM_ATTR_GET_TCP_KEEPIDLE, VPPCOM_ATTR_SET_TCP_KEEPIDLE, + VPPCOM_ATTR_GET_TCP_KEEPINTVL, VPPCOM_ATTR_SET_TCP_KEEPINTVL, + VPPCOM_ATTR_GET_TCP_USER_MSS, + VPPCOM_ATTR_SET_TCP_USER_MSS, } vppcom_attr_op_t; +typedef struct _vcl_poll +{ + uint32_t fds_ndx; + uint32_t sid; + short events; + short *revents; +} vcl_poll_t; + /* * VPPCOM Public API Functions */ @@ -105,6 +156,10 @@ vppcom_retval_str (int retval) st = "VPPCOM_EAGAIN"; break; + case VPPCOM_EFAULT: + st = "VPPCOM_EFAULT"; + break; + case VPPCOM_ENOMEM: st = "VPPCOM_ENOMEM"; break; @@ -160,13 +215,12 @@ extern int vppcom_session_close (uint32_t session_index); extern int vppcom_session_bind (uint32_t session_index, vppcom_endpt_t * ep); extern int vppcom_session_listen (uint32_t session_index, uint32_t q_len); extern int vppcom_session_accept (uint32_t session_index, - vppcom_endpt_t * client_ep, - uint32_t flags, double wait_for_time); + vppcom_endpt_t * client_ep, uint32_t flags); extern int vppcom_session_connect (uint32_t session_index, vppcom_endpt_t * server_ep); -extern int vppcom_session_read (uint32_t session_index, void *buf, int n); -extern int vppcom_session_write (uint32_t session_index, void *buf, int n); +extern int vppcom_session_read (uint32_t session_index, void *buf, size_t n); +extern int vppcom_session_write (uint32_t session_index, void *buf, size_t n); extern int vppcom_select (unsigned long n_bits, unsigned long *read_map, @@ -187,6 +241,8 @@ extern int vppcom_session_recvfrom (uint32_t session_index, void *buffer, extern int vppcom_session_sendto (uint32_t session_index, void *buffer, uint32_t buflen, int flags, vppcom_endpt_t * ep); +extern int vppcom_poll (vcl_poll_t * vp, uint32_t n_sids, + double wait_for_time); #endif /* included_vppcom_h */ diff --git a/test/scripts/socket_test.sh b/test/scripts/socket_test.sh index 862c949b6e8..609fc62ab2a 100755 --- a/test/scripts/socket_test.sh +++ b/test/scripts/socket_test.sh @@ -523,6 +523,15 @@ write_script_header() { if [ -n "$VCL_DEBUG" ] ; then echo "export VCL_DEBUG=$VCL_DEBUG" >> $1 fi + if [ -n "$VCOM_DEBUG" ] ; then + echo "export VCOM_DEBUG=$VCOM_DEBUG" >> $1 + fi + if [ -n "$VCOM_APP_NAME" ] ; then + echo "export VCOM_APP_NAME=$VCOM_APP_NAME" >> $1 + fi + if [ -n "$VCOM_SID_BIT" ] ; then + echo "export VCOM_SID_BIT=$VCOM_SID_BIT" >> $1 + fi if [ -n "$namespace_id" ] ; then echo "export VCL_APP_NAMESPACE_ID=\"$namespace_id\"" >> $1 echo "export VCL_APP_NAMESPACE_SECRET=\"$namespace_secret\"" >> $1