Fixes for 'make UNATTENDED=yes CC=clang CXX=clang verify'
[vpp.git] / src / vcl / sock_test_client.c
index 40ba043..1ed4b89 100644 (file)
 #include <time.h>
 #include <arpa/inet.h>
 #include <vcl/sock_test.h>
+#ifndef VCL_TEST
+#include <sys/un.h>
+#endif
 
 typedef struct
 {
 #ifdef VCL_TEST
   vppcom_endpt_t server_endpt;
+#else
+  int af_unix_echo_tx;
+  int af_unix_echo_rx;
 #endif
-  struct sockaddr_in server_addr;
+  struct sockaddr_storage server_addr;
+  uint32_t server_addr_size;
   sock_test_socket_t ctrl_socket;
   sock_test_socket_t *test_socket;
   uint32_t num_test_sockets;
@@ -54,7 +61,8 @@ sock_test_cfg_sync (sock_test_socket_t * socket)
                              sizeof (ctrl->cfg), NULL, ctrl->cfg.verbose);
   if (tx_bytes < 0)
     {
-      fprintf (stderr, "ERROR: write test cfg failed (%d)!\n", tx_bytes);
+      fprintf (stderr, "CLIENT: ERROR: write test cfg failed (%d)!\n",
+              tx_bytes);
       return tx_bytes;
     }
 
@@ -65,7 +73,7 @@ sock_test_cfg_sync (sock_test_socket_t * socket)
 
   if (rl_cfg->magic != SOCK_TEST_CFG_CTRL_MAGIC)
     {
-      fprintf (stderr, "ERROR: Bad server reply cfg -- aborting!\n");
+      fprintf (stderr, "CLIENT: ERROR: Bad server reply cfg -- aborting!\n");
       return -1;
     }
   if (socket->cfg.verbose)
@@ -76,8 +84,8 @@ sock_test_cfg_sync (sock_test_socket_t * socket)
   if ((rx_bytes != sizeof (sock_test_cfg_t))
       || !sock_test_cfg_verify (rl_cfg, &ctrl->cfg))
     {
-      fprintf (stderr,
-              "ERROR: Invalid config received from server -- aborting!\n");
+      fprintf (stderr, "CLIENT: ERROR: Invalid config received "
+              "from server -- aborting!\n");
       sock_test_cfg_dump (rl_cfg, 1 /* is_client */ );
       return -1;
     }
@@ -141,7 +149,8 @@ echo_test_client ()
       if (rv < 0)
        {
          perror ("select()");
-         fprintf (stderr, "\nERROR: select() failed -- aborting test!\n");
+         fprintf (stderr, "\nCLIENT: ERROR: select() failed -- "
+                  "aborting test!\n");
          return;
        }
       else if (rv == 0)
@@ -163,8 +172,8 @@ echo_test_client ()
                                 &tsock->stats, ctrl->cfg.verbose);
              if (tx_bytes < 0)
                {
-                 fprintf (stderr, "\nERROR: sock_test_write(%d) failed "
-                          "-- aborting test!\n", tsock->fd);
+                 fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) "
+                          "failed -- aborting test!\n", tsock->fd);
                  return;
                }
 
@@ -184,9 +193,9 @@ echo_test_client ()
                          tsock->fd, rx_bytes, tsock->rxbuf);
 
                  if (tsock->stats.rx_bytes != tsock->stats.tx_bytes)
-                   printf
-                     ("WARNING: bytes read (%lu) != bytes written (%lu)!\n",
-                      tsock->stats.rx_bytes, tsock->stats.tx_bytes);
+                   printf ("CLIENT: WARNING: bytes read (%lu) "
+                           "!= bytes written (%lu)!\n",
+                           tsock->stats.rx_bytes, tsock->stats.tx_bytes);
                }
            }
 
@@ -199,6 +208,94 @@ echo_test_client ()
     }
   clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop);
 
+#ifndef VCL_TEST
+  {
+    int fd, errno_val;
+    struct sockaddr_un serveraddr;
+    uint8_t buffer[256];
+    size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1;
+    struct timeval timeout;
+
+    /* Open AF_UNIX socket and send an echo to test mixed epoll on server.
+     */
+    fd = socket (AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0)
+      {
+       errno_val = errno;
+       perror ("ERROR in echo_test_client(): socket(AF_UNIX) failed");
+       fprintf (stderr,
+                "CLIENT: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed "
+                "(errno = %d)!\n", errno_val);
+       goto out;
+      }
+    memset (&serveraddr, 0, sizeof (serveraddr));
+    serveraddr.sun_family = AF_UNIX;
+    strcpy (serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME);
+    rv = connect (fd, (struct sockaddr *) &serveraddr, SUN_LEN (&serveraddr));
+    if (rv < 0)
+      {
+       errno_val = errno;
+       perror ("ERROR in echo_test_client(): connect() failed");
+       fprintf (stderr, "CLIENT: ERROR: connect(fd %d, \"%s\", %lu) "
+                "failed (errno = %d)!\n", fd, SOCK_TEST_AF_UNIX_FILENAME,
+                SUN_LEN (&serveraddr), errno_val);
+       goto done;
+      }
+
+    scm->af_unix_echo_tx++;
+    strcpy ((char *) buffer, SOCK_TEST_MIXED_EPOLL_DATA);
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 250000;
+    select (0, NULL, NULL, NULL, &timeout);    /* delay .25 secs */
+    rv = write (fd, buffer, nbytes);
+    if (rv < 0)
+      {
+       errno_val = errno;
+       perror ("ERROR in echo_test_client(): write() failed");
+       fprintf (stderr, "CLIENT: ERROR: write(fd %d, \"%s\", %lu) "
+                "failed (errno = %d)!\n", fd, buffer, nbytes, errno_val);
+       goto done;
+      }
+    else if (rv < nbytes)
+      {
+       fprintf (stderr, "CLIENT: ERROR: write(fd %d, \"%s\", %lu) "
+                "returned %d!\n", fd, buffer, nbytes, rv);
+       goto done;
+      }
+
+    printf ("CLIENT (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
+    memset (buffer, 0, sizeof (buffer));
+    rv = read (fd, buffer, nbytes);
+    if (rv < 0)
+      {
+       errno_val = errno;
+       perror ("ERROR in echo_test_client(): read() failed");
+       fprintf (stderr, "CLIENT: ERROR: read(fd %d, %p, %lu) "
+                "failed (errno = %d)!\n", fd, buffer, nbytes, errno_val);
+       goto done;
+      }
+    else if (rv < nbytes)
+      {
+       fprintf (stderr, "CLIENT: ERROR: read(fd %d, %p, %lu) "
+                "returned %d!\n", fd, buffer, nbytes, rv);
+       goto done;
+      }
+
+    if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes))
+      {
+       printf ("CLIENT (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
+       scm->af_unix_echo_rx++;
+      }
+    else
+      printf ("CLIENT (AF_UNIX): ERROR: RX (%d bytes) - '%s'\n", rv, buffer);
+
+  done:
+    close (fd);
+  out:
+    ;
+  }
+#endif
+
   for (i = 0; i < ctrl->cfg.num_test_sockets; i++)
     {
       tsock = &scm->test_socket[i];
@@ -265,7 +362,7 @@ stream_test_client (sock_test_t test)
 
   if (sock_test_cfg_sync (ctrl))
     {
-      fprintf (stderr, "ERROR: test cfg sync failed -- aborting!");
+      fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!");
       return;
     }
 
@@ -312,7 +409,8 @@ stream_test_client (sock_test_t test)
       if (rv < 0)
        {
          perror ("select()");
-         fprintf (stderr, "\nERROR: select() failed -- aborting test!\n");
+         fprintf (stderr, "\nCLIENT: ERROR: select() failed -- "
+                  "aborting test!\n");
          return;
        }
       else if (rv == 0)
@@ -325,6 +423,15 @@ stream_test_client (sock_test_t test)
                (tsock->stats.stop.tv_nsec == 0)))
            continue;
 
+         if ((test == SOCK_TEST_TYPE_BI) &&
+             FD_ISSET (tsock->fd, rfdset) &&
+             (tsock->stats.rx_bytes < ctrl->cfg.total_bytes))
+           {
+             (void) sock_test_read (tsock->fd,
+                                    (uint8_t *) tsock->rxbuf,
+                                    tsock->rxbuf_size, &tsock->stats);
+           }
+
          if (FD_ISSET (tsock->fd, wfdset) &&
              (tsock->stats.tx_bytes < ctrl->cfg.total_bytes))
            {
@@ -334,21 +441,12 @@ stream_test_client (sock_test_t test)
                                 ctrl->cfg.verbose);
              if (tx_bytes < 0)
                {
-                 fprintf (stderr, "\nERROR: sock_test_write(%d) failed "
-                          "-- aborting test!\n", tsock->fd);
+                 fprintf (stderr, "\nCLIENT: ERROR: sock_test_write(%d) "
+                          "failed -- aborting test!\n", tsock->fd);
                  return;
                }
            }
 
