Update L2 header offset after VLAN tag rewrite
[vpp.git] / src / uri / sock_test_server.c
index 52c60dc..79e762d 100644 (file)
 #include <time.h>
 #include <ctype.h>
 #include <uri/sock_test.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define SOCK_SERVER_USE_EPOLL 1
+#define VPPCOM_SESSION_ATTR_UNIT_TEST 0
+
+#if SOCK_SERVER_USE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#ifdef VCL_TEST
+#if VPPCOM_SESSION_ATTR_UNIT_TEST
+#define BUFLEN  sizeof (uint64_t) * 16
+uint64_t buffer[16];
+uint32_t buflen = BUFLEN;
+uint32_t *flags = (uint32_t *) buffer;
+#endif
+#endif
 
 typedef struct
 {
@@ -38,9 +56,15 @@ typedef struct
 } sock_server_conn_t;
 
 #define SOCK_SERVER_MAX_TEST_CONN  10
+#define SOCK_SERVER_MAX_EPOLL_EVENTS 10
 typedef struct
 {
   int listen_fd;
+#if SOCK_SERVER_USE_EPOLL
+  int epfd;
+  struct epoll_event listen_ev;
+  struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS];
+#endif
   size_t num_conn;
   size_t conn_pool_size;
   sock_server_conn_t *conn_pool;
@@ -52,6 +76,7 @@ typedef struct
 
 sock_server_main_t sock_server_main;
 
+#if ! SOCK_SERVER_USE_EPOLL
 static inline int
 get_nfds (void)
 {
@@ -83,6 +108,7 @@ conn_fdset_clr (sock_server_conn_t * conn, fd_set * fdset)
   FD_CLR (conn->fd, fdset);
   ssm->nfds = get_nfds ();
 }
+#endif
 
 static inline void
 conn_pool_expand (size_t expand_size)
@@ -141,10 +167,12 @@ conn_pool_alloc (void)
 static inline void
 conn_pool_free (sock_server_conn_t * conn)
 {
+#if ! SOCK_SERVER_USE_EPOLL
   sock_server_main_t *ssm = &sock_server_main;
 
   conn_fdset_clr (conn, &ssm->rd_fdset);
   conn_fdset_clr (conn, &ssm->wr_fdset);
+#endif
   conn->fd = 0;
   conn->is_alloc = 0;
 }
@@ -274,6 +302,8 @@ new_client (void)
 #ifdef VCL_TEST
   client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt,
                                     -1.0 /* wait forever */ );
+  if (client_fd < 0)
+    errno = -client_fd;
 #else
   client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL);
 #endif
@@ -281,7 +311,7 @@ new_client (void)
     {
       int errno_val;
       errno_val = errno;
-      perror ("ERROR in main()");
+      perror ("ERROR in new_client()");
       fprintf (stderr, "ERROR: accept failed (errno = %d)!\n", errno_val);
     }
 
@@ -289,7 +319,36 @@ new_client (void)
          client_fd, client_fd);
 
   conn->fd = client_fd;
+
+#if ! SOCK_SERVER_USE_EPOLL
   conn_fdset_set (conn, &ssm->rd_fdset);
+  ssm->nfds++;
+#else
+  {
+    struct epoll_event ev;
+    int rv;
+
+    ev.events = EPOLLIN;
+    ev.data.u64 = conn - ssm->conn_pool;
+#ifdef VCL_TEST
+    rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
+    if (rv)
+      errno = -rv;
+#else
+    rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
+#endif
+    if (rv < 0)
+      {
+       int errno_val;
+       errno_val = errno;
+       perror ("ERROR in new_client()");
+       fprintf (stderr, "ERROR: epoll_ctl failed (errno = %d)!\n",
+                errno_val);
+      }
+    else
+      ssm->nfds++;
+  }
+#endif
 }
 
 int
@@ -306,11 +365,15 @@ main (int argc, char **argv)
   int errno_val;
   int v, i;
   uint16_t port = SOCK_TEST_SERVER_PORT;
+#if ! SOCK_SERVER_USE_EPOLL
   fd_set _rfdset, *rfdset = &_rfdset;
