aboutsummaryrefslogtreecommitdiffstats
path: root/src/vcl/vcl_private.c
AgeCommit message (Expand)AuthorFilesLines
2023-07-26vcl: allow rx of zero length dgramsFlorin Coras1-1/+2
2023-06-14vcl: fix debug logging of mapped segmentsFlorin Coras1-1/+1
2023-02-07vcl: drop lock on segment attach failureFlorin Coras1-0/+1
2022-03-31vcl: fix api detach if attach failedFlorin Coras1-0/+4
2022-03-02vcl: fix segment detach post api disconnectFlorin Coras1-8/+35
2022-02-17vcl: add support for reconnectFilip Tehlar1-0/+70
2021-11-30vcl: avoid ip format function vnet dependencyFlorin Coras1-0/+120
2021-09-23vcl: grab wrk create lock soonerFlorin Coras1-3/+6
2021-07-22session vcl: explit mq indices in ctrl messagesFlorin Coras1-4/+3
2021-06-29vcl: improvements to epoll ltFlorin Coras1-2/+1
2021-06-24vcl: fix vcl_session_write_ready when connectingliuyacan1-0/+4
2021-06-16vcl: fix fifo sharingFlorin Coras1-0/+20
2021-06-16vcl: fix worker cleanupFlorin Coras1-0/+7
2021-06-16vcl: basic support for epoll level-triggered evtsFlorin Coras1-0/+2
2021-05-01vcl: attr api to set endpt ext configFlorin Coras1-4/+4
2021-04-22vcl session: refactor passing of crypto contextFlorin Coras1-0/+15
2021-04-22vcl session: extended connect/listen configurationFlorin Coras1-0/+26
2021-04-15vcl: validate fs before cleanupFlorin Coras1-2/+5
2021-04-07vcl: fix worker cleanup cb functionFlorin Coras1-2/+8
2021-02-23vcl: segment index leak on attachFlorin Coras1-1/+1
2021-02-22vcl: cleanup fifos detached from segmentsFlorin Coras1-0/+31
2021-01-28svm vcl: add helper fn that discovers mqs in segmentFlorin Coras1-0/+23
2021-01-25svm: add custom q implementation for mqFlorin Coras1-1/+1
2020-12-29svm vcl: allow random offsets for fifo segments in appsFlorin Coras1-9/+5
2020-12-29svm: allow mq attachments at random offsetsFlorin Coras1-2/+42
2020-12-24svm: split fifo into private and shared structsFlorin Coras1-0/+45
2020-10-20vcl: convert vep variables into flagsFlorin Coras1-2/+2
2020-10-19vcl: cleanup read and write readyFlorin Coras1-61/+45
2020-10-15vcl: refactor session state enumFlorin Coras1-29/+32
2020-09-14vcl: add support for app socket apiFlorin Coras1-2/+20
2020-09-14vcl: cleanup bapi and wrk registrationFlorin Coras1-103/+3
2020-08-12vcl: support multi-threads with session migrationhanlin1-0/+2
2020-04-06vcl session: enforce full dgram reads/writesFlorin Coras1-0/+9
2020-04-01session udp: support connect on listenersFlorin Coras1-1/+19
2020-03-05session: API cleanupJakub Grajciar1-1/+1
2019-12-23vcl: fix multi-thread app segment attachingFlorin Coras1-32/+27
2019-12-21session: move add/del segment msg to mqFlorin Coras1-0/+41
2019-12-12vcl: fix disconnect from binary apiFlorin Coras1-0/+8
2019-12-10api: multiple connections per processDave Barach1-1/+1
2019-08-27session: move ctrl messages from bapi to mqFlorin Coras1-0/+6
2019-08-02vcl: initialize worker thread index and heap map slotFlorin Coras1-0/+3
2019-04-16svm_fifo rework to avoid contention on cursizeSirshak Das1-5/+5
2019-03-15vcl: cleanup debug messagesFlorin Coras1-7/+7
2019-03-06session: use vpp to switch io events for ct sessionsFlorin Coras1-73/+6
2019-02-04session: cleanup part 1Florin Coras1-2/+2
2019-01-29vls: multi-process and multi-threaded apps improvementsFlorin Coras1-0/+64
2019-01-18vcl: move forking logic to vlsFlorin Coras1-121/+15
2019-01-17vcl/session: replicate events for shared sessionsFlorin Coras1-0/+11
2019-01-05vcl/session: add api for changing session app workerFlorin Coras1-7/+15
2018-12-04vcl: cleanup children that use _exit()Florin Coras1-11/+14
span class="n">wait) timeout = clib_time_now (&scm->clib_time) + wait; while (1) { current_rx_index = vec_len (scm->socket_rx_buffer); while (current_rx_index < sizeof (*mbp)) { vec_validate (scm->socket_rx_buffer, current_rx_index + scm->socket_buffer_size - 1); n = read (scm->socket_fd, scm->socket_rx_buffer + current_rx_index, scm->socket_buffer_size); if (n < 0) { if (errno == EAGAIN) continue; clib_unix_warning ("socket_read"); vec_set_len (scm->socket_rx_buffer, current_rx_index); return -1; } current_rx_index += n; } vec_set_len (scm->socket_rx_buffer, current_rx_index); #if CLIB_DEBUG > 1 if (n > 0) clib_warning ("read %d bytes", n); #endif mbp = (msgbuf_t *) (scm->socket_rx_buffer); data_len = ntohl (mbp->data_len); current_rx_index = vec_len (scm->socket_rx_buffer); vec_validate (scm->socket_rx_buffer, current_rx_index + data_len); mbp = (msgbuf_t *) (scm->socket_rx_buffer); msg_size = data_len + sizeof (*mbp); while (current_rx_index < msg_size) { n = read (scm->socket_fd, scm->socket_rx_buffer + current_rx_index, msg_size - current_rx_index); if (n < 0) { if (errno == EAGAIN) continue; clib_unix_warning ("socket_read"); vec_set_len (scm->socket_rx_buffer, current_rx_index); return -1; } current_rx_index += n; } vec_set_len (scm->socket_rx_buffer, current_rx_index); if (vec_len (scm->socket_rx_buffer) >= data_len + sizeof (*mbp)) { vl_msg_api_socket_handler ((void *) (mbp->data), data_len); if (vec_len (scm->socket_rx_buffer) == data_len + sizeof (*mbp)) vec_set_len (scm->socket_rx_buffer, 0); else vec_delete (scm->socket_rx_buffer, data_len + sizeof (*mbp), 0); mbp = 0; /* Quit if we're out of data, and not expecting a ping reply */ if (vec_len (scm->socket_rx_buffer) == 0 && scm->control_pings_outstanding == 0) break; } if (wait && clib_time_now (&scm->clib_time) >= timeout) return -1; } return 0; } int vl_socket_client_read (int wait) { return vl_socket_client_read_internal (socket_client_ctx, wait); } int vl_socket_client_read2 (socket_client_main_t * scm, int wait) { socket_client_main_t *old_ctx; int rv; old_ctx = vl_socket_client_ctx_push (scm); rv = vl_socket_client_read_internal (scm, wait); vl_socket_client_ctx_pop (old_ctx); return rv; } static int vl_socket_client_write_internal (socket_client_main_t * scm) { int n; int len = vec_len (scm->socket_tx_buffer); msgbuf_t msgbuf = { .q = 0, .gc_mark_timestamp = 0, .data_len = htonl (len), }; n = write (scm->socket_fd, &msgbuf, sizeof (msgbuf)); if (n < sizeof (msgbuf)) { clib_unix_warning ("socket write (msgbuf)"); return -1; } n = write (scm->socket_fd, scm->socket_tx_buffer, len); vec_set_len (scm->socket_tx_buffer, 0); if (n < len) { clib_unix_warning ("socket write (msg)"); return -1; } return n; } int vl_socket_client_write (void) { return vl_socket_client_write_internal (socket_client_ctx); } int vl_socket_client_write2 (socket_client_main_t * scm) { socket_client_main_t *old_ctx; int rv; old_ctx = vl_socket_client_ctx_push (scm); rv = vl_socket_client_write_internal (scm); vl_socket_client_ctx_pop (old_ctx); return rv; } void * vl_socket_client_msg_alloc2 (socket_client_main_t * scm, int nbytes) { vec_set_len (scm->socket_tx_buffer, nbytes); return ((void *) scm->socket_tx_buffer); } void * vl_socket_client_msg_alloc (int nbytes) { return vl_socket_client_msg_alloc2 (socket_client_ctx, nbytes); } void vl_socket_client_disconnect2 (socket_client_main_t * scm) { if (vl_mem_client_is_connected ()) { vl_client_disconnect_from_vlib_no_unmap (); ssvm_delete_memfd (&scm->memfd_segment); } if (scm->socket_fd && (close (scm->socket_fd) < 0)) clib_unix_warning ("close"); scm->socket_fd = 0; } void vl_socket_client_disconnect (void) { vl_socket_client_disconnect2 (socket_client_ctx); } void vl_socket_client_enable_disable2 (socket_client_main_t * scm, int enable) { scm->socket_enable = enable; } void vl_socket_client_enable_disable (int enable) { vl_socket_client_enable_disable2 (socket_client_ctx, enable); } static clib_error_t * vl_sock_api_recv_fd_msg_internal (socket_client_main_t * scm, int fds[], int n_fds, u32 wait) { char msgbuf[16]; char ctl[CMSG_SPACE (sizeof (int) * n_fds) + CMSG_SPACE (sizeof (struct ucred))]; struct msghdr mh = { 0 }; struct iovec iov[1]; ssize_t size = 0; struct ucred *cr = 0; struct cmsghdr *cmsg; pid_t pid __attribute__ ((unused)); uid_t uid __attribute__ ((unused)); gid_t gid __attribute__ ((unused)); int socket_fd; f64 timeout; socket_fd = scm->client_socket.fd; iov[0].iov_base = msgbuf; iov[0].iov_len = 5; mh.msg_iov = iov; mh.msg_iovlen = 1; mh.msg_control = ctl; mh.msg_controllen = sizeof (ctl); clib_memset (ctl, 0, sizeof (ctl)); if (wait != ~0) { timeout = clib_time_now (&scm->clib_time) + wait; while (size != 5 && clib_time_now (&scm->clib_time) < timeout) size = recvmsg (socket_fd, &mh, MSG_DONTWAIT); } else size = recvmsg (socket_fd, &mh, 0); if (size != 5) { return (size == 0) ? clib_error_return (0, "disconnected") : clib_error_return_unix (0, "recvmsg: malformed message (fd %d)", socket_fd); } cmsg = CMSG_FIRSTHDR (&mh); while (cmsg) { if (cmsg->cmsg_level == SOL_SOCKET) { if (cmsg->cmsg_type == SCM_CREDENTIALS) { cr = (struct ucred *) CMSG_DATA (cmsg); uid = cr->uid; gid = cr->gid; pid = cr->pid; } else if (cmsg->cmsg_type == SCM_RIGHTS) { clib_memcpy_fast (fds, CMSG_DATA (cmsg), sizeof (int) * n_fds); } } cmsg = CMSG_NXTHDR (&mh, cmsg); } return 0; } clib_error_t * vl_sock_api_recv_fd_msg (int socket_fd, int fds[], int n_fds, u32 wait) { return vl_sock_api_recv_fd_msg_internal (socket_client_ctx, fds, n_fds, wait); } clib_error_t * vl_sock_api_recv_fd_msg2 (socket_client_main_t * scm, int socket_fd, int fds[], int n_fds, u32 wait) { socket_client_main_t *old_ctx; clib_error_t *error; old_ctx = vl_socket_client_ctx_push (scm); error = vl_sock_api_recv_fd_msg_internal (scm, fds, n_fds, wait); vl_socket_client_ctx_pop (old_ctx); return error; } static void vl_api_sock_init_shm_reply_t_handler (vl_api_sock_init_shm_reply_t * mp) { socket_client_main_t *scm = socket_client_ctx; ssvm_private_t *memfd = &scm->memfd_segment; i32 retval = ntohl (mp->retval); api_main_t *am = vlibapi_get_main (); clib_error_t *error; int my_fd = -1; u8 *new_name; if (retval) { clib_warning ("failed to init shmem"); return; } /* * Check the socket for the magic fd */ error = vl_sock_api_recv_fd_msg (scm->socket_fd, &my_fd, 1, 5); if (error) { clib_error_report (error); retval = -99; return; } clib_memset (memfd, 0, sizeof (*memfd)); memfd->fd = my_fd; /* Note: this closes memfd.fd */ retval = ssvm_client_init_memfd (memfd); if (retval) clib_warning ("WARNING: segment map returned %d", retval); /* * Pivot to the memory client segment that vpp just created */ am->vlib_rp = (void *) (memfd->requested_va + MMAP_PAGESIZE); am->shmem_hdr = (void *) am->vlib_rp->user_ctx; new_name = format (0, "%v[shm]%c", scm->name, 0); vl_client_install_client_message_handlers (); if (scm->want_shm_pthread) { vl_client_connect_to_vlib_no_map ("pvt", (char *) new_name, 32 /* input_queue_length */ ); } else { vl_client_connect_to_vlib_no_rx_pthread_no_map ("pvt", (char *) new_name, 32 /* input_queue_length */ ); } vl_socket_client_enable_disable (0); vec_free (new_name); } static void vl_api_sockclnt_create_reply_t_handler (vl_api_sockclnt_create_reply_t * mp) { socket_client_main_t *scm = socket_client_ctx; if (!mp->response) { scm->socket_enable = 1; scm->client_index = clib_net_to_host_u32 (mp->index); } } #define foreach_sock_client_api_msg \ _(SOCKCLNT_CREATE_REPLY, sockclnt_create_reply) \ _(SOCK_INIT_SHM_REPLY, sock_init_shm_reply) \ void vl_sock_client_install_message_handlers (void) { #define _(N, n) \ vl_msg_api_config (&(vl_msg_api_msg_config_t){ \ .id = VL_API_##N, \ .name = #n, \ .handler = vl_api_##n##_t_handler, \ .endian = vl_api_##n##_t_endian, \ .format_fn = vl_api_##n##_t_format, \ .size = sizeof (vl_api_##n##_t), \ .traced = 0, \ .tojson = vl_api_##n##_t_tojson, \ .fromjson = vl_api_##n##_t_fromjson, \ .calc_size = vl_api_##n##_t_calc_size, \ }); foreach_sock_client_api_msg; #undef _ } int vl_socket_client_connect_internal (socket_client_main_t * scm, char *socket_path, char *client_name, u32 socket_buffer_size) { vl_api_sockclnt_create_t *mp; clib_socket_t *sock; clib_error_t *error; /* Already connected? */ if (scm->socket_fd) return (-2); /* bogus call? */ if (socket_path == 0 || client_name == 0) return (-3); sock = &scm->client_socket; sock->config = socket_path; sock->flags = CLIB_SOCKET_F_IS_CLIENT; if ((error = clib_socket_init (sock))) { clib_error_report (error); return (-1); } vl_sock_client_install_message_handlers (); scm->socket_fd = sock->fd; scm->socket_buffer_size = socket_buffer_size ? socket_buffer_size : SOCKET_CLIENT_DEFAULT_BUFFER_SIZE; vec_validate (scm->socket_tx_buffer, scm->socket_buffer_size - 1); vec_validate (scm->socket_rx_buffer, scm->socket_buffer_size - 1); vec_set_len (scm->socket_rx_buffer, 0); vec_set_len (scm->socket_tx_buffer, 0); scm->name = format (0, "%s", client_name); mp = vl_socket_client_msg_alloc2 (scm, sizeof (*mp)); mp->_vl_msg_id = htons (VL_API_SOCKCLNT_CREATE); strncpy ((char *) mp->name, client_name, sizeof (mp->name) - 1); mp->name[sizeof (mp->name) - 1] = 0; mp->context = 0xfeedface; clib_time_init (&scm->clib_time); if (vl_socket_client_write_internal (scm) <= 0) return (-1); if (vl_socket_client_read_internal (scm, 5)) return (-1); return (0); } int vl_socket_client_connect (char *socket_path, char *client_name, u32 socket_buffer_size) { return vl_socket_client_connect_internal (socket_client_ctx, socket_path, client_name, socket_buffer_size); } int vl_socket_client_connect2 (socket_client_main_t * scm, char *socket_path, char *client_name, u32 socket_buffer_size) { socket_client_main_t *old_ctx; int rv; old_ctx = vl_socket_client_ctx_push (scm); rv = vl_socket_client_connect_internal (socket_client_ctx, socket_path, client_name, socket_buffer_size); vl_socket_client_ctx_pop (old_ctx); return rv; } int vl_socket_client_init_shm_internal (socket_client_main_t * scm, vl_api_shm_elem_config_t * config, int want_pthread) { vl_api_sock_init_shm_t *mp; int rv, i; u64 *cfg; scm->want_shm_pthread = want_pthread; mp = vl_socket_client_msg_alloc2 (scm, sizeof (*mp) + vec_len (config) * sizeof (u64)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_SOCK_INIT_SHM); mp->client_index = clib_host_to_net_u32 (scm->client_index); mp->requested_size = 64 << 20; if (config) { for (i = 0; i < vec_len (config); i++) { cfg = (u64 *) & config[i]; mp->configs[i] = *cfg; } mp->nitems = vec_len (config); } rv = vl_socket_client_write_internal (scm); if (rv <= 0) return rv; if (vl_socket_client_read_internal (scm, 1)) return -1; return 0; } int vl_socket_client_init_shm (vl_api_shm_elem_config_t * config, int want_pthread) { return vl_socket_client_init_shm_internal (socket_client_ctx, config, want_pthread); } int vl_socket_client_init_shm2 (socket_client_main_t * scm, vl_api_shm_elem_config_t * config, int want_pthread) { socket_client_main_t *old_ctx; int rv; old_ctx = vl_socket_client_ctx_push (scm); rv = vl_socket_client_init_shm_internal (socket_client_ctx, config, want_pthread); vl_socket_client_ctx_pop (old_ctx); return rv; } clib_error_t * vl_socket_client_recv_fd_msg2 (socket_client_main_t * scm, int fds[], int n_fds, u32 wait) { if (!scm->socket_fd) return clib_error_return (0, "no socket"); return vl_sock_api_recv_fd_msg_internal (scm, fds, n_fds, wait); } clib_error_t * vl_socket_client_recv_fd_msg (int fds[], int n_fds, u32 wait) { return vl_socket_client_recv_fd_msg2 (socket_client_ctx, fds, n_fds, wait); } /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */