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>
22 #include <vppinfra/types.h>
23 #include <vppinfra/hash.h>
24 #include <vppinfra/pool.h>
26 #include <libvcl-ldpreload/vcom_socket.h>
27 #include <libvcl-ldpreload/vcom_socket_wrapper.h>
28 #include <libvcl-ldpreload/vcom.h>
30 #include <uri/vppcom.h>
34 * VCOM_SOCKET Private definitions and functions.
37 typedef struct vcom_socket_main_t_
41 /* vcom_socket pool */
42 vcom_socket_t *vsockets;
44 /* Hash table for socketidx to fd mapping */
48 vcom_epoll_t *vepolls;
50 /* Hash table for epollidx to epfd mapping */
51 uword *epollidx_by_epfd;
54 /* common epitem poll for all epfd */
55 /* TBD: epitem poll per epfd */
56 /* vcom_epitem pool */
57 vcom_epitem_t *vepitems;
59 /* Hash table for epitemidx to epfdfd mapping */
60 uword *epitemidx_by_epfdfd;
62 /* Hash table - key:epfd, value:vec of epitemidx */
63 uword *epitemidxs_by_epfd;
64 /* Hash table - key:fd, value:vec of epitemidx */
65 uword *epitemidxs_by_fd;
69 vcom_socket_main_t vcom_socket_main;
73 vcom_socket_open_socket (int domain, int type, int protocol)
77 /* handle domains implemented by vpp */
82 /* get socket type and
83 * handle the socket types supported by vpp */
84 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
88 /* the type argument serves a second purpose,
89 * in addition to specifying a socket type,
90 * it may include the bitwise OR of any of
91 * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify
92 * the behavior of socket. */
93 rv = libc_socket (domain, type, protocol);
112 vcom_socket_open_epoll (int flags)
120 if (flags && (flags & ~EPOLL_CLOEXEC))
125 /* flags can be either zero or EPOLL_CLOEXEC */
126 rv = libc_epoll_create1 (flags);
134 vcom_socket_close_socket (int fd)
138 rv = libc_close (fd);
146 vcom_socket_close_epoll (int epfd)
150 rv = libc_close (epfd);
158 * Public API functions
163 vcom_socket_is_vcom_fd (int fd)
165 vcom_socket_main_t *vsm = &vcom_socket_main;
167 vcom_socket_t *vsock;
169 p = hash_get (vsm->sockidx_by_fd, fd);
173 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
174 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
181 vcom_socket_is_vcom_epfd (int epfd)
183 vcom_socket_main_t *vsm = &vcom_socket_main;
185 vcom_epoll_t *vepoll;
187 p = hash_get (vsm->epollidx_by_epfd, epfd);
191 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
192 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
199 vcom_socket_get_sid (int fd)
201 vcom_socket_main_t *vsm = &vcom_socket_main;
203 vcom_socket_t *vsock;
205 p = hash_get (vsm->sockidx_by_fd, fd);
209 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
210 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
213 return INVALID_SESSION_ID;
217 vcom_socket_get_vep_idx (int epfd)
219 vcom_socket_main_t *vsm = &vcom_socket_main;
221 vcom_epoll_t *vepoll;
223 p = hash_get (vsm->epollidx_by_epfd, epfd);
227 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
228 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
229 return vepoll->vep_idx;
231 return INVALID_VEP_IDX;
235 vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp)
237 vcom_socket_main_t *vsm = &vcom_socket_main;
239 vcom_socket_t *vsock;
241 p = hash_get (vsm->sockidx_by_fd, fd);
245 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
246 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
252 return INVALID_SESSION_ID;
256 vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp)
258 vcom_socket_main_t *vsm = &vcom_socket_main;
260 vcom_epoll_t *vepoll;
262 p = hash_get (vsm->epollidx_by_epfd, epfd);
266 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
267 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
270 return vepoll->vep_idx;
273 return INVALID_VEP_IDX;
278 vcom_socket_close_vepoll (int epfd)
281 vcom_socket_main_t *vsm = &vcom_socket_main;
283 vcom_epoll_t *vepoll;
285 p = hash_get (vsm->epollidx_by_epfd, epfd);
289 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
293 if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND)
310 rv = vppcom_session_close (vepoll->vep_idx);
311 rv = vcom_socket_close_epoll (vepoll->epfd);
313 vepoll_init (vepoll);
314 hash_unset (vsm->epollidx_by_epfd, epfd);
315 pool_put (vsm->vepolls, vepoll);
321 vcom_socket_close_vsock (int fd)
324 vcom_socket_main_t *vsm = &vcom_socket_main;
326 vcom_socket_t *vsock;
328 vcom_epitem_t *vepitem;
330 i32 *vepitemidxs = 0;
331 i32 *vepitemidxs_var = 0;
333 p = hash_get (vsm->sockidx_by_fd, fd);
337 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
341 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
344 rv = vppcom_session_close (vsock->sid);
345 rv = vcom_socket_close_socket (vsock->fd);
347 vsocket_init (vsock);
348 hash_unset (vsm->sockidx_by_fd, fd);
349 pool_put (vsm->vsockets, vsock);
353 * Before calling close(), user should remove
354 * this fd from the epoll-set of all epoll instances,
355 * otherwise resource(epitems) leaks ensues.
359 * 00. close all epoll instances that are marked as "close"
360 * of which this fd is the "last" remaining member.
361 * 01. epitems associated with this fd are intentionally
362 * not removed, see NOTE: above.
365 /* does this fd participate in epoll */
366 p = hash_get (vsm->epitemidxs_by_fd, fd);
369 vepitemidxs = *(i32 **) p;
370 vec_foreach (vepitemidxs_var, vepitemidxs)
372 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]);
373 if (vepitem && vepitem->fd == fd &&
374 vepitem->type == FD_TYPE_VCOM_SOCKET)
377 vcom_epoll_t *vepoll;
379 vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd,
385 if (vepoll->count == 1)
388 * force count to zero and
389 * close this epoll instance
392 vcom_socket_close_vepoll (vepoll->epfd);
409 vcom_socket_close (int __fd)
413 if (vcom_socket_is_vcom_fd (__fd))
415 rv = vcom_socket_close_vsock (__fd);
417 else if (vcom_socket_is_vcom_epfd (__fd))
419 rv = vcom_socket_close_vepoll (__fd);
430 vcom_socket_read (int __fd, void *__buf, size_t __nbytes)
433 vcom_socket_main_t *vsm = &vcom_socket_main;
435 vcom_socket_t *vsock;
437 p = hash_get (vsm->sockidx_by_fd, __fd);
441 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
445 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
448 if (!__buf || __nbytes < 0)
453 rv = vcom_fcntl (__fd, F_GETFL, 0);
461 if (!(rv & O_NONBLOCK))
465 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
467 while (rv == -EAGAIN || rv == -EWOULDBLOCK);
470 /* The file descriptor refers to a socket and has been
471 * marked nonblocking(O_NONBLOCK) and the read would
474 /* is non blocking */
475 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
480 vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt)
483 vcom_socket_main_t *vsm = &vcom_socket_main;
485 vcom_socket_t *vsock;
486 ssize_t total = 0, len = 0;
488 p = hash_get (vsm->sockidx_by_fd, __fd);
492 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
496 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
499 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
503 for (int i = 0; i < __iovcnt; ++i)
505 if (SSIZE_MAX - len < __iov[i].iov_len)
507 len += __iov[i].iov_len;
510 rv = vcom_fcntl (__fd, F_GETFL, 0);
517 if (!(rv & O_NONBLOCK))
521 for (int i = 0; i < __iovcnt; ++i)
523 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
530 if (rv < __iov[i].iov_len)
531 /* Read less than buffer provided, no point to continue */
536 while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0);
540 /* is non blocking */
541 for (int i = 0; i < __iovcnt; ++i)
543 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
558 if (rv < __iov[i].iov_len)
559 /* Read less than buffer provided, no point to continue */
567 vcom_socket_write (int __fd, const void *__buf, size_t __n)
570 vcom_socket_main_t *vsm = &vcom_socket_main;
572 vcom_socket_t *vsock;
574 p = hash_get (vsm->sockidx_by_fd, __fd);
578 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
582 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
585 if (!__buf || __n < 0)
590 rv = vppcom_session_write (vsock->sid, (void *) __buf, __n);
595 vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt)
599 vcom_socket_main_t *vsm = &vcom_socket_main;
601 vcom_socket_t *vsock;
603 p = hash_get (vsm->sockidx_by_fd, __fd);
607 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
611 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
614 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
617 for (int i = 0; i < __iovcnt; ++i)
619 rv = vppcom_session_write (vsock->sid, __iov[i].iov_base,
635 * RETURN: 0 - invalid cmd
636 * 1 - cmd not handled by vcom and vppcom
637 * 2 - cmd handled by vcom socket resource
638 * 3 - cmd handled by vppcom
640 /* TBD: incomplete list of cmd */
642 vcom_socket_check_fcntl_cmd (int __cmd)
646 /*cmd not handled by vcom and vppcom */
649 case F_DUPFD_CLOEXEC:
652 /* cmd handled by vcom socket resource */
666 /* cmd handled by vppcom */
677 /* TBD: move it to vppcom */
679 vppcom_session_fcntl_va (int __fd, int __cmd, va_list __ap)
689 vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap)
692 vcom_socket_main_t *vsm = &vcom_socket_main;
694 vcom_socket_t *vsock;
696 p = hash_get (vsm->sockidx_by_fd, __fd);
700 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
704 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
707 switch (vcom_socket_check_fcntl_cmd (__cmd))
713 /*cmd not handled by vcom and vppcom */
717 /* cmd handled by vcom socket resource */
719 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
721 /* cmd handled by vppcom */
723 rv = vppcom_session_fcntl_va (vsock->sid, __cmd, __ap);
735 vcom_socket_fds_2_sid_fds (
738 fd_set * __restrict vcom_rd_sid_fds,
739 fd_set * __restrict vcom_wr_sid_fds,
740 fd_set * __restrict vcom_ex_sid_fds,
743 fd_set * __restrict vcom_readfds,
744 fd_set * __restrict vcom_writefds,
745 fd_set * __restrict vcom_exceptfds)
750 /* invalid max_sid is -1 */
755 * set sid in sid sets corresponding to fd's in fd sets
756 * compute nsid and vcom_nsid_fds from sid sets
759 for (fd = 0; fd < vcom_nfds; fd++)
766 if ((F) && (S) && FD_ISSET (fd, (F))) \
768 sid = vcom_socket_get_sid (fd); \
769 if (sid != INVALID_SESSION_ID) \
786 _(vcom_rd_sid_fds, vcom_readfds);
787 _(vcom_wr_sid_fds, vcom_writefds);
788 _(vcom_ex_sid_fds, vcom_exceptfds);
792 *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0;
800 * PRE: 00. sid sets were derived from fd sets
801 * 01. sid sets were updated with sids that actually changed
803 * 02. fd sets still has watched fds
805 * This function will modify in place fd sets to indicate which fd's
806 * actually changed status(inferred from sid sets)
809 vcom_socket_sid_fds_2_fds (
813 fd_set * __restrict vcom_readfds,
814 fd_set * __restrict vcom_writefds,
815 fd_set * __restrict vcom_exceptfds,
818 fd_set * __restrict vcom_rd_sid_fds,
819 fd_set * __restrict vcom_wr_sid_fds,
820 fd_set * __restrict vcom_ex_sid_fds)
825 /* invalid max_fd is -1 */
831 * modify in place fd sets to indicate which fd's
832 * actually changed status(inferred from sid sets)
834 for (fd = 0; fd < vcom_nfds; fd++)
841 if ((F) && (S) && FD_ISSET (fd, (F))) \
843 sid = vcom_socket_get_sid (fd); \
844 if (sid != INVALID_SESSION_ID) \
846 if (!FD_ISSET (sid, (S))) \
859 _(vcom_rd_sid_fds, vcom_readfds);
860 _(vcom_wr_sid_fds, vcom_writefds);
861 _(vcom_ex_sid_fds, vcom_exceptfds);
866 * compute nfd and new_vcom_nfds from fd sets
868 for (fd = 0; fd < vcom_nfds; fd++)
872 if ((F) && FD_ISSET (fd, (F))) \
889 *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0;
898 * vom_socket_select is always called with
899 * timeout->tv_sec and timeout->tv_usec set to zero.
900 * hence vppcom_select return immediately.
903 * TBD: do{body;} while(timeout conditional); timeout loop
906 vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds,
907 fd_set * __restrict vcom_writefds,
908 fd_set * __restrict vcom_exceptfds,
909 struct timeval *__restrict timeout)
912 pid_t pid = getpid ();
914 int new_vcom_nfds = 0;
915 int new_vcom_nfd = 0;
918 fd_set vcom_rd_sid_fds;
919 fd_set vcom_wr_sid_fds;
920 fd_set vcom_ex_sid_fds;
921 unsigned long vcom_nsid_fds = 0;
924 /* in seconds eg. 3.123456789 seconds */
925 double time_to_wait = (double) 0;
927 /* validate inputs */
933 /* convert timeval timeout to double time_to_wait */
936 if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
938 /* polling: vppcom_select returns immediately */
939 time_to_wait = (double) 0;
943 /*TBD: use timeval api */
944 time_to_wait = (double) timeout->tv_sec +
945 (double) timeout->tv_usec / (double) 1000000 +
946 (double) (timeout->tv_usec % 1000000) / (double) 1000000;
952 * no timeout: vppcom_select can block indefinitely
953 * waiting for a file descriptor to become ready
955 /* set to a phantom value */
959 /* zero the sid_sets */
971 _(&vcom_rd_sid_fds, vcom_readfds);
972 _(&vcom_wr_sid_fds, vcom_writefds);
973 _(&vcom_ex_sid_fds, vcom_exceptfds);
976 /* populate read, write and except sid_sets */
977 vcom_nsid = vcom_socket_fds_2_sid_fds (
979 vcom_readfds || vcom_writefds
980 || vcom_exceptfds ? (int *)
981 &vcom_nsid_fds : NULL,
982 vcom_readfds ? &vcom_rd_sid_fds :
984 vcom_writefds ? &vcom_wr_sid_fds :
986 vcom_exceptfds ? &vcom_ex_sid_fds :
991 vcom_writefds, vcom_exceptfds);
996 if (vcom_nsid_fds < 0)
1001 rv = vppcom_select (vcom_nsid_fds,
1002 vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds :
1004 vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds :
1006 vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
1007 NULL, time_to_wait);
1009 fprintf (stderr, "[%d] vppcom_select: "
1010 "'%04d'='%04d'\n", pid, rv, (int) vcom_nsid_fds);
1012 /* check if any file descriptors changed status */
1016 * on exit, sets are modified in place to indicate which
1017 * file descriptors actually changed status
1021 * comply with pre-condition
1022 * do not clear vcom fd sets befor calling
1023 * vcom_socket_sid_fds_2_fds
1025 new_vcom_nfd = vcom_socket_sid_fds_2_fds (
1035 &vcom_rd_sid_fds : NULL,
1037 &vcom_wr_sid_fds : NULL,
1039 &vcom_ex_sid_fds : NULL);
1040 if (new_vcom_nfd < 0)
1042 return new_vcom_nfd;
1044 if (new_vcom_nfds < 0)
1055 vcom_socket_socket (int __domain, int __type, int __protocol)
1058 vcom_socket_main_t *vsm = &vcom_socket_main;
1059 vcom_socket_t *vsock;
1064 u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0;
1065 int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
1067 fd = vcom_socket_open_socket (__domain, __type, __protocol);
1074 sid = vppcom_session_create (VPPCOM_VRF_DEFAULT,
1075 (type == SOCK_DGRAM) ?
1076 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP,
1081 goto out_close_socket;
1084 pool_get (vsm->vsockets, vsock);
1085 vsocket_init (vsock);
1087 sockidx = vsock - vsm->vsockets;
1088 hash_set (vsm->sockidx_by_fd, fd, sockidx);
1090 vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND);
1094 vcom_socket_close_socket (fd);
1100 vcom_socket_socketpair (int __domain, int __type, int __protocol,
1108 vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1111 vcom_socket_main_t *vsm = &vcom_socket_main;
1113 vcom_socket_t *vsock;
1117 p = hash_get (vsm->sockidx_by_fd, __fd);
1121 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1125 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1133 ep.vrf = VPPCOM_VRF_DEFAULT;
1134 switch (__addr->sa_family)
1137 if (__len != sizeof (struct sockaddr_in))
1141 ep.is_ip4 = VPPCOM_IS_IP4;
1142 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1143 ep.port = (u16) ((const struct sockaddr_in *) __addr)->sin_port;
1147 if (__len != sizeof (struct sockaddr_in6))
1151 ep.is_ip4 = VPPCOM_IS_IP6;
1152 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1153 ep.port = (u16) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1161 rv = vppcom_session_bind (vsock->sid, &ep);
1162 /* TBD: remove libc_bind code snippet
1163 * once vppcom implements vppcom_session_getsockname */
1166 rv = libc_bind (__fd, __addr, __len);
1176 vppcom_session_getsockname (int sid, vppcom_endpt_t * ep)
1178 /* TBD: move it to vppcom */
1183 vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr,
1184 socklen_t * __restrict __len)
1187 vcom_socket_main_t *vsm = &vcom_socket_main;
1189 vcom_socket_t *vsock;
1192 p = hash_get (vsm->sockidx_by_fd, __fd);
1196 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1200 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1203 if (!__addr || !__len)
1211 /* TBD: remove libc_getsockname code snippet
1212 * once vppcom implements vppcom_session_getsockname */
1213 rv = libc_getsockname (__fd, __addr, __len);
1220 /* TBD: use the below code snippet when vppcom
1221 * implements vppcom_session_getsockname */
1224 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1225 rv = vppcom_session_getsockname (vsock->sid, &ep);
1228 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1230 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1231 switch (__addr->sa_family)
1234 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1235 *__len = sizeof (struct sockaddr_in);
1239 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1240 *__len = sizeof (struct sockaddr_in6);
1254 vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1257 vcom_socket_main_t *vsm = &vcom_socket_main;
1259 vcom_socket_t *vsock;
1263 p = hash_get (vsm->sockidx_by_fd, __fd);
1266 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1268 ep.vrf = VPPCOM_VRF_DEFAULT;
1269 switch (__addr->sa_family)
1272 ep.is_ip4 = VPPCOM_IS_IP4;
1274 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1276 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1280 ep.is_ip4 = VPPCOM_IS_IP6;
1282 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1284 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1292 rv = vppcom_session_connect (vsock->sid, &ep);
1298 vppcom_session_getpeername (int sid, vppcom_endpt_t * ep)
1300 /* TBD: move it to vppcom */
1305 vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr,
1306 socklen_t * __restrict __len)
1309 vcom_socket_main_t *vsm = &vcom_socket_main;
1311 vcom_socket_t *vsock;
1314 p = hash_get (vsm->sockidx_by_fd, __fd);
1318 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1322 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1325 if (!__addr || !__len)
1333 /* DAW: hack to allow iperf3 to be happy w/ getpeername output */
1336 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
1337 ((struct sockaddr_in *) __addr)->sin_port = 0x1000;
1338 a = (uint8_t *) & ((struct sockaddr_in *) __addr)->sin_addr;
1343 *__len = sizeof (struct sockaddr_in);
1347 /* TBD: remove libc_getpeername code snippet
1348 * once vppcom implements vppcom_session_getpeername */
1349 rv = libc_getpeername (__fd, __addr, __len);
1356 /* TBD: use the below code snippet when vppcom
1357 * implements vppcom_session_getpeername */
1360 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1361 rv = vppcom_session_getpeername (vsock->sid, &ep);
1364 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1366 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1367 switch (__addr->sa_family)
1370 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1371 *__len = sizeof (struct sockaddr_in);
1375 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1376 *__len = sizeof (struct sockaddr_in6);
1390 vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags)
1392 return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0);
1396 vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags)
1399 rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0);
1404 * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET),
1408 vcom_socket_is_connection_mode_socket (int __fd)
1411 /* TBD define new vppcom api */
1412 vcom_socket_main_t *vsm = &vcom_socket_main;
1414 vcom_socket_t *vsock;
1419 p = hash_get (vsm->sockidx_by_fd, __fd);
1423 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1424 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
1426 optlen = sizeof (type);
1427 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
1432 /* get socket type */
1433 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1436 case SOCK_SEQPACKET:
1450 vvppcom_session_sendto (int __sid, const void *__buf, size_t __n,
1451 int __flags, __CONST_SOCKADDR_ARG __addr,
1452 socklen_t __addr_len)
1455 /* TBD add new vpp api */
1456 /* TBD add flags parameter */
1457 rv = vppcom_session_write (__sid, (void *) __buf, (int) __n);
1462 vcom_socket_sendto (int __fd, const void *__buf, size_t __n,
1463 int __flags, __CONST_SOCKADDR_ARG __addr,
1464 socklen_t __addr_len)
1467 vcom_socket_main_t *vsm = &vcom_socket_main;
1469 vcom_socket_t *vsock;
1471 p = hash_get (vsm->sockidx_by_fd, __fd);
1475 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1479 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1482 if (!__buf || __n < 0)
1487 if (vcom_socket_is_connection_mode_socket (__fd))
1489 /* ignore __addr and _addr_len */
1490 /* and EISCONN may be returned when they are not NULL and 0 */
1491 if ((__addr != NULL) || (__addr_len != 0))
1498 if (!__addr || __addr_len < 0)
1500 return -EDESTADDRREQ;
1502 /* not a vppcom supported address family */
1503 if ((__addr->sa_family != AF_INET) || (__addr->sa_family != AF_INET6))
1509 rv = vvppcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
1510 __flags, __addr, __addr_len);
1514 /* TBD: move it to vppcom */
1516 vppcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
1517 int __flags, __SOCKADDR_ARG __addr,
1518 socklen_t * __restrict __addr_len)
1522 /* TBD add flags parameter */
1523 rv = vppcom_session_read (__sid, __buf, __n);
1528 vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
1529 int __flags, __SOCKADDR_ARG __addr,
1530 socklen_t * __restrict __addr_len)
1533 vcom_socket_main_t *vsm = &vcom_socket_main;
1535 vcom_socket_t *vsock;
1537 p = hash_get (vsm->sockidx_by_fd, __fd);
1541 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1545 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1548 if (!__buf || __n < 0)
1553 if (__addr || __addr_len < 0)
1558 rv = vppcom_session_recvfrom (vsock->sid, __buf, __n,
1559 __flags, __addr, __addr_len);
1563 /* TBD: move it to vppcom */
1565 vppcom_sendmsg (int __sid, const struct msghdr *__message, int __flags)
1568 /* rv = vppcom_session_write (__sid, (void *) __message->__buf,
1574 vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags)
1577 vcom_socket_main_t *vsm = &vcom_socket_main;
1579 vcom_socket_t *vsock;
1581 p = hash_get (vsm->sockidx_by_fd, __fd);
1585 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1589 if (vcom_socket_is_connection_mode_socket (__fd))
1591 /* ignore __addr and _addr_len */
1592 /* and EISCONN may be returned when they are not NULL and 0 */
1593 if ((__message->msg_name != NULL) || (__message->msg_namelen != 0))
1600 /* TBD: validate __message->msg_name and __message->msg_namelen
1601 * and return -EINVAL on validation error
1606 rv = vppcom_sendmsg (vsock->sid, __message, __flags);
1613 vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages,
1614 unsigned int __vlen, int __flags)
1617 /* TBD: define a new vppcom api */
1622 /* TBD: move it to vppcom */
1624 vppcom_recvmsg (int __sid, struct msghdr *__message, int __flags)
1627 /* rv = vppcom_session_read (__sid, (void *) __message->__buf,
1634 vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags)
1637 vcom_socket_main_t *vsm = &vcom_socket_main;
1639 vcom_socket_t *vsock;
1641 p = hash_get (vsm->sockidx_by_fd, __fd);
1645 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1649 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1657 /* validate __flags */
1659 rv = vppcom_recvmsg (vsock->sid, __message, __flags);
1665 vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages,
1666 unsigned int __vlen, int __flags,
1667 struct timespec *__tmo)
1669 /* TBD: define a new vppcom api */
1674 /* TBD: move it to vppcom */
1676 vppcom_getsockopt (int __sid, int __level, int __optname,
1677 void *__restrict __optval, socklen_t * __restrict __optlen)
1679 /* 1. for socket level options that are NOT socket attributes
1680 * and that has corresponding vpp options get from vppcom */
1685 /* 2. unhandled options */
1686 return -ENOPROTOOPT;
1690 vcom_socket_getsockopt (int __fd, int __level, int __optname,
1691 void *__restrict __optval,
1692 socklen_t * __restrict __optlen)
1695 vcom_socket_main_t *vsm = &vcom_socket_main;
1697 vcom_socket_t *vsock;
1699 p = hash_get (vsm->sockidx_by_fd, __fd);
1703 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1707 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1710 if (!__optval && !__optlen)
1720 /* handle options at socket level */
1725 * 1. for socket level options that are socket attributes,
1726 * get from libc_getsockopt.
1727 * 2. for socket level options that are NOT socket
1728 * attributes and that has corresponding vpp options
1730 * 3. for socket level options unimplemented
1731 * return -ENOPROTOOPT */
1750 case SO_TIMESTAMPNS:
1751 case SO_TIMESTAMPING:
1764 case SO_WIFI_STATUS:
1767 case SO_BINDTODEVICE:
1769 case SO_LOCK_FILTER:
1770 case SO_BPF_EXTENSIONS:
1771 case SO_SELECT_ERR_QUEUE:
1772 #ifdef CONFIG_NET_RX_BUSY_POLL
1775 case SO_MAX_PACING_RATE:
1776 case SO_INCOMING_CPU:
1777 rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
1786 /* We implement the SO_SNDLOWAT etc to not be settable
1789 return -ENOPROTOOPT;
1795 /* 1. handle options that are NOT socket level options,
1796 * but have corresponding vpp otions. */
1797 rv = vppcom_getsockopt (vsock->sid, __level, __optname,
1798 __optval, __optlen);
1802 /* 2. unhandled options */
1803 return -ENOPROTOOPT;
1810 /* TBD: move it to vppcom */
1812 vppcom_setsockopt (int __fd, int __level, int __optname,
1813 const void *__optval, socklen_t __optlen)
1815 /* 1. for socket level options that are NOT socket attributes
1816 * and that has corresponding vpp options set it from vppcom */
1821 /* 2. unhandled options */
1822 return -ENOPROTOOPT;
1826 vcom_socket_setsockopt (int __fd, int __level, int __optname,
1827 const void *__optval, socklen_t __optlen)
1830 vcom_socket_main_t *vsm = &vcom_socket_main;
1832 vcom_socket_t *vsock;
1834 p = hash_get (vsm->sockidx_by_fd, __fd);
1838 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1842 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1846 * Options without arguments
1849 if (__optname == SO_BINDTODEVICE)
1851 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
1862 if ((__optlen < 0) || (__optlen < sizeof (int)))
1867 /* handle options at socket level */
1872 * 1. for socket level options that are socket attributes,
1873 * set it from libc_getsockopt
1874 * 2. for socket level options that are NOT socket
1875 * attributes and that has corresponding vpp options
1876 * set it from vppcom
1877 * 3. for socket level options unimplemented
1878 * return -ENOPROTOOPT */
1897 case SO_TIMESTAMPNS:
1898 case SO_TIMESTAMPING:
1911 case SO_WIFI_STATUS:
1915 * SO_BINDTODEVICE already handled as
1916 * "Options without arguments" */
1917 /* case SO_BINDTODEVICE: */
1919 case SO_LOCK_FILTER:
1920 case SO_BPF_EXTENSIONS:
1921 case SO_SELECT_ERR_QUEUE:
1922 #ifdef CONFIG_NET_RX_BUSY_POLL
1925 case SO_MAX_PACING_RATE:
1926 case SO_INCOMING_CPU:
1927 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
1936 /* We implement the SO_SNDLOWAT etc to not be settable
1939 return -ENOPROTOOPT;
1945 /* 1. handle options that are NOT socket level options,
1946 * but have corresponding vpp otions. */
1947 rv = vppcom_setsockopt (vsock->sid, __level, __optname,
1948 __optval, __optlen);
1951 /* 2. unhandled options */
1952 return -ENOPROTOOPT;
1960 vcom_socket_listen (int __fd, int __n)
1963 vcom_socket_main_t *vsm = &vcom_socket_main;
1965 vcom_socket_t *vsock;
1967 p = hash_get (vsm->sockidx_by_fd, __fd);
1970 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1972 /* TBD vppcom to accept __n parameter */
1973 rv = vppcom_session_listen (vsock->sid, __n);
1980 vcom_socket_connected_socket (int __fd, int __sid,
1982 int *__type, int *__protocol, int flags)
1985 vcom_socket_main_t *vsm = &vcom_socket_main;
1986 vcom_socket_t *vsock;
1993 optlen = sizeof (*__domain);
1994 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen);
2001 optlen = sizeof (*__type);
2002 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen);
2009 optlen = sizeof (*__protocol);
2010 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen);
2017 fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol);
2024 pool_get (vsm->vsockets, vsock);
2025 vsocket_init (vsock);
2027 sockidx = vsock - vsm->vsockets;
2028 hash_set (vsm->sockidx_by_fd, fd, sockidx);
2030 vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND);
2037 /* If flag is 0, then accept4() is the same as accept().
2038 * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags
2041 vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr,
2042 socklen_t * __restrict __addr_len, int flags)
2045 vcom_socket_main_t *vsm = &vcom_socket_main;
2047 vcom_socket_t *vsock;
2055 uint8_t addr8[sizeof (struct in6_addr)];
2060 /* validate flags */
2067 * case SOCK_NONBLOCK:
2068 * case SOCK_CLOEXEC:
2069 * case SOCK_NONBLOCK | SOCK_CLOEXEC:
2076 /* flags can be 0 or can be bitwise OR
2077 * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */
2079 if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC))))
2081 /* TBD: return proper error code */
2085 /* TBD: return proper error code */
2087 if (!vcom_socket_is_connection_mode_socket (__fd))
2092 p = hash_get (vsm->sockidx_by_fd, __fd);
2095 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2098 rv = vcom_fcntl (vsock->fd, F_GETFL, 0);
2105 if (!(rv & O_NONBLOCK))
2107 /* socket is not marked as nonblocking
2108 * and no pending connections are present
2109 * on the queue, accept () blocks the caller
2110 * until a connection is present.
2112 rv = vppcom_session_accept (vsock->sid, &ep,
2113 -1.0 /* wait forever */ );
2117 /* The file descriptor refers to a socket and has been
2118 * marked nonblocking(O_NONBLOCK) and the accept would
2121 /* is non blocking */
2122 rv = vppcom_session_accept (vsock->sid, &ep, 0);
2123 /* If the socket is marked nonblocking and
2124 * no pending connections are present on the
2125 * queue, accept fails with the error
2126 * EAGAIN or EWOULDBLOCK
2128 if (rv == VPPCOM_ETIMEDOUT)
2140 /* create a new connected socket resource and set flags
2141 * on the new file descriptor.
2142 * update vsockets and sockidx_by_fd table
2144 fd = vcom_socket_connected_socket (__fd, sid,
2145 &domain, &type, &protocol, flags);
2153 /* TBD populate __addr and __addr_len */
2154 /* TBD: The returned address is truncated if the buffer
2155 * provided is too small, in this case, __addr_len will
2156 * return a value greater than was supplied to the call.*/
2161 /* TBD populate __addr and __addr_len */
2165 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2166 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2167 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2168 addr8, sizeof (struct in_addr));
2169 /* TBD: populate __addr_len */
2172 *__addr_len = sizeof (struct sockaddr_in);
2177 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2178 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2179 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2180 __in6_u.__u6_addr8, addr8,
2181 sizeof (struct in6_addr));
2182 /* TBD: populate __addr_len */
2185 *__addr_len = sizeof (struct sockaddr_in6);
2190 return -EAFNOSUPPORT;
2198 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2199 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2200 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2201 addr8, sizeof (struct in_addr));
2202 /* TBD: populate __addr_len */
2205 *__addr_len = sizeof (struct sockaddr_in);
2210 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2211 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2212 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2213 __in6_u.__u6_addr8, addr8,
2214 sizeof (struct in6_addr));
2215 /* TBD: populate __addr_len */
2218 *__addr_len = sizeof (struct sockaddr_in6);
2223 return -EAFNOSUPPORT;
2229 /* when __addr is NULL, nothing is filled in,
2230 * in this case, __addr_len is not used,
2231 * and should also be null
2235 /* TBD: return proper error code */
2245 vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr,
2246 socklen_t * __restrict __addr_len)
2248 /* set flags to 0 for accept() */
2249 return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0);
2254 vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr,
2255 socklen_t * __restrict __addr_len, int __flags)
2257 /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */
2258 return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags);
2262 /* TBD: move it to vppcom */
2264 vppcom_session_shutdown (int __fd, int __how)
2270 vcom_socket_shutdown (int __fd, int __how)
2273 vcom_socket_main_t *vsm = &vcom_socket_main;
2275 vcom_socket_t *vsock;
2277 p = hash_get (vsm->sockidx_by_fd, __fd);
2280 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2286 rv = vppcom_session_shutdown (vsock->sid, __how);
2300 vcom_socket_epoll_create1 (int __flags)
2303 vcom_socket_main_t *vsm = &vcom_socket_main;
2304 vcom_epoll_t *vepoll;
2310 epfd = vcom_socket_open_epoll (__flags);
2317 vep_idx = vppcom_epoll_create ();
2321 goto out_close_epoll;
2324 pool_get (vsm->vepolls, vepoll);
2325 vepoll_init (vepoll);
2327 epollidx = vepoll - vsm->vepolls;
2328 hash_set (vsm->epollidx_by_epfd, epfd, epollidx);
2330 vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0);
2335 vcom_socket_close_epoll (epfd);
2341 * PRE: vppcom_epoll_ctl() is successful
2342 * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put
2345 vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd,
2346 struct epoll_event *__event,
2347 i32 vep_idx, vcom_epoll_t * vepoll,
2348 i32 vfd_id, void *vfd, vcom_fd_type_t type,
2349 int free_vepitem_on_del)
2352 vcom_socket_main_t *vsm = &vcom_socket_main;
2353 vcom_epitem_t *vepitem;
2355 vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd };
2359 i32 *vepitemidxs = 0;
2361 struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD };
2365 /* perform control operations on the epoll instance */
2370 * supplied file descriptor is already
2371 * registered with this epoll instance
2373 /* vepitem exists */
2374 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2381 /* add a new vepitem */
2382 pool_get (vsm->vepitems, vepitem);
2383 vepitem_init (vepitem);
2385 vepitemidx = vepitem - vsm->vepitems;
2386 hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx);
2387 vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent);
2389 /* update epitemidxs */
2391 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2392 if (!p) /* not exist */
2395 vec_add1 (vepitemidxs, vepitemidx);
2396 hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs);
2400 vepitemidxs = *(i32 **) p;
2401 vec_add1 (vepitemidxs, vepitemidx);
2402 hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0);
2404 /* update epitemidxs */
2406 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2407 if (!p) /* not exist */
2410 vec_add1 (vepitemidxs, vepitemidx);
2411 hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs);
2415 vepitemidxs = *(i32 **) p;
2416 vec_add1 (vepitemidxs, vepitemidx);
2417 hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0);
2420 /* increment vepoll fd count by 1 */
2429 * supplied file descriptor is not
2430 * registered with this epoll instance
2432 /* vepitem not exist */
2433 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2439 vepitem = pool_elt_at_index (vsm->vepitems, p[0]);
2442 vepitem->event = *__event;
2443 vepitem->revent = revent;
2452 * supplied file descriptor is not
2453 * registered with this epoll instance
2455 /* vepitem not exist */
2456 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2462 vepitemidx = *(i32 *) p;
2463 hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key);
2465 /* update epitemidxs */
2467 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2468 if (!p) /* not exist */
2475 vepitemidxs = *(i32 **) p;
2476 vec_idx = vec_search (vepitemidxs, vepitemidx);
2479 vec_del1 (vepitemidxs, vec_idx);
2480 if (!vec_len (vepitemidxs))
2482 vec_free (vepitemidxs);
2483 hash_unset (vsm->epitemidxs_by_epfd, __epfd);
2488 /* update epitemidxs */
2490 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2491 if (!p) /* not exist */
2498 vepitemidxs = *(i32 **) p;
2499 vec_idx = vec_search (vepitemidxs, vepitemidx);
2502 vec_del1 (vepitemidxs, vec_idx);
2503 if (!vec_len (vepitemidxs))
2505 vec_free (vepitemidxs);
2506 hash_unset (vsm->epitemidxs_by_fd, __fd);
2511 /* pool put vepitem */
2512 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx);
2513 if (free_vepitem_on_del)
2520 vepitem_init (vepitem);
2521 pool_put (vsm->vepitems, vepitem);
2527 vepitem_init (vepitem);
2531 /* decrement vepoll fd count by 1 */
2549 * PRE: 00. null pointer check on __event
2550 * 01. all other parameters are validated
2554 vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd,
2555 struct epoll_event *__event,
2556 int free_vepitem_on_del)
2560 /* vcom_socket_main_t *vsm = &vcom_socket_main; */
2561 vcom_epoll_t *vepoll;
2563 /*__fd could could be vcom socket or vcom epoll or kernel fd */
2565 vcom_epoll_t *vfd_vepoll;
2566 vcom_socket_t *vfd_vsock;
2571 vcom_fd_type_t type = FD_TYPE_INVALID;
2573 /* validate __event */
2575 /* get vep_idx and vepoll */
2576 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
2577 if (vep_idx == INVALID_VEP_IDX)
2582 /* get vcom fd type, vfd_id and vfd */
2583 vfd_id = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock);
2584 if (vfd_id != INVALID_SESSION_ID)
2586 type = FD_TYPE_VCOM_SOCKET;
2589 else if ((vfd_id = vcom_socket_get_vep_idx_and_vepoll (__fd, &vfd_vepoll))
2592 type = FD_TYPE_EPOLL;
2597 /* FD_TYPE_KERNEL not supported by epoll instance */
2598 type = FD_TYPE_INVALID;
2603 /* vepoll and vsock are now valid */
2604 rv = vppcom_epoll_ctl (vep_idx, __op, vfd_id, __event);
2610 rv = vcom_socket_ctl_vepitem (__epfd, __op, __fd,
2613 vfd_id, vfd, type, free_vepitem_on_del);
2618 vcom_socket_epoll_ctl (int __epfd, int __op, int __fd,
2619 struct epoll_event *__event)
2623 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1);
2628 vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd,
2629 struct epoll_event *__event)
2633 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0);
2638 vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events,
2639 int __maxevents, int __timeout,
2640 const __sigset_t * __ss)
2644 /* in seconds eg. 3.123456789 seconds */
2645 double time_to_wait = (double) 0;
2649 /* validate __event */
2656 /* validate __timeout */
2659 time_to_wait = (double) __timeout / (double) 1000;
2661 else if (__timeout == 0)
2663 time_to_wait = (double) 0;
2665 else if (__timeout == -1)
2676 vep_idx = vcom_socket_get_vep_idx (__epfd);
2677 if (vep_idx != INVALID_VEP_IDX)
2679 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait);
2686 vcom_socket_main_init (void)
2688 vcom_socket_main_t *vsm = &vcom_socket_main;
2691 printf ("vcom_socket_main_init\n");
2695 /* TBD: define FD_MAXSIZE and use it here */
2696 pool_alloc (vsm->vsockets, FD_SETSIZE);
2697 vsm->sockidx_by_fd = hash_create (0, sizeof (i32));
2699 pool_alloc (vsm->vepolls, FD_SETSIZE);
2700 vsm->epollidx_by_epfd = hash_create (0, sizeof (i32));
2702 pool_alloc (vsm->vepitems, FD_SETSIZE);
2703 vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32));
2705 vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *));
2706 vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *));
2716 vcom_socket_main_show (void)
2718 vcom_socket_main_t *vsm = &vcom_socket_main;
2719 vcom_socket_t *vsock;
2721 vcom_epoll_t *vepoll;
2723 vcom_epitem_t *vepitem;
2727 i32 *vepitemidxs, *vepitemidxs_var;
2731 /* from active list of vsockets show vsock */
2734 pool_foreach (vsock, vsm->vsockets,
2737 "fd='%04d', sid='%08x',type='%-30s'\n",
2738 vsock->fd, vsock->sid,
2739 vcom_socket_type_str (vsock->type));
2743 /* from active list of vepolls, show vepoll */
2746 pool_foreach (vepoll, vsm->vepolls,
2749 "epfd='%04d', vep_idx='%08x', "
2751 "flags='%d', count='%d', close='%d'\n",
2752 vepoll->epfd, vepoll->vep_idx,
2753 vcom_socket_epoll_type_str (vepoll->type),
2754 vepoll->flags, vepoll->count, vepoll->close);
2758 /* from active list of vepitems, show vepitem */
2761 pool_foreach (vepitem, vsm->vepitems,
2764 "epfd='%04d', fd='%04d', "
2765 "next_fd='%04d', prev_fd='%04d', "
2767 "events='%04x', revents='%04x'\n",
2768 vepitem->epfd, vepitem->fd,
2769 vepitem->next_fd, vepitem->prev_fd,
2770 vcom_socket_vcom_fd_type_str (vepitem->type),
2771 vepitem->event.events, vepitem->revent.events);
2776 /* show epitemidxs for epfd */
2778 hash_foreach (epfd, vepitemidxs,
2779 vsm->epitemidxs_by_epfd,
2781 printf("\n[ '%04d': ", epfd);
2782 vec_foreach (vepitemidxs_var,vepitemidxs)
2784 printf("'%04d' ", (int)vepitemidxs_var[0]);
2790 /* show epitemidxs for fd */
2792 hash_foreach (fd, vepitemidxs,
2793 vsm->epitemidxs_by_fd,
2795 printf("\n{ '%04d': ", fd);
2796 vec_foreach (vepitemidxs_var,vepitemidxs)
2798 printf("'%04d' ", (int)vepitemidxs_var[0]);
2808 vcom_socket_main_destroy (void)
2810 vcom_socket_main_t *vsm = &vcom_socket_main;
2811 vcom_socket_t *vsock;
2813 vcom_epoll_t *vepoll;
2815 vcom_epitem_t *vepitem;
2823 printf ("vcom_socket_main_destroy\n");
2829 * from active list of vepitems,
2830 * remove all "vepitem" elements from the pool in a safe way
2834 pool_flush (vepitem, vsm->vepitems,
2836 if (vepitem->type == FD_TYPE_EPOLL || FD_TYPE_VCOM_SOCKET)
2838 vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL,
2840 vepitem_init (vepitem);
2845 pool_free (vsm->vepitems);
2846 hash_free (vsm->epitemidx_by_epfdfd);
2848 /* free vepitemidxs for each epfd */
2850 hash_foreach (epfd, vepitemidxs,
2851 vsm->epitemidxs_by_epfd,
2853 vec_free (vepitemidxs);
2856 hash_free (vsm->epitemidxs_by_epfd);
2858 /* free vepitemidxs for each fd */
2860 hash_foreach (fd, vepitemidxs,
2861 vsm->epitemidxs_by_fd,
2863 vec_free (vepitemidxs);
2866 hash_free (vsm->epitemidxs_by_fd);
2870 * from active list of vsockets,
2871 * close socket and vppcom session
2875 pool_foreach (vsock, vsm->vsockets,
2877 if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
2879 vppcom_session_close (vsock->sid);
2880 vcom_socket_close_socket (vsock->fd);
2881 vsocket_init (vsock);
2887 * return vsocket element to the pool
2891 pool_flush (vsock, vsm->vsockets,
2893 // vsocket_init(vsock);
2898 pool_free (vsm->vsockets);
2899 hash_free (vsm->sockidx_by_fd);
2902 * from active list of vepolls,
2903 * close epoll and vppcom_epoll
2907 pool_foreach (vepoll, vsm->vepolls,
2909 if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
2911 vppcom_session_close (vepoll->vep_idx);
2912 vcom_socket_close_epoll (vepoll->epfd); /* TBD: */
2913 vepoll_init (vepoll);
2919 * return vepoll element to the pool
2923 pool_flush (vepoll, vsm->vepolls,
2925 // vepoll_init(vepoll);
2930 pool_free (vsm->vepolls);
2931 hash_free (vsm->epollidx_by_epfd);
2939 * fd.io coding-style-patch-verification: ON
2942 * eval: (c-set-style "gnu")