+#endif
 #ifdef VCL_TEST
   vppcom_endpt_t endpt;
 #else
+#if ! SOCK_SERVER_USE_EPOLL
   fd_set _wfdset, *wfdset = &_wfdset;
+#endif
 #endif
 
   if ((argc == 2) && (sscanf (argv[1], "%d", &v) == 1))
@@ -345,7 +408,7 @@ main (int argc, char **argv)
   memset (&servaddr, 0, sizeof (servaddr));
 
   servaddr.sin_family = AF_INET;
-  servaddr.sin_addr.s_addr = htons (INADDR_ANY);
+  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
   servaddr.sin_port = htons (port);
 
 #ifdef VCL_TEST
@@ -360,6 +423,40 @@ main (int argc, char **argv)
       errno = -rv;
       rv = -1;
     }
+
+#if VPPCOM_SESSION_ATTR_UNIT_TEST
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nGET_FLAGS0: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+  buflen = BUFLEN;
+  *flags = O_RDWR | O_NONBLOCK;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_SET_FLAGS,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nSET_FLAGS1: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nGET_FLAGS1:Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+  *flags = O_RDWR;
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_SET_FLAGS,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nSET_FLAGS2: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_FLAGS,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nGET_FLAGS2:Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_PEER_ADDR,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nGET_PEER_ADDR: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+  buflen = BUFLEN;
+  if (vppcom_session_attr (ssm->listen_fd, VPPCOM_ATTR_GET_LCL_ADDR,
+                          buffer, &buflen) != VPPCOM_OK)
+    printf ("\nGET_LCL_ADDR: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+#endif
 #else
   rv =
     bind (ssm->listen_fd, (struct sockaddr *) &servaddr, sizeof (servaddr));
@@ -390,16 +487,55 @@ main (int argc, char **argv)
       return rv;
     }
 
+  printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port);
+
+#if ! SOCK_SERVER_USE_EPOLL
+
   FD_ZERO (&ssm->wr_fdset);
   FD_ZERO (&ssm->rd_fdset);
 
   FD_SET (ssm->listen_fd, &ssm->rd_fdset);
   ssm->nfds = ssm->listen_fd + 1;
 
