]> xenbits.xensource.com Git - unikraft/libs/lwip.git/commitdiff
Provide poll() and select() wrappers around lwip versions
authorFlorian Schmidt <florian.schmidt@neclab.eu>
Mon, 20 May 2019 11:29:51 +0000 (13:29 +0200)
committerFelipe Huici <felipe.huici@neclab.eu>
Wed, 29 May 2019 12:38:13 +0000 (14:38 +0200)
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@neclab.eu>
Reviewed-by: Felipe Huici <felipe.huici@neclab.eu>
exportsyms.uk
patches/0002-Don-t-provide-file-status-flags-when-we-have-a-libc.patch
sockets.c

index b17b5e184280cc0c5ae016e6a922a2ac3b38b85b..1720e0098e2e44c78283de6d0b1bf29a97283e73 100644 (file)
@@ -9,7 +9,7 @@ listen
 lwip_ioctl
 lwip_htonl
 lwip_htons
-lwip_select
+poll
 recv
 recvfrom
 select
index eb0da0f1593f5afea855fbd8620c224265b83b71..34a42381fd4a361ca96c62b326b65fd0109a247a 100644 (file)
@@ -17,30 +17,30 @@ index d70d36c4..72169cd0 100644
 --- a/src/include/lwip/sockets.h
 +++ b/src/include/lwip/sockets.h
 @@ -39,6 +39,8 @@
- #ifndef LWIP_HDR_SOCKETS_H
- #define LWIP_HDR_SOCKETS_H
-+#include <uk/config.h>
-+
- #include "lwip/opt.h"
- #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
-@@ -438,6 +440,7 @@ typedef struct ipv6_mreq {
- #define F_SETFL 4
- #endif
-+#ifndef CONFIG_HAVE_LIBC
- /* File status flags and file access modes for fnctl,
-    these are bits in an int. */
- #ifndef O_NONBLOCK
-@@ -455,6 +458,7 @@ typedef struct ipv6_mreq {
- #ifndef O_RDWR
- #define O_RDWR      (O_RDONLY|O_WRONLY)
- #endif
-+#endif /* CONFIG_HAVE_LIBC */
- #ifndef SHUT_RD
-   #define SHUT_RD   0
+ #ifndef LWIP_HDR_SOCKETS_H\r
+ #define LWIP_HDR_SOCKETS_H\r
\r
++#include <uk/config.h>\r
++\r
+ #include "lwip/opt.h"\r
\r
+ #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */\r
+@@ -438,6 +440,7 @@ typedef struct ipv6_mreq {\r
+ #define F_SETFL 4\r
+ #endif\r
\r
++#ifndef CONFIG_HAVE_LIBC\r
+ /* File status flags and file access modes for fnctl,\r
+    these are bits in an int. */\r
+ #ifndef O_NONBLOCK\r
+@@ -455,6 +458,7 @@ typedef struct ipv6_mreq {\r
+ #ifndef O_RDWR\r
+ #define O_RDWR      (O_RDONLY|O_WRONLY)\r
+ #endif\r
++#endif /* CONFIG_HAVE_LIBC */\r
\r
+ #ifndef SHUT_RD\r
+   #define SHUT_RD   0\r
 -- 
 2.21.0
 
index b2a65bb45c7b40e88f15c2d340a965bf8a17a15b..9ad5cfb41584a6a3f11c4eff11edc80d25e2cd78 100644 (file)
--- a/sockets.c
+++ b/sockets.c
@@ -333,6 +333,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;