2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
19 #define __need_IOV_MAX
20 #include <bits/stdio_lim.h>
21 #include <netinet/tcp.h>
23 #include <vppinfra/types.h>
24 #include <vppinfra/time.h>
25 #include <vppinfra/hash.h>
26 #include <vppinfra/pool.h>
28 #include <vcl/vcom_socket.h>
29 #include <vcl/vcom_socket_wrapper.h>
32 #include <vcl/vppcom.h>
35 #define IOV_MAX __IOV_MAX
39 * VCOM_SOCKET Private definitions and functions.
42 typedef struct vcom_socket_main_t_
45 clib_time_t clib_time;
48 /* vcom_socket pool */
49 vcom_socket_t *vsockets;
51 /* Hash table for socketidx to fd mapping */
55 vcom_epoll_t *vepolls;
57 /* Hash table for epollidx to epfd mapping */
58 uword *epollidx_by_epfd;
60 /* common epitem poll for all epfd */
61 /* TBD: epitem poll per epfd */
62 /* vcom_epitem pool */
63 vcom_epitem_t *vepitems;
65 /* Hash table for epitemidx to epfdfd mapping */
66 uword *epitemidx_by_epfdfd;
68 /* Hash table - key:epfd, value:vec of epitemidx */
69 uword *epitemidxs_by_epfd;
70 /* Hash table - key:fd, value:vec of epitemidx */
71 uword *epitemidxs_by_fd;
76 vcom_socket_main_t vcom_socket_main;
80 vcom_socket_open_socket (int domain, int type, int protocol)
84 /* handle domains implemented by vpp */
89 /* get socket type and
90 * handle the socket types supported by vpp */
91 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
95 /* the type argument serves a second purpose,
96 * in addition to specifying a socket type,
97 * it may include the bitwise OR of any of
98 * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify
99 * the behavior of socket. */
100 rv = libc_socket (domain, type, protocol);
119 vcom_socket_open_epoll (int flags)
127 if (flags && (flags & ~EPOLL_CLOEXEC))
132 /* flags can be either zero or EPOLL_CLOEXEC */
133 rv = libc_epoll_create1 (flags);
141 vcom_socket_close_socket (int fd)
145 rv = libc_close (fd);
153 vcom_socket_close_epoll (int epfd)
157 rv = libc_close (epfd);
165 * Public API functions
170 vcom_socket_is_vcom_fd (int fd)
172 vcom_socket_main_t *vsm = &vcom_socket_main;
174 vcom_socket_t *vsock;
176 p = hash_get (vsm->sockidx_by_fd, fd);
180 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
181 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
188 vcom_socket_is_vcom_epfd (int epfd)
190 vcom_socket_main_t *vsm = &vcom_socket_main;
192 vcom_epoll_t *vepoll;
194 p = hash_get (vsm->epollidx_by_epfd, epfd);
198 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
199 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
206 vcom_socket_get_sid (int fd)
208 vcom_socket_main_t *vsm = &vcom_socket_main;
210 vcom_socket_t *vsock;
212 p = hash_get (vsm->sockidx_by_fd, fd);
216 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
217 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
220 return INVALID_SESSION_ID;
224 vcom_socket_get_vep_idx (int epfd)
226 vcom_socket_main_t *vsm = &vcom_socket_main;
228 vcom_epoll_t *vepoll;
230 p = hash_get (vsm->epollidx_by_epfd, epfd);
234 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
235 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
236 return vepoll->vep_idx;
238 return INVALID_VEP_IDX;
242 vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp)
244 vcom_socket_main_t *vsm = &vcom_socket_main;
246 vcom_socket_t *vsock;
248 p = hash_get (vsm->sockidx_by_fd, fd);
252 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
253 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
259 return INVALID_SESSION_ID;
263 vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp)
265 vcom_socket_main_t *vsm = &vcom_socket_main;
267 vcom_epoll_t *vepoll;
269 p = hash_get (vsm->epollidx_by_epfd, epfd);
273 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
274 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
277 return vepoll->vep_idx;
280 return INVALID_VEP_IDX;
285 vcom_socket_close_vepoll (int epfd)
288 vcom_socket_main_t *vsm = &vcom_socket_main;
290 vcom_epoll_t *vepoll;
292 p = hash_get (vsm->epollidx_by_epfd, epfd);
296 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
300 if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND)
317 rv = vppcom_session_close (vepoll->vep_idx);
318 rv = vcom_socket_close_epoll (vepoll->epfd);
320 vepoll_init (vepoll);
321 hash_unset (vsm->epollidx_by_epfd, epfd);
322 pool_put (vsm->vepolls, vepoll);
328 vcom_socket_close_vsock (int fd)
331 vcom_socket_main_t *vsm = &vcom_socket_main;
333 vcom_socket_t *vsock;
335 vcom_epitem_t *vepitem;
337 i32 *vepitemidxs = 0;
338 i32 *vepitemidxs_var = 0;
340 p = hash_get (vsm->sockidx_by_fd, fd);
344 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
348 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
351 rv = vppcom_session_close (vsock->sid);
352 rv = vcom_socket_close_socket (vsock->fd);
354 vsocket_init (vsock);
355 hash_unset (vsm->sockidx_by_fd, fd);
356 pool_put (vsm->vsockets, vsock);
360 * Before calling close(), user should remove
361 * this fd from the epoll-set of all epoll instances,
362 * otherwise resource(epitems) leaks ensues.
366 * 00. close all epoll instances that are marked as "close"
367 * of which this fd is the "last" remaining member.
368 * 01. epitems associated with this fd are intentionally
369 * not removed, see NOTE: above.
372 /* does this fd participate in epoll */
373 p = hash_get (vsm->epitemidxs_by_fd, fd);
376 vepitemidxs = *(i32 **) p;
377 vec_foreach (vepitemidxs_var, vepitemidxs)
379 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]);
380 if (vepitem && vepitem->fd == fd &&
381 vepitem->type == FD_TYPE_VCOM_SOCKET)
384 vcom_epoll_t *vepoll;
386 vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd,
392 if (vepoll->count == 1)
395 * force count to zero and
396 * close this epoll instance
399 vcom_socket_close_vepoll (vepoll->epfd);
416 vcom_socket_close (int __fd)
420 if (vcom_socket_is_vcom_fd (__fd))
422 rv = vcom_socket_close_vsock (__fd);
424 else if (vcom_socket_is_vcom_epfd (__fd))
426 rv = vcom_socket_close_vepoll (__fd);
437 vcom_socket_read (int __fd, void *__buf, size_t __nbytes)
440 vcom_socket_main_t *vsm = &vcom_socket_main;
442 vcom_socket_t *vsock;
444 p = hash_get (vsm->sockidx_by_fd, __fd);
448 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
452 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
460 rv = vcom_fcntl (__fd, F_GETFL, 0);
468 if (!(rv & O_NONBLOCK))
472 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
474 /* coverity[CONSTANT_EXPRESSION_RESULT] */
475 while (rv == -EAGAIN || rv == -EWOULDBLOCK);
478 /* The file descriptor refers to a socket and has been
479 * marked nonblocking(O_NONBLOCK) and the read would
482 /* is non blocking */
483 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
488 vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt)
491 vcom_socket_main_t *vsm = &vcom_socket_main;
493 vcom_socket_t *vsock;
494 ssize_t total = 0, len = 0;
497 p = hash_get (vsm->sockidx_by_fd, __fd);
501 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
505 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
508 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
512 for (i = 0; i < __iovcnt; ++i)
514 if (SSIZE_MAX - len < __iov[i].iov_len)
516 len += __iov[i].iov_len;
519 rv = vcom_fcntl (__fd, F_GETFL, 0);
526 if (!(rv & O_NONBLOCK))
530 for (i = 0; i < __iovcnt; ++i)
532 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
539 if (rv < __iov[i].iov_len)
540 /* Read less than buffer provided, no point to continue */
545 /* coverity[CONSTANT_EXPRESSION_RESULT] */
546 while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0);
550 /* is non blocking */
551 for (i = 0; i < __iovcnt; ++i)
553 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
568 if (rv < __iov[i].iov_len)
569 /* Read less than buffer provided, no point to continue */
577 vcom_socket_write (int __fd, const void *__buf, size_t __n)
580 vcom_socket_main_t *vsm = &vcom_socket_main;
582 vcom_socket_t *vsock;
589 p = hash_get (vsm->sockidx_by_fd, __fd);
593 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
597 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
600 rv = vppcom_session_write (vsock->sid, (void *) __buf, __n);
605 vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt)
609 vcom_socket_main_t *vsm = &vcom_socket_main;
611 vcom_socket_t *vsock;
614 p = hash_get (vsm->sockidx_by_fd, __fd);
618 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
622 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
625 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
628 for (i = 0; i < __iovcnt; ++i)
630 rv = vppcom_session_write (vsock->sid, __iov[i].iov_base,
646 * RETURN: 0 - invalid cmd
647 * 1 - cmd not handled by vcom and vppcom
648 * 2 - cmd handled by vcom socket resource
649 * 3 - cmd handled by vppcom
651 /* TBD: incomplete list of cmd */
653 vcom_socket_check_fcntl_cmd (int __cmd)
657 /*cmd not handled by vcom and vppcom */
660 case F_DUPFD_CLOEXEC:
663 /* cmd handled by vcom socket resource */
674 /* cmd handled by vcom and vppcom */
679 /* cmd not handled by vcom and vppcom */
687 vcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
689 int flags = va_arg (__ap, int);
690 int rv = -EOPNOTSUPP;
693 size = sizeof (flags);
694 if (__cmd == F_SETFL)
696 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
698 else if (__cmd == F_GETFL)
700 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
709 vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap)
712 vcom_socket_main_t *vsm = &vcom_socket_main;
714 vcom_socket_t *vsock;
716 p = hash_get (vsm->sockidx_by_fd, __fd);
720 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
724 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
727 switch (vcom_socket_check_fcntl_cmd (__cmd))
733 /*cmd not handled by vcom and vppcom */
735 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
737 /* cmd handled by vcom socket resource */
739 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
741 /* cmd handled by vppcom */
743 rv = vcom_session_fcntl_va (vsock->sid, __cmd, __ap);
755 * RETURN: 0 - invalid cmd
756 * 1 - cmd not handled by vcom and vppcom
757 * 2 - cmd handled by vcom socket resource
758 * 3 - cmd handled by vppcom
761 vcom_socket_check_ioctl_cmd (unsigned long int __cmd)
767 /* cmd handled by vppcom */
772 /* cmd not handled by vcom and vppcom */
781 vcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
788 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
793 u32 flags = va_arg (__ap, int) ? O_NONBLOCK : 0;
794 u32 len = sizeof (flags);
795 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &len);
807 vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
810 vcom_socket_main_t *vsm = &vcom_socket_main;
812 vcom_socket_t *vsock;
814 p = hash_get (vsm->sockidx_by_fd, __fd);
818 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
822 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
825 switch (vcom_socket_check_ioctl_cmd (__cmd))
827 /* Not supported cmd */
832 /* cmd not handled by vcom and vppcom */
834 rv = libc_vioctl (vsock->fd, __cmd, __ap);
837 /* cmd handled by vcom socket resource */
839 rv = libc_vioctl (vsock->fd, __cmd, __ap);
842 /* cmd handled by vppcom */
844 rv = vcom_session_ioctl_va (vsock->sid, __cmd, __ap);
856 vcom_socket_fds_2_sid_fds (
859 fd_set * __restrict vcom_rd_sid_fds,
860 fd_set * __restrict vcom_wr_sid_fds,
861 fd_set * __restrict vcom_ex_sid_fds,
864 fd_set * __restrict vcom_readfds,
865 fd_set * __restrict vcom_writefds,
866 fd_set * __restrict vcom_exceptfds)
871 /* invalid max_sid is -1 */
876 * set sid in sid sets corresponding to fd's in fd sets
877 * compute nsid and vcom_nsid_fds from sid sets
880 for (fd = 0; fd < vcom_nfds; fd++)
887 if ((F) && (S) && FD_ISSET (fd, (F))) \
889 sid = vcom_socket_get_sid (fd); \
890 if (sid != INVALID_SESSION_ID) \
907 _(vcom_rd_sid_fds, vcom_readfds);
908 _(vcom_wr_sid_fds, vcom_writefds);
909 _(vcom_ex_sid_fds, vcom_exceptfds);
913 *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0;
921 * PRE: 00. sid sets were derived from fd sets
922 * 01. sid sets were updated with sids that actually changed
924 * 02. fd sets still has watched fds
926 * This function will modify in place fd sets to indicate which fd's
927 * actually changed status(inferred from sid sets)
930 vcom_socket_sid_fds_2_fds (
934 fd_set * __restrict vcom_readfds,
935 fd_set * __restrict vcom_writefds,
936 fd_set * __restrict vcom_exceptfds,
939 fd_set * __restrict vcom_rd_sid_fds,
940 fd_set * __restrict vcom_wr_sid_fds,
941 fd_set * __restrict vcom_ex_sid_fds)
946 /* invalid max_fd is -1 */
952 * modify in place fd sets to indicate which fd's
953 * actually changed status(inferred from sid sets)
955 for (fd = 0; fd < vcom_nfds; fd++)
962 if ((F) && (S) && FD_ISSET (fd, (F))) \
964 sid = vcom_socket_get_sid (fd); \
965 if (sid != INVALID_SESSION_ID) \
967 if (!FD_ISSET (sid, (S))) \
980 _(vcom_rd_sid_fds, vcom_readfds);
981 _(vcom_wr_sid_fds, vcom_writefds);
982 _(vcom_ex_sid_fds, vcom_exceptfds);
987 * compute nfd and new_vcom_nfds from fd sets
989 for (fd = 0; fd < vcom_nfds; fd++)
993 if ((F) && FD_ISSET (fd, (F))) \
1010 *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0;
1019 * vom_socket_select is always called with
1020 * timeout->tv_sec and timeout->tv_usec set to zero.
1021 * hence vppcom_select return immediately.
1024 * TBD: do{body;} while(timeout conditional); timeout loop
1027 vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds,
1028 fd_set * __restrict vcom_writefds,
1029 fd_set * __restrict vcom_exceptfds,
1030 struct timeval *__restrict timeout)
1032 static unsigned long vcom_nsid_fds = 0;
1036 int new_vcom_nfds = 0;
1037 int new_vcom_nfd = 0;
1040 fd_set vcom_rd_sid_fds;
1041 fd_set vcom_wr_sid_fds;
1042 fd_set vcom_ex_sid_fds;
1044 /* in seconds eg. 3.123456789 seconds */
1045 double time_to_wait = (double) 0;
1047 /* validate inputs */
1053 /* convert timeval timeout to double time_to_wait */
1056 if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
1058 /* polling: vppcom_select returns immediately */
1059 time_to_wait = (double) 0;
1063 /*TBD: use timeval api */
1064 time_to_wait = (double) timeout->tv_sec +
1065 (double) timeout->tv_usec / (double) 1000000 +
1066 (double) (timeout->tv_usec % 1000000) / (double) 1000000;
1072 * no timeout: vppcom_select can block indefinitely
1073 * waiting for a file descriptor to become ready
1075 /* set to a phantom value */
1079 /* zero the sid_sets */
1091 _(&vcom_rd_sid_fds, vcom_readfds);
1092 _(&vcom_wr_sid_fds, vcom_writefds);
1093 _(&vcom_ex_sid_fds, vcom_exceptfds);
1098 if (time_to_wait > 0)
1102 "[%d] vcom_socket_select called to "
1103 "emulate delay_ns()!\n", getpid ());
1104 rv = vppcom_select (0, NULL, NULL, NULL, time_to_wait);
1108 fprintf (stderr, "[%d] vcom_socket_select called vcom_nfds = 0 "
1109 "and invalid time_to_wait (%f)!\n",
1110 getpid (), time_to_wait);
1115 /* populate read, write and except sid_sets */
1116 vcom_nsid = vcom_socket_fds_2_sid_fds (
1118 vcom_readfds || vcom_writefds
1119 || vcom_exceptfds ? (int *)
1120 &vcom_nsid_fds : NULL,
1121 vcom_readfds ? &vcom_rd_sid_fds :
1123 vcom_writefds ? &vcom_wr_sid_fds :
1125 vcom_exceptfds ? &vcom_ex_sid_fds :
1130 vcom_writefds, vcom_exceptfds);
1136 rv = vppcom_select (vcom_nsid_fds,
1137 vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds :
1139 vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds :
1141 vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
1142 NULL, time_to_wait);
1144 fprintf (stderr, "[%d] called vppcom_select(): "
1145 "'%04d'='%04d'\n", getpid (), rv, (int) vcom_nsid_fds);
1147 /* check if any file descriptors changed status */
1151 * on exit, sets are modified in place to indicate which
1152 * file descriptors actually changed status
1156 * comply with pre-condition
1157 * do not clear vcom fd sets befor calling
1158 * vcom_socket_sid_fds_2_fds
1160 new_vcom_nfd = vcom_socket_sid_fds_2_fds (
1170 &vcom_rd_sid_fds : NULL,
1172 &vcom_wr_sid_fds : NULL,
1174 &vcom_ex_sid_fds : NULL);
1175 if (new_vcom_nfd < 0)
1177 return new_vcom_nfd;
1179 if (new_vcom_nfds < 0)
1190 vcom_socket_socket (int __domain, int __type, int __protocol)
1193 vcom_socket_main_t *vsm = &vcom_socket_main;
1194 vcom_socket_t *vsock;
1199 u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0;
1200 int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
1202 fd = vcom_socket_open_socket (__domain, __type, __protocol);
1209 sid = vppcom_session_create (VPPCOM_VRF_DEFAULT,
1210 (type == SOCK_DGRAM) ?
1211 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP,
1216 goto out_close_socket;
1219 pool_get (vsm->vsockets, vsock);
1220 vsocket_init (vsock);
1222 sockidx = vsock - vsm->vsockets;
1223 hash_set (vsm->sockidx_by_fd, fd, sockidx);
1225 vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND);
1229 vcom_socket_close_socket (fd);
1235 vcom_socket_socketpair (int __domain, int __type, int __protocol,
1243 vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1246 vcom_socket_main_t *vsm = &vcom_socket_main;
1248 vcom_socket_t *vsock;
1252 p = hash_get (vsm->sockidx_by_fd, __fd);
1256 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1260 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1268 ep.vrf = VPPCOM_VRF_DEFAULT;
1269 switch (__addr->sa_family)
1272 if (__len != sizeof (struct sockaddr_in))
1276 ep.is_ip4 = VPPCOM_IS_IP4;
1277 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1278 ep.port = (u16) ((const struct sockaddr_in *) __addr)->sin_port;
1282 if (__len != sizeof (struct sockaddr_in6))
1286 ep.is_ip4 = VPPCOM_IS_IP6;
1287 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1288 ep.port = (u16) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1296 rv = vppcom_session_bind (vsock->sid, &ep);
1301 vcom_session_getsockname (int sid, vppcom_endpt_t * ep)
1304 uint32_t size = sizeof (*ep);
1306 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, ep, &size);
1311 vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr,
1312 socklen_t * __restrict __len)
1315 vcom_socket_main_t *vsm = &vcom_socket_main;
1317 vcom_socket_t *vsock;
1320 p = hash_get (vsm->sockidx_by_fd, __fd);
1324 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1328 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1331 if (!__addr || !__len)
1335 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1336 rv = vcom_session_getsockname (vsock->sid, &ep);
1339 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1341 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1342 switch (__addr->sa_family)
1345 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1346 *__len = sizeof (struct sockaddr_in);
1350 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1351 *__len = sizeof (struct sockaddr_in6);
1364 vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1367 vcom_socket_main_t *vsm = &vcom_socket_main;
1369 vcom_socket_t *vsock;
1373 p = hash_get (vsm->sockidx_by_fd, __fd);
1376 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1378 ep.vrf = VPPCOM_VRF_DEFAULT;
1379 switch (__addr->sa_family)
1382 ep.is_ip4 = VPPCOM_IS_IP4;
1384 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1386 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1390 ep.is_ip4 = VPPCOM_IS_IP6;
1392 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1394 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1402 rv = vppcom_session_connect (vsock->sid, &ep);
1408 vcom_session_getpeername (int sid, vppcom_endpt_t * ep)
1411 uint32_t size = sizeof (*ep);
1413 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size);
1418 vcom_socket_copy_ep_to_sockaddr (__SOCKADDR_ARG __addr,
1419 socklen_t * __restrict __len,
1420 vppcom_endpt_t * ep)
1423 int sa_len, copy_len;
1425 __addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1426 switch (__addr->sa_family)
1429 ((struct sockaddr_in *) __addr)->sin_port = ep->port;
1430 if (*__len > sizeof (struct sockaddr_in))
1431 *__len = sizeof (struct sockaddr_in);
1432 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1433 copy_len = *__len - sa_len;
1435 memcpy (&((struct sockaddr_in *) __addr)->sin_addr, ep->ip, copy_len);
1439 ((struct sockaddr_in6 *) __addr)->sin6_port = ep->port;
1440 if (*__len > sizeof (struct sockaddr_in6))
1441 *__len = sizeof (struct sockaddr_in6);
1442 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1443 copy_len = *__len - sa_len;
1445 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
1446 __in6_u.__u6_addr8, ep->ip, copy_len);
1459 vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr,
1460 socklen_t * __restrict __len)
1463 vcom_socket_main_t *vsm = &vcom_socket_main;
1465 vcom_socket_t *vsock;
1466 u8 src_addr[sizeof (struct sockaddr_in6)];
1469 p = hash_get (vsm->sockidx_by_fd, __fd);
1473 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1477 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1480 if (!__addr || !__len)
1484 rv = vcom_session_getpeername (vsock->sid, &ep);
1486 rv = vcom_socket_copy_ep_to_sockaddr (__addr, __len, &ep);
1492 vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags)
1494 return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0);
1497 /* NOTE: this function is not thread safe or 32-bit friendly */
1499 vcom_socket_sendfile (int __out_fd, int __in_fd, off_t * __offset,
1502 vcom_socket_main_t *vsm = &vcom_socket_main;
1504 vcom_socket_t *vsock;
1505 size_t n_bytes_left = __len;
1506 u32 out_sockidx, out_sid = ~0;
1507 size_t bytes_to_read;
1510 ssize_t results = 0;
1514 clib_warning ("[%d] __out_fd %d, __in_fd %d, __offset %p, __len %lu",
1515 getpid (), __out_fd, __in_fd, __offset, __len);
1517 p = hash_get (vsm->sockidx_by_fd, __out_fd);
1520 clib_warning ("[%d] ERROR: invalid __out_fd (%d), fd lookup failed!",
1525 vsock = pool_elt_at_index (vsm->vsockets, out_sockidx);
1528 clib_warning ("[%d] ERROR: invalid __out_fd (%d) / out_sockidx %u, "
1529 "missing vsock pool element!",
1530 getpid (), __len, out_sockidx);
1533 out_sid = vsock->sid;
1534 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1536 clib_warning ("[%d] ERROR: __out_fd (%d), socket (sid %u) "
1537 "is not VCL bound!", getpid (), __out_fd, out_sid);
1543 off_t offset = lseek (__in_fd, *__offset, SEEK_SET);
1548 clib_warning ("[%d] ERROR: lseek SEEK_SET failed: "
1549 "in_fd %d, offset %p (%ld), rv %ld, errno %d",
1550 getpid (), __in_fd, __offset, *__offset, offset,
1555 ASSERT (offset == *__offset);
1560 bytes_to_read = vppcom_session_attr (out_sid,
1561 VPPCOM_ATTR_GET_NWRITE, 0, 0);
1563 clib_warning ("[%d] results %ld, n_bytes_left %lu, "
1564 "bytes_to_read %lu", getpid (), results,
1565 n_bytes_left, bytes_to_read);
1566 if (bytes_to_read == 0)
1568 u32 flags, flags_len = sizeof (flags);
1569 rv = vppcom_session_attr (out_sid, VPPCOM_ATTR_GET_FLAGS, &flags,
1571 ASSERT (rv == VPPCOM_OK);
1573 if (flags & O_NONBLOCK)
1578 clib_warning ("[%d] EAGAIN", getpid ());
1586 bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1587 vec_validate (vsm->io_buffer, bytes_to_read);
1588 nbytes = libc_read (__in_fd, vsm->io_buffer, bytes_to_read);
1593 clib_warning ("[%d] ERROR: libc_read (__in_fd (%d), "
1594 "io_buffer %p, bytes_to_read %lu) returned "
1596 getpid (), __in_fd, vsm->io_buffer,
1597 bytes_to_read, errno_val);
1600 vec_reset_length (vsm->io_buffer);
1605 rv = vppcom_session_write (out_sid, vsm->io_buffer, nbytes);
1608 clib_warning ("[%d] ERROR: vppcom_session_write ("
1609 "out_sid %u, io_buffer %p, nbytes %d) returned %d",
1610 getpid (), out_sid, vsm->io_buffer, nbytes, rv);
1613 vec_reset_length (vsm->io_buffer);
1620 ASSERT (n_bytes_left >= nbytes);
1621 n_bytes_left = n_bytes_left - nbytes;
1623 while (n_bytes_left > 0);
1628 off_t offset = lseek (__in_fd, *__offset, SEEK_SET);
1633 clib_warning ("[%d] ERROR: lseek (__in_fd %d, __offset %p "
1634 "(%ld), SEEK_SET) returned errno %d",
1635 getpid (), __in_fd, __offset, *__offset, errno_val);
1636 vec_reset_length (vsm->io_buffer);
1640 *__offset += results + 1;
1643 vec_reset_length (vsm->io_buffer);
1644 return eagain ? -EAGAIN : results;
1648 vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags)
1651 rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0);
1656 * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET),
1660 vcom_socket_is_connection_mode_socket (int __fd)
1663 /* TBD define new vppcom api */
1664 vcom_socket_main_t *vsm = &vcom_socket_main;
1666 vcom_socket_t *vsock;
1671 p = hash_get (vsm->sockidx_by_fd, __fd);
1675 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1676 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
1678 optlen = sizeof (type);
1679 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
1684 /* get socket type */
1685 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1688 case SOCK_SEQPACKET:
1701 static inline ssize_t
1702 vcom_session_sendto (int __sid, void *__buf, size_t __n,
1703 int __flags, __CONST_SOCKADDR_ARG __addr,
1704 socklen_t __addr_len)
1706 vppcom_endpt_t *ep = 0;
1712 ep->vrf = VPPCOM_VRF_DEFAULT;
1713 switch (__addr->sa_family)
1716 ep->is_ip4 = VPPCOM_IS_IP4;
1718 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1720 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1724 ep->is_ip4 = VPPCOM_IS_IP6;
1726 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1728 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1732 return -EAFNOSUPPORT;
1736 return vppcom_session_sendto (__sid, __buf, __n, __flags, ep);;
1740 vcom_socket_sendto (int __fd, const void *__buf, size_t __n,
1741 int __flags, __CONST_SOCKADDR_ARG __addr,
1742 socklen_t __addr_len)
1744 vcom_socket_main_t *vsm = &vcom_socket_main;
1746 vcom_socket_t *vsock;
1753 p = hash_get (vsm->sockidx_by_fd, __fd);
1757 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1761 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1766 if (vcom_socket_is_connection_mode_socket (__fd))
1768 /* ignore __addr and _addr_len */
1769 /* and EISCONN may be returned when they are not NULL and 0 */
1770 if ((__addr != NULL) || (__addr_len != 0))
1779 return -EDESTADDRREQ;
1781 /* not a vppcom supported address family */
1782 if (!((__addr->sa_family == AF_INET) ||
1783 (__addr->sa_family == AF_INET6)))
1789 return vcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
1790 __flags, __addr, __addr_len);
1793 static inline ssize_t
1794 vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
1795 int __flags, __SOCKADDR_ARG __addr,
1796 socklen_t * __restrict __addr_len)
1800 u8 src_addr[sizeof (struct sockaddr_in6)];
1805 rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, &ep);
1808 rv = vcom_socket_copy_ep_to_sockaddr (__addr, __addr_len, &ep);
1811 rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, NULL);
1817 vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
1818 int __flags, __SOCKADDR_ARG __addr,
1819 socklen_t * __restrict __addr_len)
1822 vcom_socket_main_t *vsm = &vcom_socket_main;
1824 vcom_socket_t *vsock;
1826 if (__addr && !__addr_len)
1829 p = hash_get (vsm->sockidx_by_fd, __fd);
1833 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1837 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1842 rv = vcom_session_recvfrom (vsock->sid, __buf, __n,
1843 __flags, __addr, __addr_len);
1847 /* TBD: move it to vppcom */
1848 static inline ssize_t
1849 vcom_session_sendmsg (int __sid, const struct msghdr *__message, int __flags)
1852 /* rv = vppcom_session_write (__sid, (void *) __message->__buf,
1858 vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags)
1861 vcom_socket_main_t *vsm = &vcom_socket_main;
1863 vcom_socket_t *vsock;
1865 p = hash_get (vsm->sockidx_by_fd, __fd);
1869 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1873 if (vcom_socket_is_connection_mode_socket (__fd))
1875 /* ignore __addr and _addr_len */
1876 /* and EISCONN may be returned when they are not NULL and 0 */
1877 if ((__message->msg_name != NULL) || (__message->msg_namelen != 0))
1884 /* TBD: validate __message->msg_name and __message->msg_namelen
1885 * and return -EINVAL on validation error
1890 rv = vcom_session_sendmsg (vsock->sid, __message, __flags);
1897 vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages,
1898 unsigned int __vlen, int __flags)
1901 /* TBD: define a new vppcom api */
1906 /* TBD: move it to vppcom */
1907 static inline ssize_t
1908 vcom_session_recvmsg (int __sid, struct msghdr *__message, int __flags)
1911 /* rv = vppcom_session_read (__sid, (void *) __message->__buf,
1918 vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags)
1921 vcom_socket_main_t *vsm = &vcom_socket_main;
1923 vcom_socket_t *vsock;
1925 p = hash_get (vsm->sockidx_by_fd, __fd);
1929 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1933 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1941 /* validate __flags */
1943 rv = vcom_session_recvmsg (vsock->sid, __message, __flags);
1949 vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages,
1950 unsigned int __vlen, int __flags,
1951 struct timespec *__tmo)
1953 /* TBD: define a new vppcom api */
1958 /* TBD: move it to vppcom */
1960 vcom_session_get_sockopt (int __sid, int __level, int __optname,
1961 void *__restrict __optval,
1962 socklen_t * __restrict __optlen)
1966 /* 1. for socket level options that are NOT socket attributes
1967 * and that has corresponding vpp options get from vppcom */
1974 *(int *) __optval = 0;
1982 /* 2. unhandled options */
1987 vcom_socket_getsockopt (int __fd, int __level, int __optname,
1988 void *__restrict __optval,
1989 socklen_t * __restrict __optlen)
1992 vcom_socket_main_t *vsm = &vcom_socket_main;
1994 vcom_socket_t *vsock;
1996 if (!__optval || !__optlen)
1999 p = hash_get (vsm->sockidx_by_fd, __fd);
2003 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2007 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
2016 * 1. for socket level options that are socket attributes,
2017 * get from libc_getsockopt.
2018 * 2. for socket level options that are NOT socket
2019 * attributes and that has corresponding vpp options
2021 * 3. for socket level options unimplemented
2022 * return -ENOPROTOOPT */
2040 case SO_TIMESTAMPNS:
2041 case SO_TIMESTAMPING:
2054 case SO_WIFI_STATUS:
2057 case SO_BINDTODEVICE:
2059 case SO_LOCK_FILTER:
2060 case SO_BPF_EXTENSIONS:
2061 case SO_SELECT_ERR_QUEUE:
2062 #ifdef CONFIG_NET_RX_BUSY_POLL
2065 case SO_MAX_PACING_RATE:
2066 #ifdef SO_INCOMING_CPU
2067 case SO_INCOMING_CPU:
2069 rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
2078 rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
2079 __optval, __optlen);
2083 /* We implement the SO_SNDLOWAT etc to not be settable
2086 return -ENOPROTOOPT;
2092 /* 1. handle options that are NOT socket level options,
2093 * but have corresponding vpp otions. */
2094 rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
2095 __optval, __optlen);
2102 /* TBD: move it to vppcom */
2104 vcom_session_setsockopt (int __sid, int __level, int __optname,
2105 const void *__optval, socklen_t __optlen)
2107 int rv = -EOPNOTSUPP;
2116 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, 0, 0);
2120 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, 0, 0);
2130 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0);
2140 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_KEEPALIVE, 0, 0);
2143 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0);
2146 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0);
2160 vcom_socket_setsockopt (int __fd, int __level, int __optname,
2161 const void *__optval, socklen_t __optlen)
2164 vcom_socket_main_t *vsm = &vcom_socket_main;
2166 vcom_socket_t *vsock;
2168 p = hash_get (vsm->sockidx_by_fd, __fd);
2172 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2176 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
2180 * Options without arguments
2183 if (__optname == SO_BINDTODEVICE)
2185 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2196 if (__optlen < sizeof (int))
2205 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2206 __optval, __optlen);
2219 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2220 __optval, __optlen);
2226 /* handle options at socket level */
2233 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2234 __optval, __optlen);
2238 * 1. for socket level options that are socket attributes,
2239 * set it from libc_getsockopt
2240 * 2. for socket level options that are NOT socket
2241 * attributes and that has corresponding vpp options
2242 * set it from vppcom
2243 * 3. for socket level options unimplemented
2244 * return -ENOPROTOOPT */
2260 case SO_TIMESTAMPNS:
2261 case SO_TIMESTAMPING:
2274 case SO_WIFI_STATUS:
2278 * SO_BINDTODEVICE already handled as
2279 * "Options without arguments" */
2280 /* case SO_BINDTODEVICE: */
2282 case SO_LOCK_FILTER:
2283 case SO_BPF_EXTENSIONS:
2284 case SO_SELECT_ERR_QUEUE:
2285 #ifdef CONFIG_NET_RX_BUSY_POLL
2288 case SO_MAX_PACING_RATE:
2289 #ifdef SO_INCOMING_CPU
2290 case SO_INCOMING_CPU:
2292 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2301 /* We implement the SO_SNDLOWAT etc to not be settable
2304 return -ENOPROTOOPT;
2310 return -ENOPROTOOPT;
2317 vcom_socket_listen (int __fd, int __n)
2320 vcom_socket_main_t *vsm = &vcom_socket_main;
2322 vcom_socket_t *vsock;
2324 p = hash_get (vsm->sockidx_by_fd, __fd);
2327 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2329 /* TBD vppcom to accept __n parameter */
2330 rv = vppcom_session_listen (vsock->sid, __n);
2337 vcom_socket_connected_socket (int __fd, int __sid,
2339 int *__type, int *__protocol, int flags)
2342 vcom_socket_main_t *vsm = &vcom_socket_main;
2343 vcom_socket_t *vsock;
2350 optlen = sizeof (*__domain);
2351 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen);
2358 optlen = sizeof (*__type);
2359 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen);
2366 optlen = sizeof (*__protocol);
2367 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen);
2374 fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol);
2381 pool_get (vsm->vsockets, vsock);
2382 vsocket_init (vsock);
2384 sockidx = vsock - vsm->vsockets;
2385 hash_set (vsm->sockidx_by_fd, fd, sockidx);
2387 vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND);
2394 /* If flag is 0, then accept4() is the same as accept().
2395 * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags
2398 vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr,
2399 socklen_t * __restrict __addr_len, int flags)
2402 vcom_socket_main_t *vsm = &vcom_socket_main;
2404 vcom_socket_t *vsock;
2412 uint8_t addr8[sizeof (struct in6_addr)];
2417 /* validate flags */
2424 * case SOCK_NONBLOCK:
2425 * case SOCK_CLOEXEC:
2426 * case SOCK_NONBLOCK | SOCK_CLOEXEC:
2433 /* flags can be 0 or can be bitwise OR
2434 * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */
2437 fprintf (stderr, "[%d] vcom_socket_accept_flags: "
2438 "fd = %d, __addr = %p, __addr_len = %p flags = %d (0x%x)\n",
2439 getpid (), __fd, __addr, __addr_len, flags, flags);
2441 if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC))))
2443 /* TBD: return proper error code */
2444 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2445 "invalid flags = %d (0x%x)\n", getpid (), flags, flags);
2450 /* TBD: return proper error code */
2452 if (!vcom_socket_is_connection_mode_socket (__fd))
2454 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2455 "connection mode socket support TBD!\n", getpid ());
2459 p = hash_get (vsm->sockidx_by_fd, __fd);
2462 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2465 rv = vcom_fcntl (vsock->fd, F_GETFL, 0);
2468 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2469 "vcom_fcnt() returned %d!\n", getpid (), rv);
2474 if (!(rv & O_NONBLOCK))
2476 /* socket is not marked as nonblocking
2477 * and no pending connections are present
2478 * on the queue, accept () blocks the caller
2479 * until a connection is present.
2481 rv = vppcom_session_accept (vsock->sid, &ep, flags,
2482 -1.0 /* wait forever */ );
2486 /* The file descriptor refers to a socket and has been
2487 * marked nonblocking(O_NONBLOCK) and the accept would
2490 /* is non blocking */
2491 rv = vppcom_session_accept (vsock->sid, &ep, flags, 0);
2492 /* If the socket is marked nonblocking and
2493 * no pending connections are present on the
2494 * queue, accept fails with the error
2495 * EAGAIN or EWOULDBLOCK
2497 if (rv == VPPCOM_ETIMEDOUT)
2504 if (rv != VPPCOM_EAGAIN)
2505 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2506 "vppcom_session_accept() returned %d!", getpid (), rv);
2512 /* create a new connected socket resource and set flags
2513 * on the new file descriptor.
2514 * update vsockets and sockidx_by_fd table
2516 fd = vcom_socket_connected_socket (__fd, sid,
2517 &domain, &type, &protocol, flags);
2520 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2521 "vcom_socket_connected_socket() returned %d!",
2528 /* TBD populate __addr and __addr_len */
2529 /* TBD: The returned address is truncated if the buffer
2530 * provided is too small, in this case, __addr_len will
2531 * return a value greater than was supplied to the call.*/
2536 /* TBD populate __addr and __addr_len */
2540 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2541 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2542 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2543 addr8, sizeof (struct in_addr));
2544 /* TBD: populate __addr_len */
2547 *__addr_len = sizeof (struct sockaddr_in);
2552 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2553 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2554 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2555 __in6_u.__u6_addr8, addr8,
2556 sizeof (struct in6_addr));
2557 /* TBD: populate __addr_len */
2560 *__addr_len = sizeof (struct sockaddr_in6);
2565 return -EAFNOSUPPORT;
2573 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2574 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2575 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2576 addr8, sizeof (struct in_addr));
2577 /* TBD: populate __addr_len */
2580 *__addr_len = sizeof (struct sockaddr_in);
2585 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2586 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2587 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2588 __in6_u.__u6_addr8, addr8,
2589 sizeof (struct in6_addr));
2590 /* TBD: populate __addr_len */
2593 *__addr_len = sizeof (struct sockaddr_in6);
2598 return -EAFNOSUPPORT;
2608 vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr,
2609 socklen_t * __restrict __addr_len)
2611 /* set flags to 0 for accept() */
2612 return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0);
2616 vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr,
2617 socklen_t * __restrict __addr_len, int __flags)
2619 /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */
2620 return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags);
2623 /* TBD: move it to vppcom */
2625 vcom_session_shutdown (int __fd, int __how)
2631 vcom_socket_shutdown (int __fd, int __how)
2634 vcom_socket_main_t *vsm = &vcom_socket_main;
2636 vcom_socket_t *vsock;
2638 p = hash_get (vsm->sockidx_by_fd, __fd);
2641 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2647 rv = vcom_session_shutdown (vsock->sid, __how);
2661 vcom_socket_epoll_create1 (int __flags)
2664 vcom_socket_main_t *vsm = &vcom_socket_main;
2665 vcom_epoll_t *vepoll;
2671 epfd = vcom_socket_open_epoll (__flags);
2678 vep_idx = vppcom_epoll_create ();
2682 goto out_close_epoll;
2685 pool_get (vsm->vepolls, vepoll);
2686 vepoll_init (vepoll);
2688 epollidx = vepoll - vsm->vepolls;
2689 hash_set (vsm->epollidx_by_epfd, epfd, epollidx);
2691 vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0);
2696 vcom_socket_close_epoll (epfd);
2702 * PRE: vppcom_epoll_ctl() is successful
2703 * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put
2706 vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd,
2707 struct epoll_event *__event,
2708 i32 vep_idx, vcom_epoll_t * vepoll,
2709 i32 vfd_id, void *vfd, vcom_fd_type_t type,
2710 int free_vepitem_on_del)
2713 vcom_socket_main_t *vsm = &vcom_socket_main;
2714 vcom_epitem_t *vepitem;
2716 vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd };
2720 i32 *vepitemidxs = 0;
2722 struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD };
2726 /* perform control operations on the epoll instance */
2731 * supplied file descriptor is already
2732 * registered with this epoll instance
2734 /* vepitem exists */
2735 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2742 /* add a new vepitem */
2743 pool_get (vsm->vepitems, vepitem);
2744 vepitem_init (vepitem);
2746 vepitemidx = vepitem - vsm->vepitems;
2747 hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx);
2748 vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent);
2750 /* update epitemidxs */
2752 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2753 if (!p) /* not exist */
2756 vec_add1 (vepitemidxs, vepitemidx);
2757 hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs);
2761 vepitemidxs = *(i32 **) p;
2762 vec_add1 (vepitemidxs, vepitemidx);
2763 hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0);
2765 /* update epitemidxs */
2767 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2768 if (!p) /* not exist */
2771 vec_add1 (vepitemidxs, vepitemidx);
2772 hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs);
2776 vepitemidxs = *(i32 **) p;
2777 vec_add1 (vepitemidxs, vepitemidx);
2778 hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0);
2781 /* increment vepoll fd count by 1 */
2790 * supplied file descriptor is not
2791 * registered with this epoll instance
2793 /* vepitem not exist */
2794 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2800 vepitem = pool_elt_at_index (vsm->vepitems, p[0]);
2803 vepitem->event = *__event;
2804 vepitem->revent = revent;
2813 * supplied file descriptor is not
2814 * registered with this epoll instance
2816 /* vepitem not exist */
2817 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2823 vepitemidx = *(i32 *) p;
2824 hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key);
2826 /* update epitemidxs */
2828 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2829 if (!p) /* not exist */
2836 vepitemidxs = *(i32 **) p;
2837 vec_idx = vec_search (vepitemidxs, vepitemidx);
2840 vec_del1 (vepitemidxs, vec_idx);
2841 if (!vec_len (vepitemidxs))
2843 vec_free (vepitemidxs);
2844 hash_unset (vsm->epitemidxs_by_epfd, __epfd);
2849 /* update epitemidxs */
2851 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2852 if (!p) /* not exist */
2859 vepitemidxs = *(i32 **) p;
2860 vec_idx = vec_search (vepitemidxs, vepitemidx);
2863 vec_del1 (vepitemidxs, vec_idx);
2864 if (!vec_len (vepitemidxs))
2866 vec_free (vepitemidxs);
2867 hash_unset (vsm->epitemidxs_by_fd, __fd);
2872 /* pool put vepitem */
2873 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx);
2874 if (free_vepitem_on_del)
2881 vepitem_init (vepitem);
2882 pool_put (vsm->vepitems, vepitem);
2888 vepitem_init (vepitem);
2892 /* decrement vepoll fd count by 1 */
2910 * PRE: 00. null pointer check on __event
2911 * 01. all other parameters are validated
2915 vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd,
2916 struct epoll_event *__event,
2917 int free_vepitem_on_del)
2921 vcom_epoll_t *vepoll;
2922 vcom_socket_t *vfd_vsock;
2926 /* get vep_idx and vepoll */
2927 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
2928 if (vep_idx == INVALID_VEP_IDX)
2933 /* get vcom fd type, vfd_id and vfd */
2934 sid = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock);
2935 if ((sid != INVALID_SESSION_ID) &&
2936 vcom_socket_type_is_vppcom_bound (vfd_vsock->type))
2938 rv = vppcom_epoll_ctl (vep_idx, __op, sid, __event);
2939 if (rv == VPPCOM_OK)
2941 cnt = ((__op == EPOLL_CTL_ADD) ? 1 :
2942 (__op == EPOLL_CTL_DEL) ? -1 : 0);
2943 vepoll->count += cnt;
2944 vepoll->vcl_cnt += cnt;
2948 "[%d] vcom_socket_epoll_ctl_i: vppcom_epoll_ctl() "
2949 "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d"
2950 "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
2951 getpid (), rv, __epfd, vep_idx, __fd, sid, __op,
2952 vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
2956 rv = libc_epoll_ctl (__epfd, __op, __fd, __event);
2959 cnt = ((__op == EPOLL_CTL_ADD) ? 1 :
2960 (__op == EPOLL_CTL_DEL) ? -1 : 0);
2961 vepoll->count += cnt;
2962 vepoll->libc_cnt += cnt;
2966 "[%d] vcom_socket_epoll_ctl_i: libc_epoll_ctl() "
2967 "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d"
2968 "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
2969 getpid (), rv, __epfd, vep_idx, __fd, sid, __op,
2970 vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
2977 vcom_socket_epoll_ctl (int __epfd, int __op, int __fd,
2978 struct epoll_event *__event)
2982 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1);
2987 vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd,
2988 struct epoll_event *__event)
2992 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0);
2997 vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events,
2998 int __maxevents, int __timeout,
2999 const __sigset_t * __ss)
3001 vcom_socket_main_t *vsm = &vcom_socket_main;
3004 double time_to_wait = (double) 0;
3005 double timeout, now = 0;
3006 vcom_epoll_t *vepoll;
3008 static struct epoll_event *libc_ev = 0;
3010 /* validate __event */
3011 if (!__events || (__timeout < -1))
3013 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: "
3014 "Bad args __events %p, __timeout %d\n", getpid (),
3015 __events, __timeout);
3020 time_to_wait = ((__timeout >= 0) ? (double) __timeout / (double) 1000 : 0);
3022 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
3023 if (vep_idx == INVALID_VEP_IDX)
3025 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: "
3026 "Bad epoll fd %d\n", getpid (), __epfd);
3030 if (vepoll->count <= 0)
3032 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: No events"
3033 " in epfd!\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
3034 getpid (), vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
3039 if (vepoll->libc_cnt == 0)
3042 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: libc_cnt = 0, "
3043 "calling vppcom_epoll_wait() time_to_wait = %f\n",
3044 getpid (), time_to_wait);
3045 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait);
3047 else if (vepoll->vcl_cnt == 0)
3050 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = 0, "
3051 "calling libc_epoll_pwait()\n", getpid ());
3052 rv = libc_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss);
3057 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = %d, "
3058 "libc_cnt = %d -> mixed polling (time_to_wait = %f, "
3059 "__timeout = %d)\n",
3060 getpid (), vepoll->vcl_cnt, vepoll->libc_cnt,
3061 time_to_wait, __timeout);
3062 vec_validate (libc_ev, __maxevents);
3063 timeout = clib_time_now (&vsm->clib_time) + time_to_wait;
3066 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, 0);
3067 rv2 = libc_epoll_pwait (__epfd, libc_ev, __maxevents, 1, __ss);
3068 if (VCOM_DEBUG == 666)
3069 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: "
3070 "rv = %d, rv2 = %d, timeout = %f, now = %f\n",
3071 getpid (), rv, rv2, timeout, now);
3072 if ((rv > 0) || (rv2 > 0))
3075 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: "
3076 "rv = %d, rv2 = %d\n", getpid (), rv, rv2);
3077 int n = __maxevents - rv;
3078 n = rv2 <= n ? rv2 : n;
3079 rv = (rv > 0) ? rv : 0;
3081 clib_memcpy (&__events[rv], libc_ev, n * sizeof (*libc_ev));
3085 else if ((rv < 0) || (rv2 < 0))
3089 "[%d] ERROR: vppcom_epoll_wait() returned %d\n",
3094 "[%d] ERROR: libc_epoll_wait() failed, errno %d\n",
3096 rv = (rv < 0) ? rv : -errno;
3100 if (__timeout != -1)
3101 now = clib_time_now (&vsm->clib_time);
3103 while (now < timeout);
3107 vec_reset_length (libc_ev);
3112 vcom_pollfds_2_selectfds (
3114 struct pollfd *__fds, nfds_t __nfds,
3117 fd_set * __restrict vcom_readfds,
3118 fd_set * __restrict vcom_writefds,
3119 fd_set * __restrict vcom_exceptfds)
3123 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3125 /* ignore negative fds */
3126 if (__fds[fds_idx].fd < 0)
3131 /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
3132 FD_SET (__fds[fds_idx].fd, vcom_exceptfds);
3134 /* requested events */
3135 if (__fds[fds_idx].events)
3137 if (__fds[fds_idx].events & POLLIN)
3139 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3141 if (__fds[fds_idx].events & POLLPRI)
3143 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3145 if (__fds[fds_idx].events & POLLOUT)
3147 FD_SET (__fds[fds_idx].fd, vcom_writefds);
3149 #if defined __USE_XOPEN || defined __USE_XOPEN2K8
3150 if (__fds[fds_idx].events & POLLRDNORM)
3152 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3154 if (__fds[fds_idx].events & POLLRDBAND)
3156 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3158 if (__fds[fds_idx].events & POLLWRNORM)
3160 FD_SET (__fds[fds_idx].fd, vcom_writefds);
3162 if (__fds[fds_idx].events & POLLWRBAND)
3164 FD_SET (__fds[fds_idx].fd, vcom_writefds);
3168 } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
3172 vcom_selectfds_2_pollfds (
3174 struct pollfd *__fds, nfds_t __nfds, int *nfd,
3177 fd_set * __restrict vcom_readfds,
3178 fd_set * __restrict vcom_writefds,
3179 fd_set * __restrict vcom_exceptfds)
3184 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3186 /* ignore negative fds */
3187 if (__fds[fds_idx].fd < 0)
3189 __fds[fds_idx].revents = 0;
3192 /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
3193 if (FD_ISSET (__fds[fds_idx].fd, vcom_exceptfds))
3196 * TBD: for now any select exception
3197 * is flagged as POLLERR
3199 __fds[fds_idx].revents |= POLLERR;
3202 /* requested events */
3203 if (__fds[fds_idx].events & POLLIN)
3205 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3207 __fds[fds_idx].revents |= POLLIN;
3210 if (__fds[fds_idx].events & POLLPRI)
3212 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3214 __fds[fds_idx].revents |= POLLIN;
3217 if (__fds[fds_idx].events & POLLOUT)
3219 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3221 __fds[fds_idx].revents |= POLLOUT;
3224 #if defined __USE_XOPEN || defined __USE_XOPEN2K8
3225 if (__fds[fds_idx].events & POLLRDNORM)
3227 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3229 __fds[fds_idx].revents |= POLLRDNORM;
3232 if (__fds[fds_idx].events & POLLRDBAND)
3234 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3236 __fds[fds_idx].revents |= POLLRDBAND;
3239 if (__fds[fds_idx].events & POLLWRNORM)
3241 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3243 __fds[fds_idx].revents |= POLLWRNORM;
3246 if (__fds[fds_idx].events & POLLWRBAND)
3248 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3250 __fds[fds_idx].revents |= POLLWRBAND;
3254 } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
3258 * the number of structures which have nonzero revents fields
3259 * (in other words, those descriptors with events or
3263 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3265 /* ignore negative fds */
3266 if (__fds[fds_idx].fd < 0)
3271 if (__fds[fds_idx].revents)
3279 * PRE: parameters are validated,
3280 * vcom_socket_poll is always called with __timeout set to zero
3281 * hence returns immediately
3283 * ACTION: handle non negative validated vcom fds and ignore rest
3287 * implements vcom_socket_poll () interface
3289 * internally uses vcom_socket_select ()
3290 * to realize the behavior
3293 vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds,
3303 fd_set vcom_readfds;
3304 fd_set vcom_writefds;
3305 fd_set vcom_exceptfds;
3307 /* invalid max_vcom_fd is -1 */
3308 int max_vcom_fd = -1;
3310 /* __timeout is zero to get ready events and return immediately */
3311 struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
3313 /* validate __nfds from select perspective */
3314 if (__nfds > FD_SETSIZE)
3320 /* zero vcom fd sets */
3336 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3338 /* ignore negative fds */
3339 if (__fds[fds_idx].fd < 0)
3344 /* non negative validated vcom fds */
3345 if (__fds[fds_idx].fd > FD_SETSIZE)
3351 /* max_vcom_fd and vcom_nfd */
3352 if (__fds[fds_idx].fd > max_vcom_fd)
3354 /* requested events */
3355 if (__fds[fds_idx].events)
3357 max_vcom_fd = __fds[fds_idx].fd;
3363 vcom_nfds = max_vcom_fd != -1 ? max_vcom_fd + 1 : 0;
3371 vcom_pollfds_2_selectfds (
3376 &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
3378 /* select on vcom fds */
3379 vcom_nfd = vcom_socket_select (vcom_nfds,
3381 &vcom_writefds, &vcom_exceptfds, &tv);
3384 "[%d] vcom_socket_select: "
3385 "'%04d'='%04d'\n", getpid (), vcom_nfd, vcom_nfds);
3393 vcom_selectfds_2_pollfds (
3395 __fds, __nfds, &nfd,
3398 &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
3407 * TBD: remove this static function once vppcom
3408 * has an implementation in place
3413 vppcom_poll (struct pollfd *__fds, nfds_t __nfds, double time_to_wait)
3419 vcom_socket_poll_vppcom_impl (struct pollfd *__fds, nfds_t __nfds,
3424 /* in seconds eg. 3.123456789 seconds */
3425 double time_to_wait = (double) 0;
3430 /* replace vcom fd with session idx */
3431 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3433 /* ignore negative fds */
3434 if (__fds[fds_idx].fd < 0)
3439 /* non negative validated vcom fds */
3440 sid = vcom_socket_get_sid (__fds[fds_idx].fd);
3441 if (sid != INVALID_SESSION_ID)
3443 __fds[fds_idx].fd = sid;
3448 vep_idx = vcom_socket_get_vep_idx (__fds[fds_idx].fd);
3449 if (vep_idx != INVALID_VEP_IDX)
3451 __fds[fds_idx].fd = vep_idx;
3460 /* validate __timeout */
3463 time_to_wait = (double) __timeout / (double) 1000;
3465 else if (__timeout == 0)
3467 time_to_wait = (double) 0;
3474 return vppcom_poll (__fds, __nfds, time_to_wait);
3478 vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
3480 /* select an implementation */
3482 /* return vcom_socket_poll_vppcom_impl (__fds, __nfds, __timeout); */
3483 return vcom_socket_poll_select_impl (__fds, __nfds, __timeout);
3488 vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds,
3489 const struct timespec *__timeout, const __sigset_t * __ss)
3496 vcom_socket_main_init (void)
3498 vcom_socket_main_t *vsm = &vcom_socket_main;
3501 printf ("vcom_socket_main_init\n");
3505 /* TBD: define FD_MAXSIZE and use it here */
3506 pool_alloc (vsm->vsockets, FD_SETSIZE);
3507 vsm->sockidx_by_fd = hash_create (0, sizeof (i32));
3509 pool_alloc (vsm->vepolls, FD_SETSIZE);
3510 vsm->epollidx_by_epfd = hash_create (0, sizeof (i32));
3512 pool_alloc (vsm->vepitems, FD_SETSIZE);
3513 vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32));
3515 vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *));
3516 vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *));
3518 clib_time_init (&vsm->clib_time);
3528 vcom_socket_main_show (void)
3530 vcom_socket_main_t *vsm = &vcom_socket_main;
3531 vcom_socket_t *vsock;
3533 vcom_epoll_t *vepoll;
3535 vcom_epitem_t *vepitem;
3539 i32 *vepitemidxs, *vepitemidxs_var;
3543 /* from active list of vsockets show vsock */
3546 pool_foreach (vsock, vsm->vsockets,
3549 "fd='%04d', sid='%08x',type='%-30s'\n",
3550 vsock->fd, vsock->sid,
3551 vcom_socket_type_str (vsock->type));
3555 /* from active list of vepolls, show vepoll */
3558 pool_foreach (vepoll, vsm->vepolls,
3561 "epfd='%04d', vep_idx='%08x', "
3563 "flags='%d', count='%d', close='%d'\n",
3564 vepoll->epfd, vepoll->vep_idx,
3565 vcom_socket_epoll_type_str (vepoll->type),
3566 vepoll->flags, vepoll->count, vepoll->close);
3570 /* from active list of vepitems, show vepitem */
3573 pool_foreach (vepitem, vsm->vepitems,
3576 "epfd='%04d', fd='%04d', "
3577 "next_fd='%04d', prev_fd='%04d', "
3579 "events='%04x', revents='%04x'\n",
3580 vepitem->epfd, vepitem->fd,
3581 vepitem->next_fd, vepitem->prev_fd,
3582 vcom_socket_vcom_fd_type_str (vepitem->type),
3583 vepitem->event.events, vepitem->revent.events);
3588 /* show epitemidxs for epfd */
3590 hash_foreach (epfd, vepitemidxs,
3591 vsm->epitemidxs_by_epfd,
3593 printf("\n[ '%04d': ", epfd);
3594 vec_foreach (vepitemidxs_var,vepitemidxs)
3596 printf("'%04d' ", (int)vepitemidxs_var[0]);
3602 /* show epitemidxs for fd */
3604 hash_foreach (fd, vepitemidxs,
3605 vsm->epitemidxs_by_fd,
3607 printf("\n{ '%04d': ", fd);
3608 vec_foreach (vepitemidxs_var,vepitemidxs)
3610 printf("'%04d' ", (int)vepitemidxs_var[0]);
3620 vcom_socket_main_destroy (void)
3622 vcom_socket_main_t *vsm = &vcom_socket_main;
3623 vcom_socket_t *vsock;
3625 vcom_epoll_t *vepoll;
3627 vcom_epitem_t *vepitem;
3635 printf ("vcom_socket_main_destroy\n");
3641 * from active list of vepitems,
3642 * remove all "vepitem" elements from the pool in a safe way
3646 pool_flush (vepitem, vsm->vepitems,
3648 if ((vepitem->type == FD_TYPE_EPOLL) ||
3649 (vepitem->type == FD_TYPE_VCOM_SOCKET))
3651 vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL,
3653 vepitem_init (vepitem);
3658 pool_free (vsm->vepitems);
3659 hash_free (vsm->epitemidx_by_epfdfd);
3661 /* free vepitemidxs for each epfd */
3663 hash_foreach (epfd, vepitemidxs,
3664 vsm->epitemidxs_by_epfd,
3666 vec_free (vepitemidxs);
3669 hash_free (vsm->epitemidxs_by_epfd);
3671 /* free vepitemidxs for each fd */
3673 hash_foreach (fd, vepitemidxs,
3674 vsm->epitemidxs_by_fd,
3676 vec_free (vepitemidxs);
3679 hash_free (vsm->epitemidxs_by_fd);
3683 * from active list of vsockets,
3684 * close socket and vppcom session
3688 pool_foreach (vsock, vsm->vsockets,
3690 if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
3692 vppcom_session_close (vsock->sid);
3693 vcom_socket_close_socket (vsock->fd);
3694 vsocket_init (vsock);
3700 * return vsocket element to the pool
3704 pool_flush (vsock, vsm->vsockets,
3706 // vsocket_init(vsock);
3711 pool_free (vsm->vsockets);
3712 hash_free (vsm->sockidx_by_fd);
3715 * from active list of vepolls,
3716 * close epoll and vppcom_epoll
3720 pool_foreach (vepoll, vsm->vepolls,
3722 if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
3724 vppcom_session_close (vepoll->vep_idx);
3725 vcom_socket_close_epoll (vepoll->epfd); /* TBD: */
3726 vepoll_init (vepoll);
3732 * return vepoll element to the pool
3736 pool_flush (vepoll, vsm->vepolls,
3738 // vepoll_init(vepoll);
3743 pool_free (vsm->vepolls);
3744 hash_free (vsm->epollidx_by_epfd);
3752 * fd.io coding-style-patch-verification: ON
3755 * eval: (c-set-style "gnu")