-         if ((test == SOCK_TEST_TYPE_BI) &&
-             FD_ISSET (tsock->fd, rfdset) &&
-             (tsock->stats.rx_bytes < ctrl->cfg.total_bytes))
-           {
-             (void) sock_test_read (tsock->fd,
-                                    (uint8_t *) tsock->rxbuf,
-                                    tsock->rxbuf_size, &tsock->stats);
-           }
-
          if (((test == SOCK_TEST_TYPE_UNI) &&
               (tsock->stats.tx_bytes >= ctrl->cfg.total_bytes)) ||
              ((test == SOCK_TEST_TYPE_BI) &&
@@ -366,7 +464,7 @@ stream_test_client (sock_test_t test)
 
   if (sock_test_cfg_sync (ctrl))
     {
-      fprintf (stderr, "ERROR: test cfg sync failed -- aborting!");
+      fprintf (stderr, "CLIENT: ERROR: test cfg sync failed -- aborting!");
       return;
     }
 
@@ -409,7 +507,7 @@ stream_test_client (sock_test_t test)
 
   ctrl->cfg.test = SOCK_TEST_TYPE_ECHO;
   if (sock_test_cfg_sync (ctrl))
-    fprintf (stderr, "ERROR: post-test cfg sync failed!");
+    fprintf (stderr, "CLIENT: ERROR: post-test cfg sync failed!");
 
   printf ("CLIENT (fd %d): %s-directional Stream Test Complete!\n"
          SOCK_TEST_BANNER_STRING "\n", ctrl->fd,
@@ -424,6 +522,10 @@ exit_client (void)
   sock_test_socket_t *tsock;
   int i;
 
+#ifndef VCL_TEST
+  printf ("CLIENT: af_unix_echo_tx %d, af_unix_echo_rx %d\n",
+         scm->af_unix_echo_tx, scm->af_unix_echo_rx);
+#endif
   for (i = 0; i < ctrl->cfg.num_test_sockets; i++)
     {
       tsock = &scm->test_socket[i];
@@ -491,7 +593,8 @@ sock_test_connect_test_sockets (uint32_t num_test_sockets)
        {
          errno_val = errno;
          perror ("ERROR in sock_test_connect_test_sockets()");
-         fprintf (stderr, "ERROR: socket failed (errno = %d)!\n", errno_val);
+         fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n",
+                  errno_val);
          return -1;
        }
 
@@ -503,39 +606,48 @@ sock_test_connect_test_sockets (uint32_t num_test_sockets)
        {
          tsock = &scm->test_socket[i];
 #ifdef VCL_TEST
-         tsock->fd =
-           vppcom_session_create (VPPCOM_VRF_DEFAULT, VPPCOM_PROTO_TCP,
-                                  1 /* is_nonblocking */ );
+         tsock->fd = vppcom_session_create (ctrl->cfg.transport_udp ?
+                                            VPPCOM_PROTO_UDP :
+                                            VPPCOM_PROTO_TCP,
+                                            1 /* is_nonblocking */ );
          if (tsock->fd < 0)
            {
              errno = -tsock->fd;
              tsock->fd = -1;
            }
 #else
-         tsock->fd = socket (AF_INET, SOCK_STREAM, 0);
+         tsock->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET,
+                             ctrl->cfg.transport_udp ?
+                             SOCK_DGRAM : SOCK_STREAM, 0);
 #endif
          if (tsock->fd < 0)
            {
              errno_val = errno;
              perror ("ERROR in sock_test_connect_test_sockets()");
-             fprintf (stderr, "ERROR: socket failed (errno = %d)!\n",
+             fprintf (stderr, "CLIENT: ERROR: socket failed (errno = %d)!\n",
                       errno_val);
              return tsock->fd;
            }
 
 #ifdef VCL_TEST
          rv = vppcom_session_connect (tsock->fd, &scm->server_endpt);
+         if (rv)
+           {
+             errno = -rv;
+             rv = -1;
+           }
 #else
          rv =
            connect (tsock->fd, (struct sockaddr *) &scm->server_addr,
-                    sizeof (scm->server_addr));
+                    scm->server_addr_size);
 #endif
          if (rv < 0)
            {
              errno_val = errno;
-             perror ("ERROR in main()");
-             fprintf (stderr, "ERROR: connect failed (errno = %d)!\n",
-                      errno_val);
+             perror ("ERROR in sock_test_connect_test_sockets()");
+             fprintf (stderr, "CLIENT: ERROR: connect failed "
+                      "(errno = %d)!\n", errno_val);
+             return -1;
            }
          tsock->cfg = ctrl->cfg;
          sock_test_socket_buf_alloc (tsock);
@@ -556,7 +668,7 @@ dump_help (void)
 {
 #define INDENT "\n  "
 
-  printf ("Test configuration commands:"
+  printf ("CLIENT: Test configuration commands:"
          INDENT SOCK_TEST_TOKEN_HELP
          "\t\t\tDisplay help."
          INDENT SOCK_TEST_TOKEN_EXIT
@@ -594,8 +706,8 @@ cfg_txbuf_size_set (void)
       sock_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     }
   else
-    fprintf (stderr,
-            "ERROR: Invalid txbuf size (%lu) < minimum buf size (%u)!\n",
+    fprintf (stderr, "CLIENT: ERROR: Invalid txbuf size (%lu) < "
+            "minimum buf size (%u)!\n",
             txbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN);
 }
 
@@ -615,7 +727,7 @@ cfg_num_writes_set (void)
     }
   else
     {
-      fprintf (stderr, "ERROR: invalid num writes: %u\n", num_writes);
+      fprintf (stderr, "CLIENT: ERROR: invalid num writes: %u\n", num_writes);
     }
 }
 
@@ -632,11 +744,13 @@ cfg_num_test_sockets_set (void)
     {
       ctrl->cfg.num_test_sockets = num_test_sockets;
       sock_test_connect_test_sockets (num_test_sockets);
+
       sock_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     }
   else
     {
-      fprintf (stderr, "ERROR: invalid num test sockets: %u, (%d max)\n",
+      fprintf (stderr, "CLIENT: ERROR: invalid num test sockets: "
+              "%u, (%d max)\n",
               num_test_sockets, SOCK_TEST_CFG_MAX_TEST_SCKTS);
     }
 }
@@ -657,8 +771,8 @@ cfg_rxbuf_size_set (void)
       sock_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     }
   else
-    fprintf (stderr,
-            "ERROR: Invalid rxbuf size (%lu) < minimum buf size (%u)!\n",
+    fprintf (stderr, "CLIENT: ERROR: Invalid rxbuf size (%lu) < "
+            "minimum buf size (%u)!\n",
             rxbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN);
 }
 
@@ -680,16 +794,20 @@ parse_input ()
   sock_test_socket_t *ctrl = &scm->ctrl_socket;
   sock_test_t rv = SOCK_TEST_TYPE_NONE;
 
-  if (!strcmp (SOCK_TEST_TOKEN_EXIT, ctrl->txbuf))
+  if (!strncmp (SOCK_TEST_TOKEN_EXIT, ctrl->txbuf,
+               strlen (SOCK_TEST_TOKEN_EXIT)))
     rv = SOCK_TEST_TYPE_EXIT;
 
-  else if (!strcmp (SOCK_TEST_TOKEN_HELP, ctrl->txbuf))
+  else if (!strncmp (SOCK_TEST_TOKEN_HELP, ctrl->txbuf,
+                    strlen (SOCK_TEST_TOKEN_HELP)))
     dump_help ();
 
-  else if (!strcmp (SOCK_TEST_TOKEN_SHOW_CFG, ctrl->txbuf))
+  else if (!strncmp (SOCK_TEST_TOKEN_SHOW_CFG, ctrl->txbuf,
+                    strlen (SOCK_TEST_TOKEN_SHOW_CFG)))
     scm->dump_cfg = 1;
 
-  else if (!strcmp (SOCK_TEST_TOKEN_VERBOSE, ctrl->txbuf))
+  else if (!strncmp (SOCK_TEST_TOKEN_VERBOSE, ctrl->txbuf,
+                    strlen (SOCK_TEST_TOKEN_VERBOSE)))
     cfg_verbose_toggle ();
 
   else if (!strncmp (SOCK_TEST_TOKEN_TXBUF_SIZE, ctrl->txbuf,
@@ -729,6 +847,8 @@ print_usage_and_exit (void)
           "sock_test_client [OPTIONS] <ipaddr> <port>\n"
           "  OPTIONS\n"
           "  -h               Print this message and exit.\n"
+          "  -6               Use IPv6\n"
+          "  -u               Use UDP transport layer\n"
           "  -c               Print test config before test.\n"
           "  -w <dir>         Write test results to <dir>.\n"
           "  -X               Exit after running test.\n"
@@ -754,7 +874,7 @@ main (int argc, char **argv)
   sock_test_socket_buf_alloc (ctrl);
 
   opterr = 0;
-  while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV")) != -1)
+  while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6D")) != -1)
     switch (c)
       {
       case 'c':
@@ -765,14 +885,15 @@ main (int argc, char **argv)
        if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sockets) != 1)
          if (sscanf (optarg, "%u", &ctrl->cfg.num_test_sockets) != 1)
            {
-             fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c);
+             fprintf (stderr, "CLIENT: ERROR: Invalid value for "
+                      "option -%c!\n", c);
              print_usage_and_exit ();
            }
        if (!ctrl->cfg.num_test_sockets ||
            (ctrl->cfg.num_test_sockets > FD_SETSIZE))
          {
-           fprintf (stderr, "ERROR: Invalid number of sockets (%d)"
-                    "specified for option -%c!\n"
+           fprintf (stderr, "CLIENT: ERROR: Invalid number of "
+                    "sockets (%d) specified for option -%c!\n"
                     "       Valid range is 1 - %d\n",
                     ctrl->cfg.num_test_sockets, c, FD_SETSIZE);
            print_usage_and_exit ();
@@ -780,7 +901,7 @@ main (int argc, char **argv)
        break;
 
       case 'w':
-       fprintf (stderr, "Writing test results to files is TBD.\n");
+       fprintf (stderr, "CLIENT: Writing test results to files is TBD.\n");
        break;
 
       case 'X':
@@ -790,8 +911,8 @@ main (int argc, char **argv)
       case 'E':
        if (strlen (optarg) > ctrl->txbuf_size)
          {
-           fprintf (stderr,
-                    "ERROR: Option -%c value larger than txbuf size (%d)!\n",
+           fprintf (stderr, "CLIENT: ERROR: Option -%c value "
+                    "larger than txbuf size (%d)!\n",
                     optopt, ctrl->txbuf_size);
            print_usage_and_exit ();
          }
@@ -803,13 +924,15 @@ main (int argc, char **argv)
        if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sockets) != 1)
          if (sscanf (optarg, "%d", &ctrl->cfg.num_test_sockets) != 1)
            {
-             fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c);
+             fprintf (stderr, "CLIENT: ERROR: Invalid value for "
+                      "option -%c!\n", c);
              print_usage_and_exit ();
            }
        if (ctrl->cfg.num_test_sockets > SOCK_TEST_CFG_MAX_TEST_SCKTS)
          {
-           fprintf (stderr, "ERROR: value greater than max number test"
-                    " sockets (%d)!", SOCK_TEST_CFG_MAX_TEST_SCKTS);
+           fprintf (stderr, "CLIENT: ERROR: value greater than max "
+                    "number test sockets (%d)!",
+                    SOCK_TEST_CFG_MAX_TEST_SCKTS);
            print_usage_and_exit ();
          }
        break;
@@ -818,7 +941,8 @@ main (int argc, char **argv)
        if (sscanf (optarg, "0x%lx", &ctrl->cfg.num_writes) != 1)
          if (sscanf (optarg, "%ld", &ctrl->cfg.num_writes) != 1)
            {
-             fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c);
+             fprintf (stderr, "CLIENT: ERROR: Invalid value for "
+                      "option -%c!\n", c);
              print_usage_and_exit ();
            }
        ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
@@ -828,7 +952,8 @@ main (int argc, char **argv)
        if (sscanf (optarg, "0x%lx", &ctrl->cfg.rxbuf_size) != 1)
          if (sscanf (optarg, "%ld", &ctrl->cfg.rxbuf_size) != 1)
            {
-             fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c);
+             fprintf (stderr, "CLIENT: ERROR: Invalid value for "
+                      "option -%c!\n", c);
              print_usage_and_exit ();
            }
        if (ctrl->cfg.rxbuf_size >= SOCK_TEST_CFG_BUF_SIZE_MIN)
