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/hash.h>
25 #include <vppinfra/pool.h>
27 #include <libvcl-ldpreload/vcom_socket.h>
28 #include <libvcl-ldpreload/vcom_socket_wrapper.h>
29 #include <libvcl-ldpreload/vcom.h>
31 #include <uri/vppcom.h>
35 * VCOM_SOCKET Private definitions and functions.
38 typedef struct vcom_socket_main_t_
42 /* vcom_socket pool */
43 vcom_socket_t *vsockets;
45 /* Hash table for socketidx to fd mapping */
49 vcom_epoll_t *vepolls;
51 /* Hash table for epollidx to epfd mapping */
52 uword *epollidx_by_epfd;
55 /* common epitem poll for all epfd */
56 /* TBD: epitem poll per epfd */
57 /* vcom_epitem pool */
58 vcom_epitem_t *vepitems;
60 /* Hash table for epitemidx to epfdfd mapping */
61 uword *epitemidx_by_epfdfd;
63 /* Hash table - key:epfd, value:vec of epitemidx */
64 uword *epitemidxs_by_epfd;
65 /* Hash table - key:fd, value:vec of epitemidx */
66 uword *epitemidxs_by_fd;
70 vcom_socket_main_t vcom_socket_main;
74 vcom_socket_open_socket (int domain, int type, int protocol)
78 /* handle domains implemented by vpp */
83 /* get socket type and
84 * handle the socket types supported by vpp */
85 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
89 /* the type argument serves a second purpose,
90 * in addition to specifying a socket type,
91 * it may include the bitwise OR of any of
92 * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify
93 * the behavior of socket. */
94 rv = libc_socket (domain, type, protocol);
113 vcom_socket_open_epoll (int flags)
121 if (flags && (flags & ~EPOLL_CLOEXEC))
126 /* flags can be either zero or EPOLL_CLOEXEC */
127 rv = libc_epoll_create1 (flags);
135 vcom_socket_close_socket (int fd)
139 rv = libc_close (fd);
147 vcom_socket_close_epoll (int epfd)
151 rv = libc_close (epfd);
159 * Public API functions
164 vcom_socket_is_vcom_fd (int fd)
166 vcom_socket_main_t *vsm = &vcom_socket_main;
168 vcom_socket_t *vsock;
170 p = hash_get (vsm->sockidx_by_fd, fd);
174 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
175 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
182 vcom_socket_is_vcom_epfd (int epfd)
184 vcom_socket_main_t *vsm = &vcom_socket_main;
186 vcom_epoll_t *vepoll;
188 p = hash_get (vsm->epollidx_by_epfd, epfd);
192 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
193 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
200 vcom_socket_get_sid (int fd)
202 vcom_socket_main_t *vsm = &vcom_socket_main;
204 vcom_socket_t *vsock;
206 p = hash_get (vsm->sockidx_by_fd, fd);
210 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
211 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
214 return INVALID_SESSION_ID;
218 vcom_socket_get_vep_idx (int epfd)
220 vcom_socket_main_t *vsm = &vcom_socket_main;
222 vcom_epoll_t *vepoll;
224 p = hash_get (vsm->epollidx_by_epfd, epfd);
228 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
229 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
230 return vepoll->vep_idx;
232 return INVALID_VEP_IDX;
236 vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp)
238 vcom_socket_main_t *vsm = &vcom_socket_main;
240 vcom_socket_t *vsock;
242 p = hash_get (vsm->sockidx_by_fd, fd);
246 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
247 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
253 return INVALID_SESSION_ID;
257 vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp)
259 vcom_socket_main_t *vsm = &vcom_socket_main;
261 vcom_epoll_t *vepoll;
263 p = hash_get (vsm->epollidx_by_epfd, epfd);
267 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
268 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
271 return vepoll->vep_idx;
274 return INVALID_VEP_IDX;
279 vcom_socket_close_vepoll (int epfd)
282 vcom_socket_main_t *vsm = &vcom_socket_main;
284 vcom_epoll_t *vepoll;
286 p = hash_get (vsm->epollidx_by_epfd, epfd);
290 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
294 if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND)
311 rv = vppcom_session_close (vepoll->vep_idx);
312 rv = vcom_socket_close_epoll (vepoll->epfd);
314 vepoll_init (vepoll);
315 hash_unset (vsm->epollidx_by_epfd, epfd);
316 pool_put (vsm->vepolls, vepoll);
322 vcom_socket_close_vsock (int fd)
325 vcom_socket_main_t *vsm = &vcom_socket_main;
327 vcom_socket_t *vsock;
329 vcom_epitem_t *vepitem;
331 i32 *vepitemidxs = 0;
332 i32 *vepitemidxs_var = 0;
334 p = hash_get (vsm->sockidx_by_fd, fd);
338 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
342 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
345 rv = vppcom_session_close (vsock->sid);
346 rv = vcom_socket_close_socket (vsock->fd);
348 vsocket_init (vsock);
349 hash_unset (vsm->sockidx_by_fd, fd);
350 pool_put (vsm->vsockets, vsock);
354 * Before calling close(), user should remove
355 * this fd from the epoll-set of all epoll instances,
356 * otherwise resource(epitems) leaks ensues.
360 * 00. close all epoll instances that are marked as "close"
361 * of which this fd is the "last" remaining member.
362 * 01. epitems associated with this fd are intentionally
363 * not removed, see NOTE: above.
366 /* does this fd participate in epoll */
367 p = hash_get (vsm->epitemidxs_by_fd, fd);
370 vepitemidxs = *(i32 **) p;
371 vec_foreach (vepitemidxs_var, vepitemidxs)
373 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]);
374 if (vepitem && vepitem->fd == fd &&
375 vepitem->type == FD_TYPE_VCOM_SOCKET)
378 vcom_epoll_t *vepoll;
380 vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd,
386 if (vepoll->count == 1)
389 * force count to zero and
390 * close this epoll instance
393 vcom_socket_close_vepoll (vepoll->epfd);
410 vcom_socket_close (int __fd)
414 if (vcom_socket_is_vcom_fd (__fd))
416 rv = vcom_socket_close_vsock (__fd);
418 else if (vcom_socket_is_vcom_epfd (__fd))
420 rv = vcom_socket_close_vepoll (__fd);
431 vcom_socket_read (int __fd, void *__buf, size_t __nbytes)
434 vcom_socket_main_t *vsm = &vcom_socket_main;
436 vcom_socket_t *vsock;
438 p = hash_get (vsm->sockidx_by_fd, __fd);
442 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
446 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
449 if (!__buf || __nbytes < 0)
454 rv = vcom_fcntl (__fd, F_GETFL, 0);
462 if (!(rv & O_NONBLOCK))
466 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
468 while (rv == -EAGAIN || rv == -EWOULDBLOCK);
471 /* The file descriptor refers to a socket and has been
472 * marked nonblocking(O_NONBLOCK) and the read would
475 /* is non blocking */
476 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
481 vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt)
484 vcom_socket_main_t *vsm = &vcom_socket_main;
486 vcom_socket_t *vsock;
487 ssize_t total = 0, len = 0;
489 p = hash_get (vsm->sockidx_by_fd, __fd);
493 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
497 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
500 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
504 for (int i = 0; i < __iovcnt; ++i)
506 if (SSIZE_MAX - len < __iov[i].iov_len)
508 len += __iov[i].iov_len;
511 rv = vcom_fcntl (__fd, F_GETFL, 0);
518 if (!(rv & O_NONBLOCK))
522 for (int i = 0; i < __iovcnt; ++i)
524 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
531 if (rv < __iov[i].iov_len)
532 /* Read less than buffer provided, no point to continue */
537 while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0);
541 /* is non blocking */
542 for (int i = 0; i < __iovcnt; ++i)
544 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
559 if (rv < __iov[i].iov_len)
560 /* Read less than buffer provided, no point to continue */
568 vcom_socket_write (int __fd, const void *__buf, size_t __n)
571 vcom_socket_main_t *vsm = &vcom_socket_main;
573 vcom_socket_t *vsock;
575 p = hash_get (vsm->sockidx_by_fd, __fd);
579 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
583 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
586 if (!__buf || __n < 0)
591 rv = vppcom_session_write (vsock->sid, (void *) __buf, __n);
596 vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt)
600 vcom_socket_main_t *vsm = &vcom_socket_main;
602 vcom_socket_t *vsock;
604 p = hash_get (vsm->sockidx_by_fd, __fd);
608 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
612 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
615 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
618 for (int i = 0; i < __iovcnt; ++i)
620 rv = vppcom_session_write (vsock->sid, __iov[i].iov_base,
636 * RETURN: 0 - invalid cmd
637 * 1 - cmd not handled by vcom and vppcom
638 * 2 - cmd handled by vcom socket resource
639 * 3 - cmd handled by vppcom
641 /* TBD: incomplete list of cmd */
643 vcom_socket_check_fcntl_cmd (int __cmd)
647 /*cmd not handled by vcom and vppcom */
650 case F_DUPFD_CLOEXEC:
653 /* cmd handled by vcom socket resource */
664 /* cmd handled by vcom and vppcom */
669 /* cmd not handled by vcom and vppcom */
677 vppcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
679 int flags = va_arg (__ap, int);
680 int rv = -EOPNOTSUPP;
683 size = sizeof (flags);
684 if (__cmd == F_SETFL)
686 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
688 else if (__cmd == F_GETFL)
690 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
699 vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap)
702 vcom_socket_main_t *vsm = &vcom_socket_main;
704 vcom_socket_t *vsock;
706 p = hash_get (vsm->sockidx_by_fd, __fd);
710 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
714 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
717 switch (vcom_socket_check_fcntl_cmd (__cmd))
723 /*cmd not handled by vcom and vppcom */
725 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
727 /* cmd handled by vcom socket resource */
729 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
731 /* cmd handled by vppcom */
733 rv = vppcom_session_fcntl_va (vsock->sid, __cmd, __ap);
745 * RETURN: 0 - invalid cmd
746 * 1 - cmd not handled by vcom and vppcom
747 * 2 - cmd handled by vcom socket resource
748 * 3 - cmd handled by vppcom
751 vcom_socket_check_ioctl_cmd (unsigned long int __cmd)
757 /* cmd handled by vppcom */
762 /* cmd not handled by vcom and vppcom */
771 vppcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
775 if (__cmd == FIONREAD)
776 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
783 vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
786 vcom_socket_main_t *vsm = &vcom_socket_main;
788 vcom_socket_t *vsock;
790 p = hash_get (vsm->sockidx_by_fd, __fd);
794 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
798 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
801 switch (vcom_socket_check_ioctl_cmd (__cmd))
803 /* Not supported cmd */
808 /* cmd not handled by vcom and vppcom */
810 rv = libc_vioctl (vsock->fd, __cmd, __ap);
813 /* cmd handled by vcom socket resource */
815 rv = libc_vioctl (vsock->fd, __cmd, __ap);
818 /* cmd handled by vppcom */
820 rv = vppcom_session_ioctl_va (vsock->sid, __cmd, __ap);
832 vcom_socket_fds_2_sid_fds (
835 fd_set * __restrict vcom_rd_sid_fds,
836 fd_set * __restrict vcom_wr_sid_fds,
837 fd_set * __restrict vcom_ex_sid_fds,
840 fd_set * __restrict vcom_readfds,
841 fd_set * __restrict vcom_writefds,
842 fd_set * __restrict vcom_exceptfds)
847 /* invalid max_sid is -1 */
852 * set sid in sid sets corresponding to fd's in fd sets
853 * compute nsid and vcom_nsid_fds from sid sets
856 for (fd = 0; fd < vcom_nfds; fd++)
863 if ((F) && (S) && FD_ISSET (fd, (F))) \
865 sid = vcom_socket_get_sid (fd); \
866 if (sid != INVALID_SESSION_ID) \
883 _(vcom_rd_sid_fds, vcom_readfds);
884 _(vcom_wr_sid_fds, vcom_writefds);
885 _(vcom_ex_sid_fds, vcom_exceptfds);
889 *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0;
897 * PRE: 00. sid sets were derived from fd sets
898 * 01. sid sets were updated with sids that actually changed
900 * 02. fd sets still has watched fds
902 * This function will modify in place fd sets to indicate which fd's
903 * actually changed status(inferred from sid sets)
906 vcom_socket_sid_fds_2_fds (
910 fd_set * __restrict vcom_readfds,
911 fd_set * __restrict vcom_writefds,
912 fd_set * __restrict vcom_exceptfds,
915 fd_set * __restrict vcom_rd_sid_fds,
916 fd_set * __restrict vcom_wr_sid_fds,
917 fd_set * __restrict vcom_ex_sid_fds)
922 /* invalid max_fd is -1 */
928 * modify in place fd sets to indicate which fd's
929 * actually changed status(inferred from sid sets)
931 for (fd = 0; fd < vcom_nfds; fd++)
938 if ((F) && (S) && FD_ISSET (fd, (F))) \
940 sid = vcom_socket_get_sid (fd); \
941 if (sid != INVALID_SESSION_ID) \
943 if (!FD_ISSET (sid, (S))) \
956 _(vcom_rd_sid_fds, vcom_readfds);
957 _(vcom_wr_sid_fds, vcom_writefds);
958 _(vcom_ex_sid_fds, vcom_exceptfds);
963 * compute nfd and new_vcom_nfds from fd sets
965 for (fd = 0; fd < vcom_nfds; fd++)
969 if ((F) && FD_ISSET (fd, (F))) \
986 *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0;
995 * vom_socket_select is always called with
996 * timeout->tv_sec and timeout->tv_usec set to zero.
997 * hence vppcom_select return immediately.
1000 * TBD: do{body;} while(timeout conditional); timeout loop
1003 vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds,
1004 fd_set * __restrict vcom_writefds,
1005 fd_set * __restrict vcom_exceptfds,
1006 struct timeval *__restrict timeout)
1009 pid_t pid = getpid ();
1011 int new_vcom_nfds = 0;
1012 int new_vcom_nfd = 0;
1015 fd_set vcom_rd_sid_fds;
1016 fd_set vcom_wr_sid_fds;
1017 fd_set vcom_ex_sid_fds;
1018 unsigned long vcom_nsid_fds = 0;
1021 /* in seconds eg. 3.123456789 seconds */
1022 double time_to_wait = (double) 0;
1024 /* validate inputs */
1030 /* convert timeval timeout to double time_to_wait */
1033 if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
1035 /* polling: vppcom_select returns immediately */
1036 time_to_wait = (double) 0;
1040 /*TBD: use timeval api */
1041 time_to_wait = (double) timeout->tv_sec +
1042 (double) timeout->tv_usec / (double) 1000000 +
1043 (double) (timeout->tv_usec % 1000000) / (double) 1000000;
1049 * no timeout: vppcom_select can block indefinitely
1050 * waiting for a file descriptor to become ready
1052 /* set to a phantom value */
1056 /* zero the sid_sets */
1068 _(&vcom_rd_sid_fds, vcom_readfds);
1069 _(&vcom_wr_sid_fds, vcom_writefds);
1070 _(&vcom_ex_sid_fds, vcom_exceptfds);
1073 /* populate read, write and except sid_sets */
1074 vcom_nsid = vcom_socket_fds_2_sid_fds (
1076 vcom_readfds || vcom_writefds
1077 || vcom_exceptfds ? (int *)
1078 &vcom_nsid_fds : NULL,
1079 vcom_readfds ? &vcom_rd_sid_fds :
1081 vcom_writefds ? &vcom_wr_sid_fds :
1083 vcom_exceptfds ? &vcom_ex_sid_fds :
1088 vcom_writefds, vcom_exceptfds);
1093 if (vcom_nsid_fds < 0)
1098 rv = vppcom_select (vcom_nsid_fds,
1099 vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds :
1101 vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds :
1103 vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
1104 NULL, time_to_wait);
1106 fprintf (stderr, "[%d] vppcom_select: "
1107 "'%04d'='%04d'\n", pid, rv, (int) vcom_nsid_fds);
1109 /* check if any file descriptors changed status */
1113 * on exit, sets are modified in place to indicate which
1114 * file descriptors actually changed status
1118 * comply with pre-condition
1119 * do not clear vcom fd sets befor calling
1120 * vcom_socket_sid_fds_2_fds
1122 new_vcom_nfd = vcom_socket_sid_fds_2_fds (
1132 &vcom_rd_sid_fds : NULL,
1134 &vcom_wr_sid_fds : NULL,
1136 &vcom_ex_sid_fds : NULL);
1137 if (new_vcom_nfd < 0)
1139 return new_vcom_nfd;
1141 if (new_vcom_nfds < 0)
1152 vcom_socket_socket (int __domain, int __type, int __protocol)
1155 vcom_socket_main_t *vsm = &vcom_socket_main;
1156 vcom_socket_t *vsock;
1161 u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0;
1162 int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
1164 fd = vcom_socket_open_socket (__domain, __type, __protocol);
1171 sid = vppcom_session_create (VPPCOM_VRF_DEFAULT,
1172 (type == SOCK_DGRAM) ?
1173 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP,
1178 goto out_close_socket;
1181 pool_get (vsm->vsockets, vsock);
1182 vsocket_init (vsock);
1184 sockidx = vsock - vsm->vsockets;
1185 hash_set (vsm->sockidx_by_fd, fd, sockidx);
1187 vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND);
1191 vcom_socket_close_socket (fd);
1197 vcom_socket_socketpair (int __domain, int __type, int __protocol,
1205 vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1208 vcom_socket_main_t *vsm = &vcom_socket_main;
1210 vcom_socket_t *vsock;
1214 p = hash_get (vsm->sockidx_by_fd, __fd);
1218 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1222 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1230 ep.vrf = VPPCOM_VRF_DEFAULT;
1231 switch (__addr->sa_family)
1234 if (__len != sizeof (struct sockaddr_in))
1238 ep.is_ip4 = VPPCOM_IS_IP4;
1239 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1240 ep.port = (u16) ((const struct sockaddr_in *) __addr)->sin_port;
1244 if (__len != sizeof (struct sockaddr_in6))
1248 ep.is_ip4 = VPPCOM_IS_IP6;
1249 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1250 ep.port = (u16) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1258 rv = vppcom_session_bind (vsock->sid, &ep);
1259 /* TBD: remove libc_bind code snippet
1260 * once vppcom implements vppcom_session_getsockname */
1263 rv = libc_bind (__fd, __addr, __len);
1273 vppcom_session_getsockname (int sid, vppcom_endpt_t * ep)
1276 uint32_t size = sizeof (*ep);
1278 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, ep, &size);
1283 vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr,
1284 socklen_t * __restrict __len)
1287 vcom_socket_main_t *vsm = &vcom_socket_main;
1289 vcom_socket_t *vsock;
1292 p = hash_get (vsm->sockidx_by_fd, __fd);
1296 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1300 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1303 if (!__addr || !__len)
1312 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1313 rv = vppcom_session_getsockname (vsock->sid, &ep);
1316 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1318 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1319 switch (__addr->sa_family)
1322 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1323 *__len = sizeof (struct sockaddr_in);
1327 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1328 *__len = sizeof (struct sockaddr_in6);
1341 vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1344 vcom_socket_main_t *vsm = &vcom_socket_main;
1346 vcom_socket_t *vsock;
1350 p = hash_get (vsm->sockidx_by_fd, __fd);
1353 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1355 ep.vrf = VPPCOM_VRF_DEFAULT;
1356 switch (__addr->sa_family)
1359 ep.is_ip4 = VPPCOM_IS_IP4;
1361 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1363 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1367 ep.is_ip4 = VPPCOM_IS_IP6;
1369 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1371 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1379 rv = vppcom_session_connect (vsock->sid, &ep);
1385 vppcom_session_getpeername (int sid, vppcom_endpt_t * ep)
1388 uint32_t size = sizeof (*ep);
1390 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size);
1395 vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr,
1396 socklen_t * __restrict __len)
1399 vcom_socket_main_t *vsm = &vcom_socket_main;
1401 vcom_socket_t *vsock;
1404 p = hash_get (vsm->sockidx_by_fd, __fd);
1408 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1412 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1415 if (!__addr || !__len)
1423 /* DAW: hack to allow iperf3 to be happy w/ getpeername output */
1426 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
1427 ((struct sockaddr_in *) __addr)->sin_port = 0x1000;
1428 a = (uint8_t *) & ((struct sockaddr_in *) __addr)->sin_addr;
1433 *__len = sizeof (struct sockaddr_in);
1438 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1439 rv = vppcom_session_getpeername (vsock->sid, &ep);
1442 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1444 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1445 switch (__addr->sa_family)
1448 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1449 *__len = sizeof (struct sockaddr_in);
1453 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1454 *__len = sizeof (struct sockaddr_in6);
1467 vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags)
1469 return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0);
1473 vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags)
1476 rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0);
1481 * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET),
1485 vcom_socket_is_connection_mode_socket (int __fd)
1488 /* TBD define new vppcom api */
1489 vcom_socket_main_t *vsm = &vcom_socket_main;
1491 vcom_socket_t *vsock;
1496 p = hash_get (vsm->sockidx_by_fd, __fd);
1500 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1501 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
1503 optlen = sizeof (type);
1504 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
1509 /* get socket type */
1510 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1513 case SOCK_SEQPACKET:
1527 vvppcom_session_sendto (int __sid, const void *__buf, size_t __n,
1528 int __flags, __CONST_SOCKADDR_ARG __addr,
1529 socklen_t __addr_len)
1532 /* TBD add new vpp api */
1533 /* TBD add flags parameter */
1534 rv = vppcom_session_write (__sid, (void *) __buf, (int) __n);
1539 vcom_socket_sendto (int __fd, const void *__buf, size_t __n,
1540 int __flags, __CONST_SOCKADDR_ARG __addr,
1541 socklen_t __addr_len)
1544 vcom_socket_main_t *vsm = &vcom_socket_main;
1546 vcom_socket_t *vsock;
1548 p = hash_get (vsm->sockidx_by_fd, __fd);
1552 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1556 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1559 if (!__buf || __n < 0)
1564 if (vcom_socket_is_connection_mode_socket (__fd))
1566 /* ignore __addr and _addr_len */
1567 /* and EISCONN may be returned when they are not NULL and 0 */
1568 if ((__addr != NULL) || (__addr_len != 0))
1575 if (!__addr || __addr_len < 0)
1577 return -EDESTADDRREQ;
1579 /* not a vppcom supported address family */
1580 if ((__addr->sa_family != AF_INET) || (__addr->sa_family != AF_INET6))
1586 rv = vvppcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
1587 __flags, __addr, __addr_len);
1591 /* TBD: move it to vppcom */
1593 vppcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
1594 int __flags, __SOCKADDR_ARG __addr,
1595 socklen_t * __restrict __addr_len)
1599 /* TBD add flags parameter */
1600 rv = vppcom_session_read (__sid, __buf, __n);
1605 vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
1606 int __flags, __SOCKADDR_ARG __addr,
1607 socklen_t * __restrict __addr_len)
1610 vcom_socket_main_t *vsm = &vcom_socket_main;
1612 vcom_socket_t *vsock;
1614 p = hash_get (vsm->sockidx_by_fd, __fd);
1618 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1622 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1625 if (!__buf || __n < 0)
1630 if (__addr || __addr_len < 0)
1635 rv = vppcom_session_recvfrom (vsock->sid, __buf, __n,
1636 __flags, __addr, __addr_len);
1640 /* TBD: move it to vppcom */
1642 vppcom_sendmsg (int __sid, const struct msghdr *__message, int __flags)
1645 /* rv = vppcom_session_write (__sid, (void *) __message->__buf,
1651 vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags)
1654 vcom_socket_main_t *vsm = &vcom_socket_main;
1656 vcom_socket_t *vsock;
1658 p = hash_get (vsm->sockidx_by_fd, __fd);
1662 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1666 if (vcom_socket_is_connection_mode_socket (__fd))
1668 /* ignore __addr and _addr_len */
1669 /* and EISCONN may be returned when they are not NULL and 0 */
1670 if ((__message->msg_name != NULL) || (__message->msg_namelen != 0))
1677 /* TBD: validate __message->msg_name and __message->msg_namelen
1678 * and return -EINVAL on validation error
1683 rv = vppcom_sendmsg (vsock->sid, __message, __flags);
1690 vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages,
1691 unsigned int __vlen, int __flags)
1694 /* TBD: define a new vppcom api */
1699 /* TBD: move it to vppcom */
1701 vppcom_recvmsg (int __sid, struct msghdr *__message, int __flags)
1704 /* rv = vppcom_session_read (__sid, (void *) __message->__buf,
1711 vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags)
1714 vcom_socket_main_t *vsm = &vcom_socket_main;
1716 vcom_socket_t *vsock;
1718 p = hash_get (vsm->sockidx_by_fd, __fd);
1722 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1726 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1734 /* validate __flags */
1736 rv = vppcom_recvmsg (vsock->sid, __message, __flags);
1742 vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages,
1743 unsigned int __vlen, int __flags,
1744 struct timespec *__tmo)
1746 /* TBD: define a new vppcom api */
1751 /* TBD: move it to vppcom */
1753 vppcom_getsockopt (int __sid, int __level, int __optname,
1754 void *__restrict __optval, socklen_t * __restrict __optlen)
1756 /* 1. for socket level options that are NOT socket attributes
1757 * and that has corresponding vpp options get from vppcom */
1762 /* 2. unhandled options */
1763 return -ENOPROTOOPT;
1767 vcom_socket_getsockopt (int __fd, int __level, int __optname,
1768 void *__restrict __optval,
1769 socklen_t * __restrict __optlen)
1772 vcom_socket_main_t *vsm = &vcom_socket_main;
1774 vcom_socket_t *vsock;
1776 p = hash_get (vsm->sockidx_by_fd, __fd);
1780 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1784 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1787 if (!__optval && !__optlen)
1797 /* handle options at socket level */
1802 * 1. for socket level options that are socket attributes,
1803 * get from libc_getsockopt.
1804 * 2. for socket level options that are NOT socket
1805 * attributes and that has corresponding vpp options
1807 * 3. for socket level options unimplemented
1808 * return -ENOPROTOOPT */
1827 case SO_TIMESTAMPNS:
1828 case SO_TIMESTAMPING:
1841 case SO_WIFI_STATUS:
1844 case SO_BINDTODEVICE:
1846 case SO_LOCK_FILTER:
1847 case SO_BPF_EXTENSIONS:
1848 case SO_SELECT_ERR_QUEUE:
1849 #ifdef CONFIG_NET_RX_BUSY_POLL
1852 case SO_MAX_PACING_RATE:
1853 case SO_INCOMING_CPU:
1854 rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
1863 /* We implement the SO_SNDLOWAT etc to not be settable
1866 return -ENOPROTOOPT;
1872 /* 1. handle options that are NOT socket level options,
1873 * but have corresponding vpp otions. */
1874 rv = vppcom_getsockopt (vsock->sid, __level, __optname,
1875 __optval, __optlen);
1879 /* 2. unhandled options */
1880 return -ENOPROTOOPT;
1887 /* TBD: move it to vppcom */
1889 vppcom_session_setsockopt (int __sid, int __level, int __optname,
1890 const void *__optval, socklen_t __optlen)
1892 int rv = -EOPNOTSUPP;
1901 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, 0, 0);
1905 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, 0, 0);
1915 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0);
1925 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_KEEPALIVE, 0, 0);
1928 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0);
1931 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0);
1945 vcom_socket_setsockopt (int __fd, int __level, int __optname,
1946 const void *__optval, socklen_t __optlen)
1949 vcom_socket_main_t *vsm = &vcom_socket_main;
1951 vcom_socket_t *vsock;
1953 p = hash_get (vsm->sockidx_by_fd, __fd);
1957 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1961 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1965 * Options without arguments
1968 if (__optname == SO_BINDTODEVICE)
1970 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
1981 if ((__optlen < 0) || (__optlen < sizeof (int)))
1990 rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
1991 __optval, __optlen);
2004 rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
2005 __optval, __optlen);
2011 /* handle options at socket level */
2018 rv = vppcom_session_setsockopt (vsock->sid, __level, __optname,
2019 __optval, __optlen);
2023 * 1. for socket level options that are socket attributes,
2024 * set it from libc_getsockopt
2025 * 2. for socket level options that are NOT socket
2026 * attributes and that has corresponding vpp options
2027 * set it from vppcom
2028 * 3. for socket level options unimplemented
2029 * return -ENOPROTOOPT */
2045 case SO_TIMESTAMPNS:
2046 case SO_TIMESTAMPING:
2059 case SO_WIFI_STATUS:
2063 * SO_BINDTODEVICE already handled as
2064 * "Options without arguments" */
2065 /* case SO_BINDTODEVICE: */
2067 case SO_LOCK_FILTER:
2068 case SO_BPF_EXTENSIONS:
2069 case SO_SELECT_ERR_QUEUE:
2070 #ifdef CONFIG_NET_RX_BUSY_POLL
2073 case SO_MAX_PACING_RATE:
2074 case SO_INCOMING_CPU:
2075 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2084 /* We implement the SO_SNDLOWAT etc to not be settable
2087 return -ENOPROTOOPT;
2093 return -ENOPROTOOPT;
2100 vcom_socket_listen (int __fd, int __n)
2103 vcom_socket_main_t *vsm = &vcom_socket_main;
2105 vcom_socket_t *vsock;
2107 p = hash_get (vsm->sockidx_by_fd, __fd);
2110 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2112 /* TBD vppcom to accept __n parameter */
2113 rv = vppcom_session_listen (vsock->sid, __n);
2120 vcom_socket_connected_socket (int __fd, int __sid,
2122 int *__type, int *__protocol, int flags)
2125 vcom_socket_main_t *vsm = &vcom_socket_main;
2126 vcom_socket_t *vsock;
2133 optlen = sizeof (*__domain);
2134 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen);
2141 optlen = sizeof (*__type);
2142 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen);
2149 optlen = sizeof (*__protocol);
2150 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen);
2157 fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol);
2164 pool_get (vsm->vsockets, vsock);
2165 vsocket_init (vsock);
2167 sockidx = vsock - vsm->vsockets;
2168 hash_set (vsm->sockidx_by_fd, fd, sockidx);
2170 vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND);
2177 /* If flag is 0, then accept4() is the same as accept().
2178 * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags
2181 vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr,
2182 socklen_t * __restrict __addr_len, int flags)
2185 vcom_socket_main_t *vsm = &vcom_socket_main;
2187 vcom_socket_t *vsock;
2195 uint8_t addr8[sizeof (struct in6_addr)];
2200 /* validate flags */
2207 * case SOCK_NONBLOCK:
2208 * case SOCK_CLOEXEC:
2209 * case SOCK_NONBLOCK | SOCK_CLOEXEC:
2216 /* flags can be 0 or can be bitwise OR
2217 * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */
2219 if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC))))
2221 /* TBD: return proper error code */
2225 /* TBD: return proper error code */
2227 if (!vcom_socket_is_connection_mode_socket (__fd))
2232 p = hash_get (vsm->sockidx_by_fd, __fd);
2235 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2238 rv = vcom_fcntl (vsock->fd, F_GETFL, 0);
2245 if (!(rv & O_NONBLOCK))
2247 /* socket is not marked as nonblocking
2248 * and no pending connections are present
2249 * on the queue, accept () blocks the caller
2250 * until a connection is present.
2252 rv = vppcom_session_accept (vsock->sid, &ep,
2253 -1.0 /* wait forever */ );
2257 /* The file descriptor refers to a socket and has been
2258 * marked nonblocking(O_NONBLOCK) and the accept would
2261 /* is non blocking */
2262 rv = vppcom_session_accept (vsock->sid, &ep, 0);
2263 /* If the socket is marked nonblocking and
2264 * no pending connections are present on the
2265 * queue, accept fails with the error
2266 * EAGAIN or EWOULDBLOCK
2268 if (rv == VPPCOM_ETIMEDOUT)
2280 /* create a new connected socket resource and set flags
2281 * on the new file descriptor.
2282 * update vsockets and sockidx_by_fd table
2284 fd = vcom_socket_connected_socket (__fd, sid,
2285 &domain, &type, &protocol, flags);
2293 /* TBD populate __addr and __addr_len */
2294 /* TBD: The returned address is truncated if the buffer
2295 * provided is too small, in this case, __addr_len will
2296 * return a value greater than was supplied to the call.*/
2301 /* TBD populate __addr and __addr_len */
2305 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2306 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2307 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2308 addr8, sizeof (struct in_addr));
2309 /* TBD: populate __addr_len */
2312 *__addr_len = sizeof (struct sockaddr_in);
2317 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2318 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2319 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2320 __in6_u.__u6_addr8, addr8,
2321 sizeof (struct in6_addr));
2322 /* TBD: populate __addr_len */
2325 *__addr_len = sizeof (struct sockaddr_in6);
2330 return -EAFNOSUPPORT;
2338 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2339 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2340 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2341 addr8, sizeof (struct in_addr));
2342 /* TBD: populate __addr_len */
2345 *__addr_len = sizeof (struct sockaddr_in);
2350 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2351 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2352 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2353 __in6_u.__u6_addr8, addr8,
2354 sizeof (struct in6_addr));
2355 /* TBD: populate __addr_len */
2358 *__addr_len = sizeof (struct sockaddr_in6);
2363 return -EAFNOSUPPORT;
2369 /* when __addr is NULL, nothing is filled in,
2370 * in this case, __addr_len is not used,
2371 * and should also be null
2375 /* TBD: return proper error code */
2385 vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr,
2386 socklen_t * __restrict __addr_len)
2388 /* set flags to 0 for accept() */
2389 return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0);
2394 vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr,
2395 socklen_t * __restrict __addr_len, int __flags)
2397 /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */
2398 return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags);
2402 /* TBD: move it to vppcom */
2404 vppcom_session_shutdown (int __fd, int __how)
2410 vcom_socket_shutdown (int __fd, int __how)
2413 vcom_socket_main_t *vsm = &vcom_socket_main;
2415 vcom_socket_t *vsock;
2417 p = hash_get (vsm->sockidx_by_fd, __fd);
2420 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2426 rv = vppcom_session_shutdown (vsock->sid, __how);
2440 vcom_socket_epoll_create1 (int __flags)
2443 vcom_socket_main_t *vsm = &vcom_socket_main;
2444 vcom_epoll_t *vepoll;
2450 epfd = vcom_socket_open_epoll (__flags);
2457 vep_idx = vppcom_epoll_create ();
2461 goto out_close_epoll;
2464 pool_get (vsm->vepolls, vepoll);
2465 vepoll_init (vepoll);
2467 epollidx = vepoll - vsm->vepolls;
2468 hash_set (vsm->epollidx_by_epfd, epfd, epollidx);
2470 vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0);
2475 vcom_socket_close_epoll (epfd);
2481 * PRE: vppcom_epoll_ctl() is successful
2482 * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put
2485 vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd,
2486 struct epoll_event *__event,
2487 i32 vep_idx, vcom_epoll_t * vepoll,
2488 i32 vfd_id, void *vfd, vcom_fd_type_t type,
2489 int free_vepitem_on_del)
2492 vcom_socket_main_t *vsm = &vcom_socket_main;
2493 vcom_epitem_t *vepitem;
2495 vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd };
2499 i32 *vepitemidxs = 0;
2501 struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD };
2505 /* perform control operations on the epoll instance */
2510 * supplied file descriptor is already
2511 * registered with this epoll instance
2513 /* vepitem exists */
2514 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2521 /* add a new vepitem */
2522 pool_get (vsm->vepitems, vepitem);
2523 vepitem_init (vepitem);
2525 vepitemidx = vepitem - vsm->vepitems;
2526 hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx);
2527 vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent);
2529 /* update epitemidxs */
2531 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2532 if (!p) /* not exist */
2535 vec_add1 (vepitemidxs, vepitemidx);
2536 hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs);
2540 vepitemidxs = *(i32 **) p;
2541 vec_add1 (vepitemidxs, vepitemidx);
2542 hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0);
2544 /* update epitemidxs */
2546 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2547 if (!p) /* not exist */
2550 vec_add1 (vepitemidxs, vepitemidx);
2551 hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs);
2555 vepitemidxs = *(i32 **) p;
2556 vec_add1 (vepitemidxs, vepitemidx);
2557 hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0);
2560 /* increment vepoll fd count by 1 */
2569 * supplied file descriptor is not
2570 * registered with this epoll instance
2572 /* vepitem not exist */
2573 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2579 vepitem = pool_elt_at_index (vsm->vepitems, p[0]);
2582 vepitem->event = *__event;
2583 vepitem->revent = revent;
2592 * supplied file descriptor is not
2593 * registered with this epoll instance
2595 /* vepitem not exist */
2596 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2602 vepitemidx = *(i32 *) p;
2603 hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key);
2605 /* update epitemidxs */
2607 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2608 if (!p) /* not exist */
2615 vepitemidxs = *(i32 **) p;
2616 vec_idx = vec_search (vepitemidxs, vepitemidx);
2619 vec_del1 (vepitemidxs, vec_idx);
2620 if (!vec_len (vepitemidxs))
2622 vec_free (vepitemidxs);
2623 hash_unset (vsm->epitemidxs_by_epfd, __epfd);
2628 /* update epitemidxs */
2630 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2631 if (!p) /* not exist */
2638 vepitemidxs = *(i32 **) p;
2639 vec_idx = vec_search (vepitemidxs, vepitemidx);
2642 vec_del1 (vepitemidxs, vec_idx);
2643 if (!vec_len (vepitemidxs))
2645 vec_free (vepitemidxs);
2646 hash_unset (vsm->epitemidxs_by_fd, __fd);
2651 /* pool put vepitem */
2652 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx);
2653 if (free_vepitem_on_del)
2660 vepitem_init (vepitem);
2661 pool_put (vsm->vepitems, vepitem);
2667 vepitem_init (vepitem);
2671 /* decrement vepoll fd count by 1 */
2689 * PRE: 00. null pointer check on __event
2690 * 01. all other parameters are validated
2694 vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd,
2695 struct epoll_event *__event,
2696 int free_vepitem_on_del)
2700 /* vcom_socket_main_t *vsm = &vcom_socket_main; */
2701 vcom_epoll_t *vepoll;
2703 /*__fd could could be vcom socket or vcom epoll or kernel fd */
2705 vcom_epoll_t *vfd_vepoll;
2706 vcom_socket_t *vfd_vsock;
2711 vcom_fd_type_t type = FD_TYPE_INVALID;
2713 /* validate __event */
2715 /* get vep_idx and vepoll */
2716 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
2717 if (vep_idx == INVALID_VEP_IDX)
2722 /* get vcom fd type, vfd_id and vfd */
2723 vfd_id = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock);
2724 if (vfd_id != INVALID_SESSION_ID)
2726 type = FD_TYPE_VCOM_SOCKET;
2729 else if ((vfd_id = vcom_socket_get_vep_idx_and_vepoll (__fd, &vfd_vepoll))
2732 type = FD_TYPE_EPOLL;
2737 /* FD_TYPE_KERNEL not supported by epoll instance */
2738 type = FD_TYPE_INVALID;
2743 /* vepoll and vsock are now valid */
2744 rv = vppcom_epoll_ctl (vep_idx, __op, vfd_id, __event);
2750 rv = vcom_socket_ctl_vepitem (__epfd, __op, __fd,
2753 vfd_id, vfd, type, free_vepitem_on_del);
2758 vcom_socket_epoll_ctl (int __epfd, int __op, int __fd,
2759 struct epoll_event *__event)
2763 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1);
2768 vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd,
2769 struct epoll_event *__event)
2773 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0);
2778 vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events,
2779 int __maxevents, int __timeout,
2780 const __sigset_t * __ss)
2784 /* in seconds eg. 3.123456789 seconds */
2785 double time_to_wait = (double) 0;
2789 /* validate __event */
2796 /* validate __timeout */
2799 time_to_wait = (double) __timeout / (double) 1000;
2801 else if (__timeout == 0)
2803 time_to_wait = (double) 0;
2805 else if (__timeout == -1)
2816 vep_idx = vcom_socket_get_vep_idx (__epfd);
2817 if (vep_idx != INVALID_VEP_IDX)
2819 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait);
2826 vcom_socket_main_init (void)
2828 vcom_socket_main_t *vsm = &vcom_socket_main;
2831 printf ("vcom_socket_main_init\n");
2835 /* TBD: define FD_MAXSIZE and use it here */
2836 pool_alloc (vsm->vsockets, FD_SETSIZE);
2837 vsm->sockidx_by_fd = hash_create (0, sizeof (i32));
2839 pool_alloc (vsm->vepolls, FD_SETSIZE);
2840 vsm->epollidx_by_epfd = hash_create (0, sizeof (i32));
2842 pool_alloc (vsm->vepitems, FD_SETSIZE);
2843 vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32));
2845 vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *));
2846 vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *));
2856 vcom_socket_main_show (void)
2858 vcom_socket_main_t *vsm = &vcom_socket_main;
2859 vcom_socket_t *vsock;
2861 vcom_epoll_t *vepoll;
2863 vcom_epitem_t *vepitem;
2867 i32 *vepitemidxs, *vepitemidxs_var;
2871 /* from active list of vsockets show vsock */
2874 pool_foreach (vsock, vsm->vsockets,
2877 "fd='%04d', sid='%08x',type='%-30s'\n",
2878 vsock->fd, vsock->sid,
2879 vcom_socket_type_str (vsock->type));
2883 /* from active list of vepolls, show vepoll */
2886 pool_foreach (vepoll, vsm->vepolls,
2889 "epfd='%04d', vep_idx='%08x', "
2891 "flags='%d', count='%d', close='%d'\n",
2892 vepoll->epfd, vepoll->vep_idx,
2893 vcom_socket_epoll_type_str (vepoll->type),
2894 vepoll->flags, vepoll->count, vepoll->close);
2898 /* from active list of vepitems, show vepitem */
2901 pool_foreach (vepitem, vsm->vepitems,
2904 "epfd='%04d', fd='%04d', "
2905 "next_fd='%04d', prev_fd='%04d', "
2907 "events='%04x', revents='%04x'\n",
2908 vepitem->epfd, vepitem->fd,
2909 vepitem->next_fd, vepitem->prev_fd,
2910 vcom_socket_vcom_fd_type_str (vepitem->type),
2911 vepitem->event.events, vepitem->revent.events);
2916 /* show epitemidxs for epfd */
2918 hash_foreach (epfd, vepitemidxs,
2919 vsm->epitemidxs_by_epfd,
2921 printf("\n[ '%04d': ", epfd);
2922 vec_foreach (vepitemidxs_var,vepitemidxs)
2924 printf("'%04d' ", (int)vepitemidxs_var[0]);
2930 /* show epitemidxs for fd */
2932 hash_foreach (fd, vepitemidxs,
2933 vsm->epitemidxs_by_fd,
2935 printf("\n{ '%04d': ", fd);
2936 vec_foreach (vepitemidxs_var,vepitemidxs)
2938 printf("'%04d' ", (int)vepitemidxs_var[0]);
2948 vcom_socket_main_destroy (void)
2950 vcom_socket_main_t *vsm = &vcom_socket_main;
2951 vcom_socket_t *vsock;
2953 vcom_epoll_t *vepoll;
2955 vcom_epitem_t *vepitem;
2963 printf ("vcom_socket_main_destroy\n");
2969 * from active list of vepitems,
2970 * remove all "vepitem" elements from the pool in a safe way
2974 pool_flush (vepitem, vsm->vepitems,
2976 if (vepitem->type == FD_TYPE_EPOLL || FD_TYPE_VCOM_SOCKET)
2978 vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL,
2980 vepitem_init (vepitem);
2985 pool_free (vsm->vepitems);
2986 hash_free (vsm->epitemidx_by_epfdfd);
2988 /* free vepitemidxs for each epfd */
2990 hash_foreach (epfd, vepitemidxs,
2991 vsm->epitemidxs_by_epfd,
2993 vec_free (vepitemidxs);
2996 hash_free (vsm->epitemidxs_by_epfd);
2998 /* free vepitemidxs for each fd */
3000 hash_foreach (fd, vepitemidxs,
3001 vsm->epitemidxs_by_fd,
3003 vec_free (vepitemidxs);
3006 hash_free (vsm->epitemidxs_by_fd);
3010 * from active list of vsockets,
3011 * close socket and vppcom session
3015 pool_foreach (vsock, vsm->vsockets,
3017 if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
3019 vppcom_session_close (vsock->sid);
3020 vcom_socket_close_socket (vsock->fd);
3021 vsocket_init (vsock);
3027 * return vsocket element to the pool
3031 pool_flush (vsock, vsm->vsockets,
3033 // vsocket_init(vsock);
3038 pool_free (vsm->vsockets);
3039 hash_free (vsm->sockidx_by_fd);
3042 * from active list of vepolls,
3043 * close epoll and vppcom_epoll
3047 pool_foreach (vepoll, vsm->vepolls,
3049 if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
3051 vppcom_session_close (vepoll->vep_idx);
3052 vcom_socket_close_epoll (vepoll->epfd); /* TBD: */
3053 vepoll_init (vepoll);
3059 * return vepoll element to the pool
3063 pool_flush (vepoll, vsm->vepolls,
3065 // vepoll_init(vepoll);
3070 pool_free (vsm->vepolls);
3071 hash_free (vsm->epollidx_by_epfd);
3079 * fd.io coding-style-patch-verification: ON
3082 * eval: (c-set-style "gnu")