[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT/LWIP PATCH 8/8] Provide poll() and select() wrappers around lwip versions



This takes the vfscore-provided file descriptors, translates them into
lwip file descriptors, and will run the lwip versions on those sockets.
If any of the file descriptors provided isn't an LWIP socket, the call
will fail with a return of -1, errno EBADF.

Signed-off-by: Florian Schmidt <florian.schmidt@xxxxxxxxx>
---
 exportsyms.uk |   2 +-
 sockets.c     | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/exportsyms.uk b/exportsyms.uk
index b17b5e1..1720e00 100644
--- a/exportsyms.uk
+++ b/exportsyms.uk
@@ -9,7 +9,7 @@ listen
 lwip_ioctl
 lwip_htonl
 lwip_htons
-lwip_select
+poll
 recv
 recvfrom
 select
diff --git a/sockets.c b/sockets.c
index 7f4b6f3..294de3d 100644
--- a/sockets.c
+++ b/sockets.c
@@ -335,6 +335,143 @@ EXIT:
        return ret;
 }
 
+int poll(struct pollfd fds[], nfds_t nfds, int timeout)
+{
+       unsigned int i;
+       struct sock_net_file *file;
+       struct pollfd lwip_fds[nfds];
+
+       for (i = 0; i < nfds; i++) {
+               if (fds[i].fd < 0)
+                       lwip_fds[i].fd = fds[i].fd;
+               else {
+                       file = sock_net_file_get(fds[i].fd);
+                       if (PTRISERR(file)) {
+                               LWIP_DEBUGF(SOCKETS_DEBUG,
+                                           ("failed to identify socket 
descriptor\n"));
+                               /* Setting the errno */
+                               SOCK_NET_SET_ERRNO(PTR2ERR(file));
+                               return -1;
+                       }
+                       lwip_fds[i].fd = file->sock_fd;
+                       lwip_fds[i].events = fds[i].events;
+               }
+       }
+
+       lwip_poll(lwip_fds, nfds, timeout);
+
+       for (i = 0; i < nfds; i++) {
+               if (fds[i].fd < 0)
+                       fds[i].revents = 0;
+               else
+                       fds[i].revents = lwip_fds[i].revents;
+       }
+       return 0;
+}
+
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+               struct timeval *timeout)
+{
+       uint64_t nsecs;
+       fd_set rd, wr, xc;
+       int i, ret, maxfd;
+       struct sock_net_file *file;
+
+       if (nfds == 0 && timeout != NULL) {
+               nsecs = timeout->tv_sec * 1000000000;
+               nsecs += timeout->tv_usec * 1000;
+               uk_sched_thread_sleep(nsecs);
+               return 0;
+       }
+
+       /* translate the public (vfscore) fds into lwIP socket fds */
+       FD_ZERO(&rd);
+       FD_ZERO(&wr);
+       FD_ZERO(&xc);
+       maxfd = 0;
+       for (i = 0; i < nfds; i++) {
+               if (readfds && FD_ISSET(i, readfds)) {
+                       maxfd = i;
+                       file = sock_net_file_get(i);
+                       if (PTRISERR(file)) {
+                               LWIP_DEBUGF(SOCKETS_DEBUG,
+                                           ("failed to identify socket 
descriptor\n"));
+                               ret = -1;
+                               /* Setting the errno */
+                               SOCK_NET_SET_ERRNO(PTR2ERR(file));
+                               goto EXIT;
+                       }
+                       FD_SET(file->sock_fd, &rd);
+               }
+               if (writefds && FD_ISSET(i, writefds)) {
+                       maxfd = i;
+                       file = sock_net_file_get(i);
+                       if (PTRISERR(file)) {
+                               LWIP_DEBUGF(SOCKETS_DEBUG,
+                                           ("failed to identify socket 
descriptor\n"));
+                               ret = -1;
+                               /* Setting the errno */
+                               SOCK_NET_SET_ERRNO(PTR2ERR(file));
+                               goto EXIT;
+                       }
+                       FD_SET(file->sock_fd, &wr);
+               }
+               if (exceptfds && FD_ISSET(i, exceptfds)) {
+                       maxfd = i;
+                       file = sock_net_file_get(i);
+                       if (PTRISERR(file)) {
+                               LWIP_DEBUGF(SOCKETS_DEBUG,
+                                           ("failed to identify socket 
descriptor\n"));
+                               ret = -1;
+                               /* Setting the errno */
+                               SOCK_NET_SET_ERRNO(PTR2ERR(file));
+                               goto EXIT;
+                       }
+                       FD_SET(file->sock_fd, &xc);
+               }
+       }
+
+       ret = lwip_select(maxfd+1, &rd, &wr, &xc, timeout);
+       if (ret < 0)
+               return ret;
+
+       /* translate back from lwIP socket fds to public (vfscore) fds.
+        * But there's no way to go from lwIP to vfscore, so iterate over
+        * everything again. Check which ones were set originally, and if
+        * they aren't also set in lwip_select()'s return, clear them.
+        */
+       for (i = 0; i < nfds; i++) {
+               if (readfds && FD_ISSET(i, readfds)) {
+                       /* This lookup can't fail, or it would already have
+                        * failed during the translation above.
+                        */
+                       file = sock_net_file_get(i);
+                       if (!FD_ISSET(file->sock_fd, &rd))
+                               FD_CLR(i, readfds);
+               }
+               if (writefds && FD_ISSET(i, writefds)) {
+                       /* This lookup can't fail, or it would already have
+                        * failed during the translation above.
+                        */
+                       file = sock_net_file_get(i);
+                       if (!FD_ISSET(file->sock_fd, &wr))
+                               FD_CLR(i, writefds);
+               }
+               if (exceptfds && FD_ISSET(i, exceptfds)) {
+                       /* This lookup can't fail, or it would already have
+                        * failed during the translation above.
+                        */
+                       file = sock_net_file_get(i);
+                       if (!FD_ISSET(file->sock_fd, &xc))
+                               FD_CLR(i, exceptfds);
+               }
+       }
+       return 0;
+
+EXIT:
+       return ret;
+}
+
 int shutdown(int s, int how)
 {
        int ret = 0;
-- 
2.21.0


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.