@@ -840,8 +965,8 @@ main (int argc, char **argv)
          }
        else
          {
-           fprintf (stderr,
-                    "ERROR: rxbuf size (%lu) less than minumum (%u)\n",
+           fprintf (stderr, "CLIENT: ERROR: rxbuf size (%lu) "
+                    "less than minumum (%u)\n",
                     ctrl->cfg.rxbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN);
            print_usage_and_exit ();
          }
@@ -852,7 +977,8 @@ main (int argc, char **argv)
        if (sscanf (optarg, "0x%lx", &ctrl->cfg.txbuf_size) != 1)
          if (sscanf (optarg, "%ld", &ctrl->cfg.txbuf_size) != 1)
            {
-             fprintf (stderr, "ERROR: Invalid value for option -%c!\n", c);
+             fprintf (stderr, "CLIENT: ERROR: Invalid value "
+                      "for option -%c!\n", c);
              print_usage_and_exit ();
            }
        if (ctrl->cfg.txbuf_size >= SOCK_TEST_CFG_BUF_SIZE_MIN)
@@ -866,8 +992,8 @@ main (int argc, char **argv)
          }
        else
          {
-           fprintf (stderr,
-                    "ERROR: txbuf size (%lu) less than minumum (%u)!\n",
+           fprintf (stderr, "CLIENT: ERROR: txbuf size (%lu) "
+                    "less than minumum (%u)!\n",
                     ctrl->cfg.txbuf_size, SOCK_TEST_CFG_BUF_SIZE_MIN);
            print_usage_and_exit ();
          }
@@ -885,6 +1011,14 @@ main (int argc, char **argv)
        ctrl->cfg.verbose = 1;
        break;
 
+      case '6':
+       ctrl->cfg.address_ip6 = 1;
+       break;
+
+      case 'D':
+       ctrl->cfg.transport_udp = 1;
+       break;
+
       case '?':
        switch (optopt)
          {
@@ -894,16 +1028,17 @@ main (int argc, char **argv)
          case 'R':
          case 'T':
          case 'w':
-           fprintf (stderr, "ERROR: Option -%c requires an argument.\n",
-                    optopt);
+           fprintf (stderr, "CLIENT: ERROR: Option -%c "
+                    "requires an argument.\n", optopt);
            break;
 
          default:
            if (isprint (optopt))
-             fprintf (stderr, "ERROR: Unknown option `-%c'.\n", optopt);
+             fprintf (stderr, "CLIENT: ERROR: Unknown "
+                      "option `-%c'.\n", optopt);
            else
-             fprintf (stderr, "ERROR: Unknown option character `\\x%x'.\n",
-                      optopt);
+             fprintf (stderr, "CLIENT: ERROR: Unknown "
+                      "option character `\\x%x'.\n", optopt);
          }
        /* fall thru */
       case 'h':
@@ -913,7 +1048,7 @@ main (int argc, char **argv)
 
   if (argc < (optind + 2))
     {
-      fprintf (stderr, "ERROR: Insufficient number of arguments!\n");
+      fprintf (stderr, "CLIENT: ERROR: Insufficient number of arguments!\n");
       print_usage_and_exit ();
     }
 
@@ -926,7 +1061,9 @@ main (int argc, char **argv)
     }
   else
     {
-      ctrl->fd = vppcom_session_create (VPPCOM_VRF_DEFAULT, VPPCOM_PROTO_TCP,
+      ctrl->fd = vppcom_session_create (ctrl->cfg.transport_udp ?
+                                       VPPCOM_PROTO_UDP :
+                                       VPPCOM_PROTO_TCP,
                                        0 /* is_nonblocking */ );
       if (ctrl->fd < 0)
        {
@@ -935,28 +1072,56 @@ main (int argc, char **argv)
        }
     }
 #else
-  ctrl->fd = socket (AF_INET, SOCK_STREAM, 0);
+  ctrl->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET,
+                    ctrl->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM, 0);
 #endif
 
   if (ctrl->fd < 0)
     {
       errno_val = errno;
       perror ("ERROR in main()");
-      fprintf (stderr, "ERROR: socket failed (errno = %d)!\n", errno_val);
+      fprintf (stderr, "CLIENT: ERROR: socket "
+              "failed (errno = %d)!\n", errno_val);
       return ctrl->fd;
     }
 
   memset (&scm->server_addr, 0, sizeof (scm->server_addr));