-  printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port);
+#else
+#ifdef VCL_TEST
+  ssm->epfd = vppcom_epoll_create ();
+  if (ssm->epfd < 0)
+    errno = -ssm->epfd;
+#else
+  ssm->epfd = epoll_create (1);
+#endif
+  if (ssm->epfd < 0)
+    {
+      errno_val = errno;
+      perror ("ERROR in main()");
+      fprintf (stderr, "ERROR: epoll_create failed (errno = %d)!\n",
+              errno_val);
+      return ssm->epfd;
+    }
+
+  ssm->listen_ev.events = EPOLLIN;
+  ssm->listen_ev.data.u32 = ~0;
+#ifdef VCL_TEST
+  rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd,
+                        &ssm->listen_ev);
+  if (rv < 0)
+    errno = -rv;
+#else
+  rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, &ssm->listen_ev);
+#endif
+  if (rv < 0)
+    {
+      errno_val = errno;
+      perror ("ERROR in main()");
+      fprintf (stderr, "ERROR: epoll_ctl failed (errno = %d)!\n", errno_val);
+      return rv;
+    }
+#endif
 
   while (1)
     {
+#if ! SOCK_SERVER_USE_EPOLL
       _rfdset = ssm->rd_fdset;
 
 #ifdef VCL_TEST
@@ -431,10 +567,64 @@ main (int argc, char **argv)
            continue;
 
          conn = &ssm->conn_pool[i];
+#else
+      int num_ev;
+#ifdef VCL_TEST
+      num_ev = vppcom_epoll_wait (ssm->epfd, ssm->wait_events,
+                                 SOCK_SERVER_MAX_EPOLL_EVENTS, 60.0);
+      if (num_ev < 0)
+       errno = -num_ev;
+#else
+      num_ev = epoll_wait (ssm->epfd, ssm->wait_events,
+                          SOCK_SERVER_MAX_EPOLL_EVENTS, 60000);
+#endif
+      if (num_ev < 0)
+       {
+         perror ("epoll_wait()");
+         fprintf (stderr, "\nERROR: epoll_wait() failed -- aborting!\n");
+         main_rv = -1;
+         goto done;
+       }
+      if (num_ev == 0)
+       {
+         fprintf (stderr, "\nepoll_wait() timeout!\n");
+         continue;
+       }
+      for (i = 0; i < num_ev; i++)
+       {
+         if (ssm->wait_events[i].data.u32 == ~0)
+           {
+             new_client ();
+             continue;
+           }
+         conn = &ssm->conn_pool[ssm->wait_events[i].data.u32];
+#endif
          client_fd = conn->fd;
 
+#if ! SOCK_SERVER_USE_EPOLL
          if (FD_ISSET (client_fd, rfdset))
+#else
+         if (EPOLLIN & ssm->wait_events[i].events)
+#endif
            {
+#ifdef VCL_TEST
+#if VPPCOM_SESSION_ATTR_UNIT_TEST
+             buflen = BUFLEN;
+             if (vppcom_session_attr (client_fd, VPPCOM_ATTR_GET_NREAD,
+                                      buffer, &buflen) < VPPCOM_OK)
+               printf ("\nNREAD: Oh no, Mr. Biiiiiiiiiiiilllllll ! ! ! !\n");
+             if (vppcom_session_attr (client_fd,
+                                      VPPCOM_ATTR_GET_PEER_ADDR,
+                                      buffer, &buflen) != VPPCOM_OK)
+               printf ("\nGET_PEER_ADDR: Oh no, Mr. "
+                       "Biiiiiiiiiiiilllllll ! ! ! !\n");
+             buflen = BUFLEN;
+             if (vppcom_session_attr (client_fd, VPPCOM_ATTR_GET_LCL_ADDR,
+                                      buffer, &buflen) != VPPCOM_OK)
+               printf ("\nGET_LCL_ADDR: Oh no, Mr. "
+                       "Biiiiiiiiiiiilllllll ! ! ! !\n");
+#endif
+#endif
              rx_bytes = sock_test_read (client_fd, conn->buf,
                                         conn->buf_size, &conn->stats);
              if (rx_bytes > 0)
@@ -489,8 +679,12 @@ main (int argc, char **argv)
                          close (client_fd);
 #endif
                          conn_pool_free (conn);
-
+#if ! SOCK_SERVER_USE_EPOLL
                          if (ssm->nfds == (ssm->listen_fd + 1))
+#else
+                         ssm->nfds--;
+                         if (!ssm->nfds)
+#endif
                            {
                              printf ("SERVER: All client connections "
                                      "closed.\n\nSERVER: "
@@ -514,9 +708,15 @@ main (int argc, char **argv)
                      continue;
                    }
 
-                 else if (strlen ((char *) conn->buf))
-                   printf ("\nSERVER (fd %d): RX (%d bytes) - '%s'\n",
-                           conn->fd, rx_bytes, conn->buf);
+                 else if (isascii (conn->buf[0]))
+                   {
+                     // If it looks vaguely like a string, make sure it's terminated
+                     ((char *) conn->buf)[rx_bytes <
+                                          conn->buf_size ? rx_bytes :
+                                          conn->buf_size - 1] = 0;
+                     printf ("SERVER (fd %d): RX (%d bytes) - '%s'\n",
+                             conn->fd, rx_bytes, conn->buf);
+                   }
                }
              else              // rx_bytes < 0
                {
@@ -530,8 +730,12 @@ main (int argc, char **argv)
                    continue;
                }
 
-             if (isascii (conn->buf[0]) && strlen ((const char *) conn->buf))
+             if (isascii (conn->buf[0]))
                {
+                 // If it looks vaguely like a string, make sure it's terminated
+                 ((char *) conn->buf)[rx_bytes <
+                                      conn->buf_size ? rx_bytes :
+                                      conn->buf_size - 1] = 0;
                  if (xtra)
                    fprintf (stderr,
                             "ERROR: FIFO not drained in previous test!\n"