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;
75 vcom_socket_main_t vcom_socket_main;
79 vcom_socket_open_socket (int domain, int type, int protocol)
83 /* handle domains implemented by vpp */
88 /* get socket type and
89 * handle the socket types supported by vpp */
90 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
94 /* the type argument serves a second purpose,
95 * in addition to specifying a socket type,
96 * it may include the bitwise OR of any of
97 * SOCK_NONBLOCK and SOCK_CLOEXEC, to modify
98 * the behavior of socket. */
99 rv = libc_socket (domain, type, protocol);
118 vcom_socket_open_epoll (int flags)
126 if (flags && (flags & ~EPOLL_CLOEXEC))
131 /* flags can be either zero or EPOLL_CLOEXEC */
132 rv = libc_epoll_create1 (flags);
140 vcom_socket_close_socket (int fd)
144 rv = libc_close (fd);
152 vcom_socket_close_epoll (int epfd)
156 rv = libc_close (epfd);
164 * Public API functions
169 vcom_socket_is_vcom_fd (int fd)
171 vcom_socket_main_t *vsm = &vcom_socket_main;
173 vcom_socket_t *vsock;
175 p = hash_get (vsm->sockidx_by_fd, fd);
179 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
180 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
187 vcom_socket_is_vcom_epfd (int epfd)
189 vcom_socket_main_t *vsm = &vcom_socket_main;
191 vcom_epoll_t *vepoll;
193 p = hash_get (vsm->epollidx_by_epfd, epfd);
197 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
198 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
205 vcom_socket_get_sid (int fd)
207 vcom_socket_main_t *vsm = &vcom_socket_main;
209 vcom_socket_t *vsock;
211 p = hash_get (vsm->sockidx_by_fd, fd);
215 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
216 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
219 return INVALID_SESSION_ID;
223 vcom_socket_get_vep_idx (int epfd)
225 vcom_socket_main_t *vsm = &vcom_socket_main;
227 vcom_epoll_t *vepoll;
229 p = hash_get (vsm->epollidx_by_epfd, epfd);
233 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
234 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
235 return vepoll->vep_idx;
237 return INVALID_VEP_IDX;
241 vcom_socket_get_sid_and_vsock (int fd, vcom_socket_t ** vsockp)
243 vcom_socket_main_t *vsm = &vcom_socket_main;
245 vcom_socket_t *vsock;
247 p = hash_get (vsm->sockidx_by_fd, fd);
251 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
252 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
258 return INVALID_SESSION_ID;
262 vcom_socket_get_vep_idx_and_vepoll (int epfd, vcom_epoll_t ** vepollp)
264 vcom_socket_main_t *vsm = &vcom_socket_main;
266 vcom_epoll_t *vepoll;
268 p = hash_get (vsm->epollidx_by_epfd, epfd);
272 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
273 if (vepoll && vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
276 return vepoll->vep_idx;
279 return INVALID_VEP_IDX;
284 vcom_socket_close_vepoll (int epfd)
287 vcom_socket_main_t *vsm = &vcom_socket_main;
289 vcom_epoll_t *vepoll;
291 p = hash_get (vsm->epollidx_by_epfd, epfd);
295 vepoll = pool_elt_at_index (vsm->vepolls, p[0]);
299 if (vepoll->type != EPOLL_TYPE_VPPCOM_BOUND)
316 rv = vppcom_session_close (vepoll->vep_idx);
317 rv = vcom_socket_close_epoll (vepoll->epfd);
319 vepoll_init (vepoll);
320 hash_unset (vsm->epollidx_by_epfd, epfd);
321 pool_put (vsm->vepolls, vepoll);
327 vcom_socket_close_vsock (int fd)
330 vcom_socket_main_t *vsm = &vcom_socket_main;
332 vcom_socket_t *vsock;
334 vcom_epitem_t *vepitem;
336 i32 *vepitemidxs = 0;
337 i32 *vepitemidxs_var = 0;
339 p = hash_get (vsm->sockidx_by_fd, fd);
343 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
347 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
350 rv = vppcom_session_close (vsock->sid);
351 rv = vcom_socket_close_socket (vsock->fd);
353 vsocket_init (vsock);
354 hash_unset (vsm->sockidx_by_fd, fd);
355 pool_put (vsm->vsockets, vsock);
359 * Before calling close(), user should remove
360 * this fd from the epoll-set of all epoll instances,
361 * otherwise resource(epitems) leaks ensues.
365 * 00. close all epoll instances that are marked as "close"
366 * of which this fd is the "last" remaining member.
367 * 01. epitems associated with this fd are intentionally
368 * not removed, see NOTE: above.
371 /* does this fd participate in epoll */
372 p = hash_get (vsm->epitemidxs_by_fd, fd);
375 vepitemidxs = *(i32 **) p;
376 vec_foreach (vepitemidxs_var, vepitemidxs)
378 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidxs_var[0]);
379 if (vepitem && vepitem->fd == fd &&
380 vepitem->type == FD_TYPE_VCOM_SOCKET)
383 vcom_epoll_t *vepoll;
385 vcom_socket_get_vep_idx_and_vepoll (vepitem->epfd,
391 if (vepoll->count == 1)
394 * force count to zero and
395 * close this epoll instance
398 vcom_socket_close_vepoll (vepoll->epfd);
415 vcom_socket_close (int __fd)
419 if (vcom_socket_is_vcom_fd (__fd))
421 rv = vcom_socket_close_vsock (__fd);
423 else if (vcom_socket_is_vcom_epfd (__fd))
425 rv = vcom_socket_close_vepoll (__fd);
436 vcom_socket_read (int __fd, void *__buf, size_t __nbytes)
439 vcom_socket_main_t *vsm = &vcom_socket_main;
441 vcom_socket_t *vsock;
443 p = hash_get (vsm->sockidx_by_fd, __fd);
447 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
451 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
459 rv = vcom_fcntl (__fd, F_GETFL, 0);
467 if (!(rv & O_NONBLOCK))
471 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
473 /* coverity[CONSTANT_EXPRESSION_RESULT] */
474 while (rv == -EAGAIN || rv == -EWOULDBLOCK);
477 /* The file descriptor refers to a socket and has been
478 * marked nonblocking(O_NONBLOCK) and the read would
481 /* is non blocking */
482 rv = vppcom_session_read (vsock->sid, __buf, __nbytes);
487 vcom_socket_readv (int __fd, const struct iovec * __iov, int __iovcnt)
490 vcom_socket_main_t *vsm = &vcom_socket_main;
492 vcom_socket_t *vsock;
493 ssize_t total = 0, len = 0;
496 p = hash_get (vsm->sockidx_by_fd, __fd);
500 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
504 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
507 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
511 for (i = 0; i < __iovcnt; ++i)
513 if (SSIZE_MAX - len < __iov[i].iov_len)
515 len += __iov[i].iov_len;
518 rv = vcom_fcntl (__fd, F_GETFL, 0);
525 if (!(rv & O_NONBLOCK))
529 for (i = 0; i < __iovcnt; ++i)
531 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
538 if (rv < __iov[i].iov_len)
539 /* Read less than buffer provided, no point to continue */
544 /* coverity[CONSTANT_EXPRESSION_RESULT] */
545 while ((rv == -EAGAIN || rv == -EWOULDBLOCK) && total == 0);
549 /* is non blocking */
550 for (i = 0; i < __iovcnt; ++i)
552 rv = vppcom_session_read (vsock->sid, __iov[i].iov_base,
567 if (rv < __iov[i].iov_len)
568 /* Read less than buffer provided, no point to continue */
576 vcom_socket_write (int __fd, const void *__buf, size_t __n)
579 vcom_socket_main_t *vsm = &vcom_socket_main;
581 vcom_socket_t *vsock;
588 p = hash_get (vsm->sockidx_by_fd, __fd);
592 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
596 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
599 rv = vppcom_session_write (vsock->sid, (void *) __buf, __n);
604 vcom_socket_writev (int __fd, const struct iovec * __iov, int __iovcnt)
608 vcom_socket_main_t *vsm = &vcom_socket_main;
610 vcom_socket_t *vsock;
613 p = hash_get (vsm->sockidx_by_fd, __fd);
617 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
621 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
624 if (__iov == 0 || __iovcnt == 0 || __iovcnt > IOV_MAX)
627 for (i = 0; i < __iovcnt; ++i)
629 rv = vppcom_session_write (vsock->sid, __iov[i].iov_base,
645 * RETURN: 0 - invalid cmd
646 * 1 - cmd not handled by vcom and vppcom
647 * 2 - cmd handled by vcom socket resource
648 * 3 - cmd handled by vppcom
650 /* TBD: incomplete list of cmd */
652 vcom_socket_check_fcntl_cmd (int __cmd)
656 /*cmd not handled by vcom and vppcom */
659 case F_DUPFD_CLOEXEC:
662 /* cmd handled by vcom socket resource */
673 /* cmd handled by vcom and vppcom */
678 /* cmd not handled by vcom and vppcom */
686 vcom_session_fcntl_va (int __sid, int __cmd, va_list __ap)
688 int flags = va_arg (__ap, int);
689 int rv = -EOPNOTSUPP;
692 size = sizeof (flags);
693 if (__cmd == F_SETFL)
695 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
697 else if (__cmd == F_GETFL)
699 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
708 vcom_socket_fcntl_va (int __fd, int __cmd, va_list __ap)
711 vcom_socket_main_t *vsm = &vcom_socket_main;
713 vcom_socket_t *vsock;
715 p = hash_get (vsm->sockidx_by_fd, __fd);
719 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
723 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
726 switch (vcom_socket_check_fcntl_cmd (__cmd))
732 /*cmd not handled by vcom and vppcom */
734 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
736 /* cmd handled by vcom socket resource */
738 rv = libc_vfcntl (vsock->fd, __cmd, __ap);
740 /* cmd handled by vppcom */
742 rv = vcom_session_fcntl_va (vsock->sid, __cmd, __ap);
754 * RETURN: 0 - invalid cmd
755 * 1 - cmd not handled by vcom and vppcom
756 * 2 - cmd handled by vcom socket resource
757 * 3 - cmd handled by vppcom
760 vcom_socket_check_ioctl_cmd (unsigned long int __cmd)
766 /* cmd handled by vppcom */
771 /* cmd not handled by vcom and vppcom */
780 vcom_session_ioctl_va (int __sid, int __cmd, va_list __ap)
787 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
792 u32 flags = va_arg (__ap, int) ? O_NONBLOCK : 0;
793 u32 len = sizeof (flags);
794 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_FLAGS, &flags, &len);
806 vcom_socket_ioctl_va (int __fd, unsigned long int __cmd, va_list __ap)
809 vcom_socket_main_t *vsm = &vcom_socket_main;
811 vcom_socket_t *vsock;
813 p = hash_get (vsm->sockidx_by_fd, __fd);
817 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
821 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
824 switch (vcom_socket_check_ioctl_cmd (__cmd))
826 /* Not supported cmd */
831 /* cmd not handled by vcom and vppcom */
833 rv = libc_vioctl (vsock->fd, __cmd, __ap);
836 /* cmd handled by vcom socket resource */
838 rv = libc_vioctl (vsock->fd, __cmd, __ap);
841 /* cmd handled by vppcom */
843 rv = vcom_session_ioctl_va (vsock->sid, __cmd, __ap);
855 vcom_socket_fds_2_sid_fds (
858 fd_set * __restrict vcom_rd_sid_fds,
859 fd_set * __restrict vcom_wr_sid_fds,
860 fd_set * __restrict vcom_ex_sid_fds,
863 fd_set * __restrict vcom_readfds,
864 fd_set * __restrict vcom_writefds,
865 fd_set * __restrict vcom_exceptfds)
870 /* invalid max_sid is -1 */
875 * set sid in sid sets corresponding to fd's in fd sets
876 * compute nsid and vcom_nsid_fds from sid sets
879 for (fd = 0; fd < vcom_nfds; fd++)
886 if ((F) && (S) && FD_ISSET (fd, (F))) \
888 sid = vcom_socket_get_sid (fd); \
889 if (sid != INVALID_SESSION_ID) \
906 _(vcom_rd_sid_fds, vcom_readfds);
907 _(vcom_wr_sid_fds, vcom_writefds);
908 _(vcom_ex_sid_fds, vcom_exceptfds);
912 *vcom_nsid_fds = max_sid != -1 ? max_sid + 1 : 0;
920 * PRE: 00. sid sets were derived from fd sets
921 * 01. sid sets were updated with sids that actually changed
923 * 02. fd sets still has watched fds
925 * This function will modify in place fd sets to indicate which fd's
926 * actually changed status(inferred from sid sets)
929 vcom_socket_sid_fds_2_fds (
933 fd_set * __restrict vcom_readfds,
934 fd_set * __restrict vcom_writefds,
935 fd_set * __restrict vcom_exceptfds,
938 fd_set * __restrict vcom_rd_sid_fds,
939 fd_set * __restrict vcom_wr_sid_fds,
940 fd_set * __restrict vcom_ex_sid_fds)
945 /* invalid max_fd is -1 */
951 * modify in place fd sets to indicate which fd's
952 * actually changed status(inferred from sid sets)
954 for (fd = 0; fd < vcom_nfds; fd++)
961 if ((F) && (S) && FD_ISSET (fd, (F))) \
963 sid = vcom_socket_get_sid (fd); \
964 if (sid != INVALID_SESSION_ID) \
966 if (!FD_ISSET (sid, (S))) \
979 _(vcom_rd_sid_fds, vcom_readfds);
980 _(vcom_wr_sid_fds, vcom_writefds);
981 _(vcom_ex_sid_fds, vcom_exceptfds);
986 * compute nfd and new_vcom_nfds from fd sets
988 for (fd = 0; fd < vcom_nfds; fd++)
992 if ((F) && FD_ISSET (fd, (F))) \
1009 *new_vcom_nfds = max_fd != -1 ? max_fd + 1 : 0;
1018 * vom_socket_select is always called with
1019 * timeout->tv_sec and timeout->tv_usec set to zero.
1020 * hence vppcom_select return immediately.
1023 * TBD: do{body;} while(timeout conditional); timeout loop
1026 vcom_socket_select (int vcom_nfds, fd_set * __restrict vcom_readfds,
1027 fd_set * __restrict vcom_writefds,
1028 fd_set * __restrict vcom_exceptfds,
1029 struct timeval *__restrict timeout)
1031 static unsigned long vcom_nsid_fds = 0;
1035 int new_vcom_nfds = 0;
1036 int new_vcom_nfd = 0;
1039 fd_set vcom_rd_sid_fds;
1040 fd_set vcom_wr_sid_fds;
1041 fd_set vcom_ex_sid_fds;
1043 /* in seconds eg. 3.123456789 seconds */
1044 double time_to_wait = (double) 0;
1046 /* validate inputs */
1052 /* convert timeval timeout to double time_to_wait */
1055 if (timeout->tv_sec == 0 && timeout->tv_usec == 0)
1057 /* polling: vppcom_select returns immediately */
1058 time_to_wait = (double) 0;
1062 /*TBD: use timeval api */
1063 time_to_wait = (double) timeout->tv_sec +
1064 (double) timeout->tv_usec / (double) 1000000 +
1065 (double) (timeout->tv_usec % 1000000) / (double) 1000000;
1071 * no timeout: vppcom_select can block indefinitely
1072 * waiting for a file descriptor to become ready
1074 /* set to a phantom value */
1078 /* zero the sid_sets */
1090 _(&vcom_rd_sid_fds, vcom_readfds);
1091 _(&vcom_wr_sid_fds, vcom_writefds);
1092 _(&vcom_ex_sid_fds, vcom_exceptfds);
1097 if (time_to_wait > 0)
1101 "[%d] vcom_socket_select called to "
1102 "emulate delay_ns()!\n", getpid ());
1103 rv = vppcom_select (0, NULL, NULL, NULL, time_to_wait);
1107 fprintf (stderr, "[%d] vcom_socket_select called vcom_nfds = 0 "
1108 "and invalid time_to_wait (%f)!\n",
1109 getpid (), time_to_wait);
1114 /* populate read, write and except sid_sets */
1115 vcom_nsid = vcom_socket_fds_2_sid_fds (
1117 vcom_readfds || vcom_writefds
1118 || vcom_exceptfds ? (int *)
1119 &vcom_nsid_fds : NULL,
1120 vcom_readfds ? &vcom_rd_sid_fds :
1122 vcom_writefds ? &vcom_wr_sid_fds :
1124 vcom_exceptfds ? &vcom_ex_sid_fds :
1129 vcom_writefds, vcom_exceptfds);
1135 rv = vppcom_select (vcom_nsid_fds,
1136 vcom_readfds ? (unsigned long *) &vcom_rd_sid_fds :
1138 vcom_writefds ? (unsigned long *) &vcom_wr_sid_fds :
1140 vcom_exceptfds ? (unsigned long *) &vcom_ex_sid_fds :
1141 NULL, time_to_wait);
1143 fprintf (stderr, "[%d] called vppcom_select(): "
1144 "'%04d'='%04d'\n", getpid (), rv, (int) vcom_nsid_fds);
1146 /* check if any file descriptors changed status */
1150 * on exit, sets are modified in place to indicate which
1151 * file descriptors actually changed status
1155 * comply with pre-condition
1156 * do not clear vcom fd sets befor calling
1157 * vcom_socket_sid_fds_2_fds
1159 new_vcom_nfd = vcom_socket_sid_fds_2_fds (
1169 &vcom_rd_sid_fds : NULL,
1171 &vcom_wr_sid_fds : NULL,
1173 &vcom_ex_sid_fds : NULL);
1174 if (new_vcom_nfd < 0)
1176 return new_vcom_nfd;
1178 if (new_vcom_nfds < 0)
1189 vcom_socket_socket (int __domain, int __type, int __protocol)
1192 vcom_socket_main_t *vsm = &vcom_socket_main;
1193 vcom_socket_t *vsock;
1198 u8 is_nonblocking = __type & SOCK_NONBLOCK ? 1 : 0;
1199 int type = __type & ~(SOCK_NONBLOCK | SOCK_CLOEXEC);
1201 fd = vcom_socket_open_socket (__domain, __type, __protocol);
1208 sid = vppcom_session_create (VPPCOM_VRF_DEFAULT,
1209 (type == SOCK_DGRAM) ?
1210 VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP,
1215 goto out_close_socket;
1218 pool_get (vsm->vsockets, vsock);
1219 vsocket_init (vsock);
1221 sockidx = vsock - vsm->vsockets;
1222 hash_set (vsm->sockidx_by_fd, fd, sockidx);
1224 vsocket_set (vsock, fd, sid, SOCKET_TYPE_VPPCOM_BOUND);
1228 vcom_socket_close_socket (fd);
1234 vcom_socket_socketpair (int __domain, int __type, int __protocol,
1242 vcom_socket_bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1245 vcom_socket_main_t *vsm = &vcom_socket_main;
1247 vcom_socket_t *vsock;
1251 p = hash_get (vsm->sockidx_by_fd, __fd);
1255 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1259 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1267 ep.vrf = VPPCOM_VRF_DEFAULT;
1268 switch (__addr->sa_family)
1271 if (__len != sizeof (struct sockaddr_in))
1275 ep.is_ip4 = VPPCOM_IS_IP4;
1276 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1277 ep.port = (u16) ((const struct sockaddr_in *) __addr)->sin_port;
1281 if (__len != sizeof (struct sockaddr_in6))
1285 ep.is_ip4 = VPPCOM_IS_IP6;
1286 ep.ip = (u8 *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1287 ep.port = (u16) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1295 rv = vppcom_session_bind (vsock->sid, &ep);
1300 vcom_session_getsockname (int sid, vppcom_endpt_t * ep)
1303 uint32_t size = sizeof (*ep);
1305 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, ep, &size);
1310 vcom_socket_getsockname (int __fd, __SOCKADDR_ARG __addr,
1311 socklen_t * __restrict __len)
1314 vcom_socket_main_t *vsm = &vcom_socket_main;
1316 vcom_socket_t *vsock;
1319 p = hash_get (vsm->sockidx_by_fd, __fd);
1323 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1327 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1330 if (!__addr || !__len)
1334 ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1335 rv = vcom_session_getsockname (vsock->sid, &ep);
1338 if (ep.vrf == VPPCOM_VRF_DEFAULT)
1340 __addr->sa_family = ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
1341 switch (__addr->sa_family)
1344 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
1345 *__len = sizeof (struct sockaddr_in);
1349 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
1350 *__len = sizeof (struct sockaddr_in6);
1363 vcom_socket_connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
1366 vcom_socket_main_t *vsm = &vcom_socket_main;
1368 vcom_socket_t *vsock;
1372 p = hash_get (vsm->sockidx_by_fd, __fd);
1375 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1377 ep.vrf = VPPCOM_VRF_DEFAULT;
1378 switch (__addr->sa_family)
1381 ep.is_ip4 = VPPCOM_IS_IP4;
1383 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1385 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1389 ep.is_ip4 = VPPCOM_IS_IP6;
1391 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1393 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1401 rv = vppcom_session_connect (vsock->sid, &ep);
1407 vcom_session_getpeername (int sid, vppcom_endpt_t * ep)
1410 uint32_t size = sizeof (*ep);
1412 rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, ep, &size);
1417 vcom_socket_copy_ep_to_sockaddr (__SOCKADDR_ARG __addr,
1418 socklen_t * __restrict __len,
1419 vppcom_endpt_t * ep)
1422 int sa_len, copy_len;
1424 __addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1425 switch (__addr->sa_family)
1428 ((struct sockaddr_in *) __addr)->sin_port = ep->port;
1429 if (*__len > sizeof (struct sockaddr_in))
1430 *__len = sizeof (struct sockaddr_in);
1431 sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1432 copy_len = *__len - sa_len;
1434 memcpy (&((struct sockaddr_in *) __addr)->sin_addr, ep->ip, copy_len);
1438 ((struct sockaddr_in6 *) __addr)->sin6_port = ep->port;
1439 if (*__len > sizeof (struct sockaddr_in6))
1440 *__len = sizeof (struct sockaddr_in6);
1441 sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1442 copy_len = *__len - sa_len;
1444 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
1445 __in6_u.__u6_addr8, ep->ip, copy_len);
1458 vcom_socket_getpeername (int __fd, __SOCKADDR_ARG __addr,
1459 socklen_t * __restrict __len)
1462 vcom_socket_main_t *vsm = &vcom_socket_main;
1464 vcom_socket_t *vsock;
1465 u8 src_addr[sizeof (struct sockaddr_in6)];
1468 p = hash_get (vsm->sockidx_by_fd, __fd);
1472 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1476 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1479 if (!__addr || !__len)
1483 rv = vcom_session_getpeername (vsock->sid, &ep);
1485 rv = vcom_socket_copy_ep_to_sockaddr (__addr, __len, &ep);
1491 vcom_socket_send (int __fd, const void *__buf, size_t __n, int __flags)
1493 return vcom_socket_sendto (__fd, __buf, __n, __flags, NULL, 0);
1497 vcom_socket_recv (int __fd, void *__buf, size_t __n, int __flags)
1500 rv = vcom_socket_recvfrom (__fd, __buf, __n, __flags, NULL, 0);
1505 * RETURN 1 if __fd is (SOCK_STREAM, SOCK_SEQPACKET),
1509 vcom_socket_is_connection_mode_socket (int __fd)
1512 /* TBD define new vppcom api */
1513 vcom_socket_main_t *vsm = &vcom_socket_main;
1515 vcom_socket_t *vsock;
1520 p = hash_get (vsm->sockidx_by_fd, __fd);
1524 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1525 if (vsock && vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
1527 optlen = sizeof (type);
1528 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, &type, &optlen);
1533 /* get socket type */
1534 switch (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
1537 case SOCK_SEQPACKET:
1550 static inline ssize_t
1551 vcom_session_sendto (int __sid, void *__buf, size_t __n,
1552 int __flags, __CONST_SOCKADDR_ARG __addr,
1553 socklen_t __addr_len)
1555 vppcom_endpt_t *ep = 0;
1561 ep->vrf = VPPCOM_VRF_DEFAULT;
1562 switch (__addr->sa_family)
1565 ep->is_ip4 = VPPCOM_IS_IP4;
1567 (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
1569 (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
1573 ep->is_ip4 = VPPCOM_IS_IP6;
1575 (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
1577 (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
1581 return -EAFNOSUPPORT;
1585 return vppcom_session_sendto (__sid, __buf, __n, __flags, ep);;
1589 vcom_socket_sendto (int __fd, const void *__buf, size_t __n,
1590 int __flags, __CONST_SOCKADDR_ARG __addr,
1591 socklen_t __addr_len)
1593 vcom_socket_main_t *vsm = &vcom_socket_main;
1595 vcom_socket_t *vsock;
1602 p = hash_get (vsm->sockidx_by_fd, __fd);
1606 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1610 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1615 if (vcom_socket_is_connection_mode_socket (__fd))
1617 /* ignore __addr and _addr_len */
1618 /* and EISCONN may be returned when they are not NULL and 0 */
1619 if ((__addr != NULL) || (__addr_len != 0))
1628 return -EDESTADDRREQ;
1630 /* not a vppcom supported address family */
1631 if (!((__addr->sa_family == AF_INET) ||
1632 (__addr->sa_family == AF_INET6)))
1638 return vcom_session_sendto (vsock->sid, (void *) __buf, (int) __n,
1639 __flags, __addr, __addr_len);
1642 static inline ssize_t
1643 vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
1644 int __flags, __SOCKADDR_ARG __addr,
1645 socklen_t * __restrict __addr_len)
1649 u8 src_addr[sizeof (struct sockaddr_in6)];
1654 rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, &ep);
1657 rv = vcom_socket_copy_ep_to_sockaddr (__addr, __addr_len, &ep);
1660 rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, NULL);
1666 vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
1667 int __flags, __SOCKADDR_ARG __addr,
1668 socklen_t * __restrict __addr_len)
1671 vcom_socket_main_t *vsm = &vcom_socket_main;
1673 vcom_socket_t *vsock;
1675 if (__addr && !__addr_len)
1678 p = hash_get (vsm->sockidx_by_fd, __fd);
1682 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1686 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1691 rv = vcom_session_recvfrom (vsock->sid, __buf, __n,
1692 __flags, __addr, __addr_len);
1696 /* TBD: move it to vppcom */
1697 static inline ssize_t
1698 vcom_session_sendmsg (int __sid, const struct msghdr *__message, int __flags)
1701 /* rv = vppcom_session_write (__sid, (void *) __message->__buf,
1707 vcom_socket_sendmsg (int __fd, const struct msghdr * __message, int __flags)
1710 vcom_socket_main_t *vsm = &vcom_socket_main;
1712 vcom_socket_t *vsock;
1714 p = hash_get (vsm->sockidx_by_fd, __fd);
1718 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1722 if (vcom_socket_is_connection_mode_socket (__fd))
1724 /* ignore __addr and _addr_len */
1725 /* and EISCONN may be returned when they are not NULL and 0 */
1726 if ((__message->msg_name != NULL) || (__message->msg_namelen != 0))
1733 /* TBD: validate __message->msg_name and __message->msg_namelen
1734 * and return -EINVAL on validation error
1739 rv = vcom_session_sendmsg (vsock->sid, __message, __flags);
1746 vcom_socket_sendmmsg (int __fd, struct mmsghdr *__vmessages,
1747 unsigned int __vlen, int __flags)
1750 /* TBD: define a new vppcom api */
1755 /* TBD: move it to vppcom */
1756 static inline ssize_t
1757 vcom_session_recvmsg (int __sid, struct msghdr *__message, int __flags)
1760 /* rv = vppcom_session_read (__sid, (void *) __message->__buf,
1767 vcom_socket_recvmsg (int __fd, struct msghdr * __message, int __flags)
1770 vcom_socket_main_t *vsm = &vcom_socket_main;
1772 vcom_socket_t *vsock;
1774 p = hash_get (vsm->sockidx_by_fd, __fd);
1778 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1782 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1790 /* validate __flags */
1792 rv = vcom_session_recvmsg (vsock->sid, __message, __flags);
1798 vcom_socket_recvmmsg (int __fd, struct mmsghdr *__vmessages,
1799 unsigned int __vlen, int __flags,
1800 struct timespec *__tmo)
1802 /* TBD: define a new vppcom api */
1807 /* TBD: move it to vppcom */
1809 vcom_session_get_sockopt (int __sid, int __level, int __optname,
1810 void *__restrict __optval,
1811 socklen_t * __restrict __optlen)
1815 /* 1. for socket level options that are NOT socket attributes
1816 * and that has corresponding vpp options get from vppcom */
1823 *(int *) __optval = 0;
1831 /* 2. unhandled options */
1836 vcom_socket_getsockopt (int __fd, int __level, int __optname,
1837 void *__restrict __optval,
1838 socklen_t * __restrict __optlen)
1841 vcom_socket_main_t *vsm = &vcom_socket_main;
1843 vcom_socket_t *vsock;
1845 if (!__optval || !__optlen)
1848 p = hash_get (vsm->sockidx_by_fd, __fd);
1852 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
1856 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
1865 * 1. for socket level options that are socket attributes,
1866 * get from libc_getsockopt.
1867 * 2. for socket level options that are NOT socket
1868 * attributes and that has corresponding vpp options
1870 * 3. for socket level options unimplemented
1871 * return -ENOPROTOOPT */
1889 case SO_TIMESTAMPNS:
1890 case SO_TIMESTAMPING:
1903 case SO_WIFI_STATUS:
1906 case SO_BINDTODEVICE:
1908 case SO_LOCK_FILTER:
1909 case SO_BPF_EXTENSIONS:
1910 case SO_SELECT_ERR_QUEUE:
1911 #ifdef CONFIG_NET_RX_BUSY_POLL
1914 case SO_MAX_PACING_RATE:
1915 #ifdef SO_INCOMING_CPU
1916 case SO_INCOMING_CPU:
1918 rv = libc_getsockopt (__fd, __level, __optname, __optval, __optlen);
1927 rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
1928 __optval, __optlen);
1932 /* We implement the SO_SNDLOWAT etc to not be settable
1935 return -ENOPROTOOPT;
1941 /* 1. handle options that are NOT socket level options,
1942 * but have corresponding vpp otions. */
1943 rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
1944 __optval, __optlen);
1951 /* TBD: move it to vppcom */
1953 vcom_session_setsockopt (int __sid, int __level, int __optname,
1954 const void *__optval, socklen_t __optlen)
1956 int rv = -EOPNOTSUPP;
1965 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE, 0, 0);
1969 vppcom_session_attr (__sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL, 0, 0);
1979 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_V6ONLY, 0, 0);
1989 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_KEEPALIVE, 0, 0);
1992 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_REUSEADDR, 0, 0);
1995 rv = vppcom_session_attr (__sid, VPPCOM_ATTR_SET_BROADCAST, 0, 0);
2009 vcom_socket_setsockopt (int __fd, int __level, int __optname,
2010 const void *__optval, socklen_t __optlen)
2013 vcom_socket_main_t *vsm = &vcom_socket_main;
2015 vcom_socket_t *vsock;
2017 p = hash_get (vsm->sockidx_by_fd, __fd);
2021 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2025 if (vsock->type != SOCKET_TYPE_VPPCOM_BOUND)
2029 * Options without arguments
2032 if (__optname == SO_BINDTODEVICE)
2034 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2045 if (__optlen < sizeof (int))
2054 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2055 __optval, __optlen);
2068 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2069 __optval, __optlen);
2075 /* handle options at socket level */
2082 rv = vcom_session_setsockopt (vsock->sid, __level, __optname,
2083 __optval, __optlen);
2087 * 1. for socket level options that are socket attributes,
2088 * set it from libc_getsockopt
2089 * 2. for socket level options that are NOT socket
2090 * attributes and that has corresponding vpp options
2091 * set it from vppcom
2092 * 3. for socket level options unimplemented
2093 * return -ENOPROTOOPT */
2109 case SO_TIMESTAMPNS:
2110 case SO_TIMESTAMPING:
2123 case SO_WIFI_STATUS:
2127 * SO_BINDTODEVICE already handled as
2128 * "Options without arguments" */
2129 /* case SO_BINDTODEVICE: */
2131 case SO_LOCK_FILTER:
2132 case SO_BPF_EXTENSIONS:
2133 case SO_SELECT_ERR_QUEUE:
2134 #ifdef CONFIG_NET_RX_BUSY_POLL
2137 case SO_MAX_PACING_RATE:
2138 #ifdef SO_INCOMING_CPU
2139 case SO_INCOMING_CPU:
2141 rv = libc_setsockopt (__fd, __level, __optname, __optval, __optlen);
2150 /* We implement the SO_SNDLOWAT etc to not be settable
2153 return -ENOPROTOOPT;
2159 return -ENOPROTOOPT;
2166 vcom_socket_listen (int __fd, int __n)
2169 vcom_socket_main_t *vsm = &vcom_socket_main;
2171 vcom_socket_t *vsock;
2173 p = hash_get (vsm->sockidx_by_fd, __fd);
2176 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2178 /* TBD vppcom to accept __n parameter */
2179 rv = vppcom_session_listen (vsock->sid, __n);
2186 vcom_socket_connected_socket (int __fd, int __sid,
2188 int *__type, int *__protocol, int flags)
2191 vcom_socket_main_t *vsm = &vcom_socket_main;
2192 vcom_socket_t *vsock;
2199 optlen = sizeof (*__domain);
2200 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_DOMAIN, __domain, &optlen);
2207 optlen = sizeof (*__type);
2208 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_TYPE, __type, &optlen);
2215 optlen = sizeof (*__protocol);
2216 rv = libc_getsockopt (__fd, SOL_SOCKET, SO_PROTOCOL, __protocol, &optlen);
2223 fd = vcom_socket_open_socket (*__domain, *__type | flags, *__protocol);
2230 pool_get (vsm->vsockets, vsock);
2231 vsocket_init (vsock);
2233 sockidx = vsock - vsm->vsockets;
2234 hash_set (vsm->sockidx_by_fd, fd, sockidx);
2236 vsocket_set (vsock, fd, __sid, SOCKET_TYPE_VPPCOM_BOUND);
2243 /* If flag is 0, then accept4() is the same as accept().
2244 * SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags
2247 vcom_socket_accept_flags (int __fd, __SOCKADDR_ARG __addr,
2248 socklen_t * __restrict __addr_len, int flags)
2251 vcom_socket_main_t *vsm = &vcom_socket_main;
2253 vcom_socket_t *vsock;
2261 uint8_t addr8[sizeof (struct in6_addr)];
2266 /* validate flags */
2273 * case SOCK_NONBLOCK:
2274 * case SOCK_CLOEXEC:
2275 * case SOCK_NONBLOCK | SOCK_CLOEXEC:
2282 /* flags can be 0 or can be bitwise OR
2283 * of any of SOCK_NONBLOCK and SOCK_CLOEXEC */
2286 fprintf (stderr, "[%d] vcom_socket_accept_flags: "
2287 "fd = %d, __addr = %p, __addr_len = %p flags = %d (0x%x)\n",
2288 getpid (), __fd, __addr, __addr_len, flags, flags);
2290 if (!(!flags || (flags & (SOCK_NONBLOCK | SOCK_CLOEXEC))))
2292 /* TBD: return proper error code */
2293 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2294 "invalid flags = %d (0x%x)\n", getpid (), flags, flags);
2299 /* TBD: return proper error code */
2301 if (!vcom_socket_is_connection_mode_socket (__fd))
2303 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2304 "connection mode socket support TBD!\n", getpid ());
2308 p = hash_get (vsm->sockidx_by_fd, __fd);
2311 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2314 rv = vcom_fcntl (vsock->fd, F_GETFL, 0);
2317 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2318 "vcom_fcnt() returned %d!\n", getpid (), rv);
2323 if (!(rv & O_NONBLOCK))
2325 /* socket is not marked as nonblocking
2326 * and no pending connections are present
2327 * on the queue, accept () blocks the caller
2328 * until a connection is present.
2330 rv = vppcom_session_accept (vsock->sid, &ep,
2331 -1.0 /* wait forever */ );
2335 /* The file descriptor refers to a socket and has been
2336 * marked nonblocking(O_NONBLOCK) and the accept would
2339 /* is non blocking */
2340 rv = vppcom_session_accept (vsock->sid, &ep, 0);
2341 /* If the socket is marked nonblocking and
2342 * no pending connections are present on the
2343 * queue, accept fails with the error
2344 * EAGAIN or EWOULDBLOCK
2346 if (rv == VPPCOM_ETIMEDOUT)
2353 if (rv != VPPCOM_EAGAIN)
2354 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2355 "vppcom_session_accept() returned %d!", getpid (), rv);
2361 /* create a new connected socket resource and set flags
2362 * on the new file descriptor.
2363 * update vsockets and sockidx_by_fd table
2365 fd = vcom_socket_connected_socket (__fd, sid,
2366 &domain, &type, &protocol, flags);
2369 fprintf (stderr, "[%d] ERROR: vcom_socket_accept_flags: "
2370 "vcom_socket_connected_socket() returned %d!",
2377 /* TBD populate __addr and __addr_len */
2378 /* TBD: The returned address is truncated if the buffer
2379 * provided is too small, in this case, __addr_len will
2380 * return a value greater than was supplied to the call.*/
2385 /* TBD populate __addr and __addr_len */
2389 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2390 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2391 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2392 addr8, sizeof (struct in_addr));
2393 /* TBD: populate __addr_len */
2396 *__addr_len = sizeof (struct sockaddr_in);
2401 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2402 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2403 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2404 __in6_u.__u6_addr8, addr8,
2405 sizeof (struct in6_addr));
2406 /* TBD: populate __addr_len */
2409 *__addr_len = sizeof (struct sockaddr_in6);
2414 return -EAFNOSUPPORT;
2422 ((struct sockaddr_in *) __addr)->sin_family = AF_INET;
2423 ((struct sockaddr_in *) __addr)->sin_port = ep.port;
2424 memcpy (&((struct sockaddr_in *) __addr)->sin_addr,
2425 addr8, sizeof (struct in_addr));
2426 /* TBD: populate __addr_len */
2429 *__addr_len = sizeof (struct sockaddr_in);
2434 ((struct sockaddr_in6 *) __addr)->sin6_family = AF_INET6;
2435 ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
2436 memcpy (((struct sockaddr_in6 *) __addr)->sin6_addr.
2437 __in6_u.__u6_addr8, addr8,
2438 sizeof (struct in6_addr));
2439 /* TBD: populate __addr_len */
2442 *__addr_len = sizeof (struct sockaddr_in6);
2447 return -EAFNOSUPPORT;
2457 vcom_socket_accept (int __fd, __SOCKADDR_ARG __addr,
2458 socklen_t * __restrict __addr_len)
2460 /* set flags to 0 for accept() */
2461 return vcom_socket_accept_flags (__fd, __addr, __addr_len, 0);
2465 vcom_socket_accept4 (int __fd, __SOCKADDR_ARG __addr,
2466 socklen_t * __restrict __addr_len, int __flags)
2468 /* SOCK_NONBLOCK and SOCK_CLOEXEC can be bitwise ORed in flags */
2469 return vcom_socket_accept_flags (__fd, __addr, __addr_len, __flags);
2472 /* TBD: move it to vppcom */
2474 vcom_session_shutdown (int __fd, int __how)
2480 vcom_socket_shutdown (int __fd, int __how)
2483 vcom_socket_main_t *vsm = &vcom_socket_main;
2485 vcom_socket_t *vsock;
2487 p = hash_get (vsm->sockidx_by_fd, __fd);
2490 vsock = pool_elt_at_index (vsm->vsockets, p[0]);
2496 rv = vcom_session_shutdown (vsock->sid, __how);
2510 vcom_socket_epoll_create1 (int __flags)
2513 vcom_socket_main_t *vsm = &vcom_socket_main;
2514 vcom_epoll_t *vepoll;
2520 epfd = vcom_socket_open_epoll (__flags);
2527 vep_idx = vppcom_epoll_create ();
2531 goto out_close_epoll;
2534 pool_get (vsm->vepolls, vepoll);
2535 vepoll_init (vepoll);
2537 epollidx = vepoll - vsm->vepolls;
2538 hash_set (vsm->epollidx_by_epfd, epfd, epollidx);
2540 vepoll_set (vepoll, epfd, vep_idx, EPOLL_TYPE_VPPCOM_BOUND, __flags, 0, 0);
2545 vcom_socket_close_epoll (epfd);
2551 * PRE: vppcom_epoll_ctl() is successful
2552 * free_vepitem_on_del : 0 - no_pool_put, 1 - pool_put
2555 vcom_socket_ctl_vepitem (int __epfd, int __op, int __fd,
2556 struct epoll_event *__event,
2557 i32 vep_idx, vcom_epoll_t * vepoll,
2558 i32 vfd_id, void *vfd, vcom_fd_type_t type,
2559 int free_vepitem_on_del)
2562 vcom_socket_main_t *vsm = &vcom_socket_main;
2563 vcom_epitem_t *vepitem;
2565 vcom_epitem_key_t epfdfd = {.epfd = __epfd,.fd = __fd };
2569 i32 *vepitemidxs = 0;
2571 struct epoll_event revent = {.events = 0,.data.fd = INVALID_FD };
2575 /* perform control operations on the epoll instance */
2580 * supplied file descriptor is already
2581 * registered with this epoll instance
2583 /* vepitem exists */
2584 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2591 /* add a new vepitem */
2592 pool_get (vsm->vepitems, vepitem);
2593 vepitem_init (vepitem);
2595 vepitemidx = vepitem - vsm->vepitems;
2596 hash_set (vsm->epitemidx_by_epfdfd, epfdfd.key, vepitemidx);
2597 vepitem_set (vepitem, __epfd, __fd, __fd, __fd, type, *__event, revent);
2599 /* update epitemidxs */
2601 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2602 if (!p) /* not exist */
2605 vec_add1 (vepitemidxs, vepitemidx);
2606 hash_set (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs);
2610 vepitemidxs = *(i32 **) p;
2611 vec_add1 (vepitemidxs, vepitemidx);
2612 hash_set3 (vsm->epitemidxs_by_epfd, __epfd, vepitemidxs, 0);
2614 /* update epitemidxs */
2616 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2617 if (!p) /* not exist */
2620 vec_add1 (vepitemidxs, vepitemidx);
2621 hash_set (vsm->epitemidxs_by_fd, __fd, vepitemidxs);
2625 vepitemidxs = *(i32 **) p;
2626 vec_add1 (vepitemidxs, vepitemidx);
2627 hash_set3 (vsm->epitemidxs_by_fd, __fd, vepitemidxs, 0);
2630 /* increment vepoll fd count by 1 */
2639 * supplied file descriptor is not
2640 * registered with this epoll instance
2642 /* vepitem not exist */
2643 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2649 vepitem = pool_elt_at_index (vsm->vepitems, p[0]);
2652 vepitem->event = *__event;
2653 vepitem->revent = revent;
2662 * supplied file descriptor is not
2663 * registered with this epoll instance
2665 /* vepitem not exist */
2666 p = hash_get (vsm->epitemidx_by_epfdfd, epfdfd.key);
2672 vepitemidx = *(i32 *) p;
2673 hash_unset (vsm->epitemidx_by_epfdfd, epfdfd.key);
2675 /* update epitemidxs */
2677 p = hash_get (vsm->epitemidxs_by_epfd, __epfd);
2678 if (!p) /* not exist */
2685 vepitemidxs = *(i32 **) p;
2686 vec_idx = vec_search (vepitemidxs, vepitemidx);
2689 vec_del1 (vepitemidxs, vec_idx);
2690 if (!vec_len (vepitemidxs))
2692 vec_free (vepitemidxs);
2693 hash_unset (vsm->epitemidxs_by_epfd, __epfd);
2698 /* update epitemidxs */
2700 p = hash_get (vsm->epitemidxs_by_fd, __fd);
2701 if (!p) /* not exist */
2708 vepitemidxs = *(i32 **) p;
2709 vec_idx = vec_search (vepitemidxs, vepitemidx);
2712 vec_del1 (vepitemidxs, vec_idx);
2713 if (!vec_len (vepitemidxs))
2715 vec_free (vepitemidxs);
2716 hash_unset (vsm->epitemidxs_by_fd, __fd);
2721 /* pool put vepitem */
2722 vepitem = pool_elt_at_index (vsm->vepitems, vepitemidx);
2723 if (free_vepitem_on_del)
2730 vepitem_init (vepitem);
2731 pool_put (vsm->vepitems, vepitem);
2737 vepitem_init (vepitem);
2741 /* decrement vepoll fd count by 1 */
2759 * PRE: 00. null pointer check on __event
2760 * 01. all other parameters are validated
2764 vcom_socket_epoll_ctl_internal (int __epfd, int __op, int __fd,
2765 struct epoll_event *__event,
2766 int free_vepitem_on_del)
2770 vcom_epoll_t *vepoll;
2771 vcom_socket_t *vfd_vsock;
2775 /* get vep_idx and vepoll */
2776 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
2777 if (vep_idx == INVALID_VEP_IDX)
2782 /* get vcom fd type, vfd_id and vfd */
2783 sid = vcom_socket_get_sid_and_vsock (__fd, &vfd_vsock);
2784 if ((sid != INVALID_SESSION_ID) &&
2785 vcom_socket_type_is_vppcom_bound (vfd_vsock->type))
2787 rv = vppcom_epoll_ctl (vep_idx, __op, sid, __event);
2788 if (rv == VPPCOM_OK)
2790 cnt = ((__op == EPOLL_CTL_ADD) ? 1 :
2791 (__op == EPOLL_CTL_DEL) ? -1 : 0);
2792 vepoll->count += cnt;
2793 vepoll->vcl_cnt += cnt;
2797 "[%d] vcom_socket_epoll_ctl_i: vppcom_epoll_ctl() "
2798 "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d"
2799 "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
2800 getpid (), rv, __epfd, vep_idx, __fd, sid, __op,
2801 vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
2805 rv = libc_epoll_ctl (__epfd, __op, __fd, __event);
2808 cnt = ((__op == EPOLL_CTL_ADD) ? 1 :
2809 (__op == EPOLL_CTL_DEL) ? -1 : 0);
2810 vepoll->count += cnt;
2811 vepoll->libc_cnt += cnt;
2815 "[%d] vcom_socket_epoll_ctl_i: libc_epoll_ctl() "
2816 "returned %d\n\tepfd %d, vep_idx %d, fd %d sid %d op %d"
2817 "\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
2818 getpid (), rv, __epfd, vep_idx, __fd, sid, __op,
2819 vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
2826 vcom_socket_epoll_ctl (int __epfd, int __op, int __fd,
2827 struct epoll_event *__event)
2831 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 1);
2836 vcom_socket_epoll_ctl1 (int __epfd, int __op, int __fd,
2837 struct epoll_event *__event)
2841 rv = vcom_socket_epoll_ctl_internal (__epfd, __op, __fd, __event, 0);
2846 vcom_socket_epoll_pwait (int __epfd, struct epoll_event *__events,
2847 int __maxevents, int __timeout,
2848 const __sigset_t * __ss)
2850 vcom_socket_main_t *vsm = &vcom_socket_main;
2853 double time_to_wait = (double) 0;
2854 double timeout, now = 0;
2855 vcom_epoll_t *vepoll;
2857 static struct epoll_event *libc_ev = 0;
2859 /* validate __event */
2860 if (!__events || (__timeout < -1))
2862 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: "
2863 "Bad args __events %p, __timeout %d\n", getpid (),
2864 __events, __timeout);
2869 time_to_wait = ((__timeout >= 0) ? (double) __timeout / (double) 1000 : 0);
2871 vep_idx = vcom_socket_get_vep_idx_and_vepoll (__epfd, &vepoll);
2872 if (vep_idx == INVALID_VEP_IDX)
2874 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: "
2875 "Bad epoll fd %d\n", getpid (), __epfd);
2879 if (vepoll->count <= 0)
2881 fprintf (stderr, "[%d] ERROR: vcom_socket_epoll_pwait: No events"
2882 " in epfd!\n\tcount %d, vcl_cnt %d, libc_cnt %d\n",
2883 getpid (), vepoll->count, vepoll->vcl_cnt, vepoll->libc_cnt);
2888 if (vepoll->libc_cnt == 0)
2891 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: libc_cnt = 0, "
2892 "calling vppcom_epoll_wait() time_to_wait = %f\n",
2893 getpid (), time_to_wait);
2894 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, time_to_wait);
2896 else if (vepoll->vcl_cnt == 0)
2899 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = 0, "
2900 "calling libc_epoll_pwait()\n", getpid ());
2901 rv = libc_epoll_pwait (__epfd, __events, __maxevents, __timeout, __ss);
2906 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: vcl_cnt = %d, "
2907 "libc_cnt = %d -> mixed polling (time_to_wait = %f, "
2908 "__timeout = %d)\n",
2909 getpid (), vepoll->vcl_cnt, vepoll->libc_cnt,
2910 time_to_wait, __timeout);
2911 vec_validate (libc_ev, __maxevents);
2912 timeout = clib_time_now (&vsm->clib_time) + time_to_wait;
2915 rv = vppcom_epoll_wait (vep_idx, __events, __maxevents, 0);
2916 rv2 = libc_epoll_pwait (__epfd, libc_ev, __maxevents, 1, __ss);
2917 if (VCOM_DEBUG == 666)
2918 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: "
2919 "rv = %d, rv2 = %d, timeout = %f, now = %f\n",
2920 getpid (), rv, rv2, timeout, now);
2921 if ((rv > 0) || (rv2 > 0))
2924 fprintf (stderr, "[%d] vcom_socket_epoll_pwait: "
2925 "rv = %d, rv2 = %d\n", getpid (), rv, rv2);
2926 int n = __maxevents - rv;
2927 n = rv2 <= n ? rv2 : n;
2928 rv = (rv > 0) ? rv : 0;
2930 clib_memcpy (&__events[rv], libc_ev, n * sizeof (*libc_ev));
2934 else if ((rv < 0) || (rv2 < 0))
2938 "[%d] ERROR: vppcom_epoll_wait() returned %d\n",
2943 "[%d] ERROR: libc_epoll_wait() failed, errno %d\n",
2945 rv = (rv < 0) ? rv : -errno;
2949 if (__timeout != -1)
2950 now = clib_time_now (&vsm->clib_time);
2952 while (now < timeout);
2956 vec_reset_length (libc_ev);
2961 vcom_pollfds_2_selectfds (
2963 struct pollfd *__fds, nfds_t __nfds,
2966 fd_set * __restrict vcom_readfds,
2967 fd_set * __restrict vcom_writefds,
2968 fd_set * __restrict vcom_exceptfds)
2972 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
2974 /* ignore negative fds */
2975 if (__fds[fds_idx].fd < 0)
2980 /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
2981 FD_SET (__fds[fds_idx].fd, vcom_exceptfds);
2983 /* requested events */
2984 if (__fds[fds_idx].events)
2986 if (__fds[fds_idx].events & POLLIN)
2988 FD_SET (__fds[fds_idx].fd, vcom_readfds);
2990 if (__fds[fds_idx].events & POLLPRI)
2992 FD_SET (__fds[fds_idx].fd, vcom_readfds);
2994 if (__fds[fds_idx].events & POLLOUT)
2996 FD_SET (__fds[fds_idx].fd, vcom_writefds);
2998 #if defined __USE_XOPEN || defined __USE_XOPEN2K8
2999 if (__fds[fds_idx].events & POLLRDNORM)
3001 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3003 if (__fds[fds_idx].events & POLLRDBAND)
3005 FD_SET (__fds[fds_idx].fd, vcom_readfds);
3007 if (__fds[fds_idx].events & POLLWRNORM)
3009 FD_SET (__fds[fds_idx].fd, vcom_writefds);
3011 if (__fds[fds_idx].events & POLLWRBAND)
3013 FD_SET (__fds[fds_idx].fd, vcom_writefds);
3017 } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
3021 vcom_selectfds_2_pollfds (
3023 struct pollfd *__fds, nfds_t __nfds, int *nfd,
3026 fd_set * __restrict vcom_readfds,
3027 fd_set * __restrict vcom_writefds,
3028 fd_set * __restrict vcom_exceptfds)
3033 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3035 /* ignore negative fds */
3036 if (__fds[fds_idx].fd < 0)
3038 __fds[fds_idx].revents = 0;
3041 /* for POLLRDHUP, POLLERR, POLLHUP and POLLNVAL */
3042 if (FD_ISSET (__fds[fds_idx].fd, vcom_exceptfds))
3045 * TBD: for now any select exception
3046 * is flagged as POLLERR
3048 __fds[fds_idx].revents |= POLLERR;
3051 /* requested events */
3052 if (__fds[fds_idx].events & POLLIN)
3054 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3056 __fds[fds_idx].revents |= POLLIN;
3059 if (__fds[fds_idx].events & POLLPRI)
3061 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3063 __fds[fds_idx].revents |= POLLIN;
3066 if (__fds[fds_idx].events & POLLOUT)
3068 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3070 __fds[fds_idx].revents |= POLLOUT;
3073 #if defined __USE_XOPEN || defined __USE_XOPEN2K8
3074 if (__fds[fds_idx].events & POLLRDNORM)
3076 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3078 __fds[fds_idx].revents |= POLLRDNORM;
3081 if (__fds[fds_idx].events & POLLRDBAND)
3083 if (FD_ISSET (__fds[fds_idx].fd, vcom_readfds))
3085 __fds[fds_idx].revents |= POLLRDBAND;
3088 if (__fds[fds_idx].events & POLLWRNORM)
3090 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3092 __fds[fds_idx].revents |= POLLWRNORM;
3095 if (__fds[fds_idx].events & POLLWRBAND)
3097 if (FD_ISSET (__fds[fds_idx].fd, vcom_writefds))
3099 __fds[fds_idx].revents |= POLLWRBAND;
3103 } /* for (fds_idx = 0; fds_idx < __nfds; fds_idx++) */
3107 * the number of structures which have nonzero revents fields
3108 * (in other words, those descriptors with events or
3112 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3114 /* ignore negative fds */
3115 if (__fds[fds_idx].fd < 0)
3120 if (__fds[fds_idx].revents)
3128 * PRE: parameters are validated,
3129 * vcom_socket_poll is always called with __timeout set to zero
3130 * hence returns immediately
3132 * ACTION: handle non negative validated vcom fds and ignore rest
3136 * implements vcom_socket_poll () interface
3138 * internally uses vcom_socket_select ()
3139 * to realize the behavior
3142 vcom_socket_poll_select_impl (struct pollfd *__fds, nfds_t __nfds,
3152 fd_set vcom_readfds;
3153 fd_set vcom_writefds;
3154 fd_set vcom_exceptfds;
3156 /* invalid max_vcom_fd is -1 */
3157 int max_vcom_fd = -1;
3159 /* __timeout is zero to get ready events and return immediately */
3160 struct timeval tv = {.tv_sec = 0,.tv_usec = 0 };
3162 /* validate __nfds from select perspective */
3163 if (__nfds > FD_SETSIZE)
3169 /* zero vcom fd sets */
3185 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3187 /* ignore negative fds */
3188 if (__fds[fds_idx].fd < 0)
3193 /* non negative validated vcom fds */
3194 if (__fds[fds_idx].fd > FD_SETSIZE)
3200 /* max_vcom_fd and vcom_nfd */
3201 if (__fds[fds_idx].fd > max_vcom_fd)
3203 /* requested events */
3204 if (__fds[fds_idx].events)
3206 max_vcom_fd = __fds[fds_idx].fd;
3212 vcom_nfds = max_vcom_fd != -1 ? max_vcom_fd + 1 : 0;
3220 vcom_pollfds_2_selectfds (
3225 &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
3227 /* select on vcom fds */
3228 vcom_nfd = vcom_socket_select (vcom_nfds,
3230 &vcom_writefds, &vcom_exceptfds, &tv);
3233 "[%d] vcom_socket_select: "
3234 "'%04d'='%04d'\n", getpid (), vcom_nfd, vcom_nfds);
3242 vcom_selectfds_2_pollfds (
3244 __fds, __nfds, &nfd,
3247 &vcom_readfds, &vcom_writefds, &vcom_exceptfds);
3256 * TBD: remove this static function once vppcom
3257 * has an implementation in place
3262 vppcom_poll (struct pollfd *__fds, nfds_t __nfds, double time_to_wait)
3268 vcom_socket_poll_vppcom_impl (struct pollfd *__fds, nfds_t __nfds,
3273 /* in seconds eg. 3.123456789 seconds */
3274 double time_to_wait = (double) 0;
3279 /* replace vcom fd with session idx */
3280 for (fds_idx = 0; fds_idx < __nfds; fds_idx++)
3282 /* ignore negative fds */
3283 if (__fds[fds_idx].fd < 0)
3288 /* non negative validated vcom fds */
3289 sid = vcom_socket_get_sid (__fds[fds_idx].fd);
3290 if (sid != INVALID_SESSION_ID)
3292 __fds[fds_idx].fd = sid;
3297 vep_idx = vcom_socket_get_vep_idx (__fds[fds_idx].fd);
3298 if (vep_idx != INVALID_VEP_IDX)
3300 __fds[fds_idx].fd = vep_idx;
3309 /* validate __timeout */
3312 time_to_wait = (double) __timeout / (double) 1000;
3314 else if (__timeout == 0)
3316 time_to_wait = (double) 0;
3323 return vppcom_poll (__fds, __nfds, time_to_wait);
3327 vcom_socket_poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
3329 /* select an implementation */
3331 /* return vcom_socket_poll_vppcom_impl (__fds, __nfds, __timeout); */
3332 return vcom_socket_poll_select_impl (__fds, __nfds, __timeout);
3337 vcom_socket_ppoll (struct pollfd *__fds, nfds_t __nfds,
3338 const struct timespec *__timeout, const __sigset_t * __ss)
3345 vcom_socket_main_init (void)
3347 vcom_socket_main_t *vsm = &vcom_socket_main;
3350 printf ("vcom_socket_main_init\n");
3354 /* TBD: define FD_MAXSIZE and use it here */
3355 pool_alloc (vsm->vsockets, FD_SETSIZE);
3356 vsm->sockidx_by_fd = hash_create (0, sizeof (i32));
3358 pool_alloc (vsm->vepolls, FD_SETSIZE);
3359 vsm->epollidx_by_epfd = hash_create (0, sizeof (i32));
3361 pool_alloc (vsm->vepitems, FD_SETSIZE);
3362 vsm->epitemidx_by_epfdfd = hash_create (0, sizeof (i32));
3364 vsm->epitemidxs_by_epfd = hash_create (0, sizeof (i32 *));
3365 vsm->epitemidxs_by_fd = hash_create (0, sizeof (i32 *));
3367 clib_time_init (&vsm->clib_time);
3377 vcom_socket_main_show (void)
3379 vcom_socket_main_t *vsm = &vcom_socket_main;
3380 vcom_socket_t *vsock;
3382 vcom_epoll_t *vepoll;
3384 vcom_epitem_t *vepitem;
3388 i32 *vepitemidxs, *vepitemidxs_var;
3392 /* from active list of vsockets show vsock */
3395 pool_foreach (vsock, vsm->vsockets,
3398 "fd='%04d', sid='%08x',type='%-30s'\n",
3399 vsock->fd, vsock->sid,
3400 vcom_socket_type_str (vsock->type));
3404 /* from active list of vepolls, show vepoll */
3407 pool_foreach (vepoll, vsm->vepolls,
3410 "epfd='%04d', vep_idx='%08x', "
3412 "flags='%d', count='%d', close='%d'\n",
3413 vepoll->epfd, vepoll->vep_idx,
3414 vcom_socket_epoll_type_str (vepoll->type),
3415 vepoll->flags, vepoll->count, vepoll->close);
3419 /* from active list of vepitems, show vepitem */
3422 pool_foreach (vepitem, vsm->vepitems,
3425 "epfd='%04d', fd='%04d', "
3426 "next_fd='%04d', prev_fd='%04d', "
3428 "events='%04x', revents='%04x'\n",
3429 vepitem->epfd, vepitem->fd,
3430 vepitem->next_fd, vepitem->prev_fd,
3431 vcom_socket_vcom_fd_type_str (vepitem->type),
3432 vepitem->event.events, vepitem->revent.events);
3437 /* show epitemidxs for epfd */
3439 hash_foreach (epfd, vepitemidxs,
3440 vsm->epitemidxs_by_epfd,
3442 printf("\n[ '%04d': ", epfd);
3443 vec_foreach (vepitemidxs_var,vepitemidxs)
3445 printf("'%04d' ", (int)vepitemidxs_var[0]);
3451 /* show epitemidxs for fd */
3453 hash_foreach (fd, vepitemidxs,
3454 vsm->epitemidxs_by_fd,
3456 printf("\n{ '%04d': ", fd);
3457 vec_foreach (vepitemidxs_var,vepitemidxs)
3459 printf("'%04d' ", (int)vepitemidxs_var[0]);
3469 vcom_socket_main_destroy (void)
3471 vcom_socket_main_t *vsm = &vcom_socket_main;
3472 vcom_socket_t *vsock;
3474 vcom_epoll_t *vepoll;
3476 vcom_epitem_t *vepitem;
3484 printf ("vcom_socket_main_destroy\n");
3490 * from active list of vepitems,
3491 * remove all "vepitem" elements from the pool in a safe way
3495 pool_flush (vepitem, vsm->vepitems,
3497 if ((vepitem->type == FD_TYPE_EPOLL) ||
3498 (vepitem->type == FD_TYPE_VCOM_SOCKET))
3500 vcom_socket_epoll_ctl1 (vepitem->epfd, EPOLL_CTL_DEL,
3502 vepitem_init (vepitem);
3507 pool_free (vsm->vepitems);
3508 hash_free (vsm->epitemidx_by_epfdfd);
3510 /* free vepitemidxs for each epfd */
3512 hash_foreach (epfd, vepitemidxs,
3513 vsm->epitemidxs_by_epfd,
3515 vec_free (vepitemidxs);
3518 hash_free (vsm->epitemidxs_by_epfd);
3520 /* free vepitemidxs for each fd */
3522 hash_foreach (fd, vepitemidxs,
3523 vsm->epitemidxs_by_fd,
3525 vec_free (vepitemidxs);
3528 hash_free (vsm->epitemidxs_by_fd);
3532 * from active list of vsockets,
3533 * close socket and vppcom session
3537 pool_foreach (vsock, vsm->vsockets,
3539 if (vsock->type == SOCKET_TYPE_VPPCOM_BOUND)
3541 vppcom_session_close (vsock->sid);
3542 vcom_socket_close_socket (vsock->fd);
3543 vsocket_init (vsock);
3549 * return vsocket element to the pool
3553 pool_flush (vsock, vsm->vsockets,
3555 // vsocket_init(vsock);
3560 pool_free (vsm->vsockets);
3561 hash_free (vsm->sockidx_by_fd);
3564 * from active list of vepolls,
3565 * close epoll and vppcom_epoll
3569 pool_foreach (vepoll, vsm->vepolls,
3571 if (vepoll->type == EPOLL_TYPE_VPPCOM_BOUND)
3573 vppcom_session_close (vepoll->vep_idx);
3574 vcom_socket_close_epoll (vepoll->epfd); /* TBD: */
3575 vepoll_init (vepoll);
3581 * return vepoll element to the pool
3585 pool_flush (vepoll, vsm->vepolls,
3587 // vepoll_init(vepoll);
3592 pool_free (vsm->vepolls);
3593 hash_free (vsm->epollidx_by_epfd);
3601 * fd.io coding-style-patch-verification: ON
3604 * eval: (c-set-style "gnu")