-
-  scm->server_addr.sin_family = AF_INET;
-  inet_pton (AF_INET, argv[optind++], &(scm->server_addr.sin_addr));
-  scm->server_addr.sin_port = htons (atoi (argv[optind]));
+  if (ctrl->cfg.address_ip6)
+    {
+      struct sockaddr_in6 *server_addr =
+       (struct sockaddr_in6 *) &scm->server_addr;
+      scm->server_addr_size = sizeof (*server_addr);
+      server_addr->sin6_family = AF_INET6;
+      inet_pton (AF_INET6, argv[optind++], &(server_addr->sin6_addr));
+      server_addr->sin6_port = htons (atoi (argv[optind]));
+    }
+  else
+    {
+      struct sockaddr_in *server_addr =
+       (struct sockaddr_in *) &scm->server_addr;
+      scm->server_addr_size = sizeof (*server_addr);
+      server_addr->sin_family = AF_INET;
+      inet_pton (AF_INET, argv[optind++], &(server_addr->sin_addr));
+      server_addr->sin_port = htons (atoi (argv[optind]));
+    }
 
 #ifdef VCL_TEST
-  scm->server_endpt.vrf = VPPCOM_VRF_DEFAULT;
-  scm->server_endpt.is_ip4 = (scm->server_addr.sin_family == AF_INET);
-  scm->server_endpt.ip = (uint8_t *) & scm->server_addr.sin_addr;
-  scm->server_endpt.port = (uint16_t) scm->server_addr.sin_port;
+  if (ctrl->cfg.address_ip6)
+    {
+      struct sockaddr_in6 *server_addr =
+       (struct sockaddr_in6 *) &scm->server_addr;
+      scm->server_endpt.is_ip4 = 0;
+      scm->server_endpt.ip = (uint8_t *) & server_addr->sin6_addr;
+      scm->server_endpt.port = (uint16_t) server_addr->sin6_port;
+    }
+  else
+    {
+      struct sockaddr_in *server_addr =
+       (struct sockaddr_in *) &scm->server_addr;
+      scm->server_endpt.is_ip4 = 1;
+      scm->server_endpt.ip = (uint8_t *) & server_addr->sin_addr;
+      scm->server_endpt.port = (uint16_t) server_addr->sin_port;
+    }
 #endif
 
   do
@@ -965,17 +1130,23 @@ main (int argc, char **argv)
 
 #ifdef VCL_TEST
       rv = vppcom_session_connect (ctrl->fd, &scm->server_endpt);
+      if (rv)
+       {
+         errno = -rv;
+         rv = -1;
+       }
 #else
       rv =
        connect (ctrl->fd, (struct sockaddr *) &scm->server_addr,
-                sizeof (scm->server_addr));
+                scm->server_addr_size);
 #endif
       if (rv < 0)
        {
          errno_val = errno;
          perror ("ERROR in main()");
-         fprintf (stderr, "ERROR: connect failed (errno = %d)!\n",
+         fprintf (stderr, "CLIENT: ERROR: connect failed (errno = %d)!\n",
                   errno_val);
+         return -1;
        }
 
       sock_test_cfg_sync (ctrl);
@@ -1040,7 +1211,7 @@ main (int argc, char **argv)
       memset (ctrl->txbuf, 0, ctrl->txbuf_size);
       memset (ctrl->rxbuf, 0, ctrl->rxbuf_size);
 
-      printf ("\nType some characters and hit <return>\n"
+      printf ("\nCLIENT: Type some characters and hit <return>\n"
              "('" SOCK_TEST_TOKEN_HELP "' for help): ");
 
       if (fgets (ctrl->txbuf, ctrl->txbuf_size, stdin) != NULL)
@@ -1061,10 +1232,11 @@ main (int argc, char **argv)
 #ifdef VCL_TEST
   vppcom_session_close (ctrl->fd);
   vppcom_app_destroy ();
+  return 0;
 #else
   close (ctrl->fd);
+  return (scm->af_unix_echo_tx == scm->af_unix_echo_rx) ? 0 : -1;
 #endif
-  return 0;
 }
 
 /*