messaging tests from Mainz
authortridge <>
Sat, 12 Aug 2006 20:50:46 +0000 (20:50 +0000)
committertridge <>
Sat, 12 Aug 2006 20:50:46 +0000 (20:50 +0000)
messaging/tcp.c [new file with mode: 0644]
messaging/tcp2.c [new file with mode: 0644]
messaging/udp.c [new file with mode: 0644]
messaging/udp2.c [new file with mode: 0644]
messaging/unix_dgram.c [new file with mode: 0644]
messaging/unix_stream.c [new file with mode: 0644]

diff --git a/messaging/tcp.c b/messaging/tcp.c
new file mode 100644 (file)
index 0000000..4425380
--- /dev/null
@@ -0,0 +1,334 @@
+/* 
+   measure latency of tcp sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+
+typedef int BOOL;
+
+#define True 1
+#define False 0
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+  char *name;
+  int level;
+  int option;
+  int value;
+  int opttype;
+} socket_options[] = {
+  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
+  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
+  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
+#ifdef TCP_NODELAY
+  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
+#endif
+  {NULL,0,0,0,0}};
+
+
+/****************************************************************************
+  Get the next token from a string, return False if none found
+  handles double-quotes. 
+Based on a routine by GJC@VILLAGE.COM. 
+Extensively modified by Andrew.Tridgell@anu.edu.au
+****************************************************************************/
+BOOL next_token(char **ptr,char *buff,char *sep)
+{
+  char *s;
+  BOOL quoted;
+  static char *last_ptr=NULL;
+
+  if (!ptr) ptr = &last_ptr;
+  if (!ptr) return(False);
+
+  s = *ptr;
+
+  /* default to simple separators */
+  if (!sep) sep = " \t\n\r";
+
+  /* find the first non sep char */
+  while(*s && strchr(sep,*s)) s++;
+
+  /* nothing left? */
+  if (! *s) return(False);
+
+  /* copy over the token */
+  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+    {
+      if (*s == '\"') 
+       quoted = !quoted;
+      else
+       *buff++ = *s;
+    }
+
+  *ptr = (*s) ? s+1 : s;  
+  *buff = 0;
+  last_ptr = *ptr;
+
+  return(True);
+}
+       
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+       char tok[200];
+
+       while (next_token(&options,tok," \t,"))
+    {
+      int ret=0,i;
+      int value = 1;
+      char *p;
+      BOOL got_value = False;
+
+      if ((p = strchr(tok,'=')))
+       {
+         *p = 0;
+         value = atoi(p+1);
+         got_value = True;
+       }
+
+      for (i=0;socket_options[i].name;i++)
+       if (strcasecmp(socket_options[i].name,tok)==0)
+         break;
+
+      if (!socket_options[i].name)
+       {
+         printf("Unknown socket option %s\n",tok);
+         continue;
+       }
+
+      switch (socket_options[i].opttype)
+       {
+       case OPT_BOOL:
+       case OPT_INT:
+         ret = setsockopt(fd,socket_options[i].level,
+                          socket_options[i].option,(char *)&value,sizeof(int));
+         break;
+
+       case OPT_ON:
+               if (got_value)
+                       printf("syntax error - %s does not take a value\n",tok);
+
+         {
+           int on = socket_options[i].value;
+           ret = setsockopt(fd,socket_options[i].level,
+                            socket_options[i].option,(char *)&on,sizeof(int));
+         }
+         break;          
+       }
+      
+      if (ret != 0)
+       printf("Failed to set socket option %s\n",tok);
+    }
+}
+
+/*
+  connect to a tcp socket
+*/
+int tcp_socket_connect(int port)
+{
+       int type = SOCK_STREAM;
+       struct sockaddr_in sock_out;
+       int res;
+       struct hostent *hp;
+       const char *host = "localhost";
+
+       res = socket(PF_INET, type, 0);
+       if (res == -1) {
+               return -1;
+       }
+
+       hp = gethostbyname(host);
+       if (!hp) {
+               fprintf(stderr,"unknown host: %s\n", host);
+               close(res);
+               return -1;
+       }
+
+       memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+       sock_out.sin_port = htons(port);
+       sock_out.sin_family = PF_INET;
+
+       if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+               fprintf(stderr,"failed to connect to %s - %s\n", host, strerror(errno));
+               close(res);
+               return -1;
+       }
+
+       return res;
+}
+
+
+/*
+  create a tcp socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int tcp_socket_bind(int port)
+{
+       struct hostent *hp;
+       struct sockaddr_in sock;
+       char host_name[1000];
+       int res;
+       int one=1;
+
+       /* get my host name */
+       if (gethostname(host_name, sizeof(host_name)) == -1) { 
+               fprintf(stderr,"gethostname failed\n"); 
+               return -1; 
+       } 
+
+       /* get host info */
+       if ((hp = gethostbyname(host_name)) == 0) {
+               fprintf(stderr,"gethostbyname: Unknown host %s\n",host_name);
+               return -1;
+       }
+  
+       memset((char *)&sock,0,sizeof(sock));
+       memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+       sock.sin_port = htons(port);
+       sock.sin_family = hp->h_addrtype;
+       sock.sin_addr.s_addr = INADDR_ANY;
+       res = socket(hp->h_addrtype, SOCK_STREAM, 0);
+       if (res == -1) { 
+               fprintf(stderr,"socket failed\n"); 
+               return -1; 
+       }
+
+       setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+       /* now we've got a socket - we need to bind it */
+       if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
+               fprintf(stderr,"bind failed on port %d\n", port);
+               close(res); 
+               return -1;
+       }
+
+       listen(res, 1);
+
+       return res;
+}
+
+/*
+  accept on a tcp socket
+*/
+static int tcp_socket_accept(int fd)
+{
+       struct sockaddr a;
+       socklen_t len;
+       return accept(fd, &a, &len);
+}
+
+static void worker(int port1, int port2, int w)
+{
+       int l = tcp_socket_bind(port1);
+       int s2, s1;
+       int count=0;
+
+       set_socket_options(l, "SO_REUSEADDR");
+
+       sleep(2);
+
+       s2 = tcp_socket_connect(port2);
+       s1 = tcp_socket_accept(l);
+
+       set_socket_options(s1, "TCP_NODELAY");
+       set_socket_options(s2, "TCP_NODELAY");
+
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\r", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       if (fork() == 0) {
+               worker(1313, 1314, 0);
+       } else {
+               worker(1314, 1313, 1);
+       }
+       return 0;
+}
diff --git a/messaging/tcp2.c b/messaging/tcp2.c
new file mode 100644 (file)
index 0000000..67398fb
--- /dev/null
@@ -0,0 +1,329 @@
+/* 
+   measure latency of tcp sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+
+typedef int BOOL;
+
+#define True 1
+#define False 0
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+  char *name;
+  int level;
+  int option;
+  int value;
+  int opttype;
+} socket_options[] = {
+  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
+  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
+  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
+#ifdef TCP_NODELAY
+  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
+#endif
+  {NULL,0,0,0,0}};
+
+
+/****************************************************************************
+  Get the next token from a string, return False if none found
+  handles double-quotes. 
+Based on a routine by GJC@VILLAGE.COM. 
+Extensively modified by Andrew.Tridgell@anu.edu.au
+****************************************************************************/
+BOOL next_token(char **ptr,char *buff,char *sep)
+{
+  char *s;
+  BOOL quoted;
+  static char *last_ptr=NULL;
+
+  if (!ptr) ptr = &last_ptr;
+  if (!ptr) return(False);
+
+  s = *ptr;
+
+  /* default to simple separators */
+  if (!sep) sep = " \t\n\r";
+
+  /* find the first non sep char */
+  while(*s && strchr(sep,*s)) s++;
+
+  /* nothing left? */
+  if (! *s) return(False);
+
+  /* copy over the token */
+  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+    {
+      if (*s == '\"') 
+       quoted = !quoted;
+      else
+       *buff++ = *s;
+    }
+
+  *ptr = (*s) ? s+1 : s;  
+  *buff = 0;
+  last_ptr = *ptr;
+
+  return(True);
+}
+       
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+       char tok[200];
+
+       while (next_token(&options,tok," \t,"))
+    {
+      int ret=0,i;
+      int value = 1;
+      char *p;
+      BOOL got_value = False;
+
+      if ((p = strchr(tok,'=')))
+       {
+         *p = 0;
+         value = atoi(p+1);
+         got_value = True;
+       }
+
+      for (i=0;socket_options[i].name;i++)
+       if (strcasecmp(socket_options[i].name,tok)==0)
+         break;
+
+      if (!socket_options[i].name)
+       {
+         printf("Unknown socket option %s\n",tok);
+         continue;
+       }
+
+      switch (socket_options[i].opttype)
+       {
+       case OPT_BOOL:
+       case OPT_INT:
+         ret = setsockopt(fd,socket_options[i].level,
+                          socket_options[i].option,(char *)&value,sizeof(int));
+         break;
+
+       case OPT_ON:
+               if (got_value)
+                       printf("syntax error - %s does not take a value\n",tok);
+
+         {
+           int on = socket_options[i].value;
+           ret = setsockopt(fd,socket_options[i].level,
+                            socket_options[i].option,(char *)&on,sizeof(int));
+         }
+         break;          
+       }
+      
+      if (ret != 0)
+       printf("Failed to set socket option %s\n",tok);
+    }
+}
+
+/*
+  connect to a tcp socket
+*/
+int tcp_socket_connect(const char *host, int port)
+{
+       int type = SOCK_STREAM;
+       struct sockaddr_in sock_out;
+       int res;
+       struct hostent *hp;
+
+       res = socket(PF_INET, type, 0);
+       if (res == -1) {
+               return -1;
+       }
+
+       hp = gethostbyname(host);
+       if (!hp) {
+               fprintf(stderr,"unknown host: %s\n", host);
+               close(res);
+               return -1;
+       }
+
+       memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+       sock_out.sin_port = htons(port);
+       sock_out.sin_family = PF_INET;
+
+       if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+               fprintf(stderr,"failed to connect to %s - %s\n", host, strerror(errno));
+               close(res);
+               return -1;
+       }
+
+       return res;
+}
+
+
+/*
+  create a tcp socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int tcp_socket_bind(int port)
+{
+       struct hostent *hp;
+       struct sockaddr_in sock;
+       char host_name[1000];
+       int res;
+       int one=1;
+
+       /* get my host name */
+       if (gethostname(host_name, sizeof(host_name)) == -1) { 
+               fprintf(stderr,"gethostname failed\n"); 
+               return -1; 
+       } 
+
+       /* get host info */
+       if ((hp = gethostbyname(host_name)) == 0) {
+               fprintf(stderr,"gethostbyname: Unknown host %s\n",host_name);
+               return -1;
+       }
+  
+       memset((char *)&sock,0,sizeof(sock));
+       memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+       sock.sin_port = htons(port);
+       sock.sin_family = hp->h_addrtype;
+       sock.sin_addr.s_addr = INADDR_ANY;
+       res = socket(hp->h_addrtype, SOCK_STREAM, 0);
+       if (res == -1) { 
+               fprintf(stderr,"socket failed\n"); 
+               return -1; 
+       }
+
+       setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+       /* now we've got a socket - we need to bind it */
+       if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
+               fprintf(stderr,"bind failed on port %d\n", port);
+               close(res); 
+               return -1;
+       }
+
+       listen(res, 1);
+
+       return res;
+}
+
+/*
+  accept on a tcp socket
+*/
+static int tcp_socket_accept(int fd)
+{
+       struct sockaddr a;
+       socklen_t len;
+       return accept(fd, &a, &len);
+}
+
+static void worker(const char *host, int port1, int port2, int w)
+{
+       int l = tcp_socket_bind(port1);
+       int s2, s1;
+       int count=0;
+
+       set_socket_options(l, "SO_REUSEADDR");
+
+       sleep(2);
+
+       s2 = tcp_socket_connect(host, port2);
+       s1 = tcp_socket_accept(l);
+
+       set_socket_options(s1, "TCP_NODELAY");
+       set_socket_options(s2, "TCP_NODELAY");
+
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\r", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       worker(argv[1], atoi(argv[2]), atoi(argv[3]), 1);
+       return 0;
+}
diff --git a/messaging/udp.c b/messaging/udp.c
new file mode 100644 (file)
index 0000000..12cb9a8
--- /dev/null
@@ -0,0 +1,318 @@
+/* 
+   measure latency of udp sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+
+typedef int BOOL;
+
+#define True 1
+#define False 0
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+  char *name;
+  int level;
+  int option;
+  int value;
+  int opttype;
+} socket_options[] = {
+  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
+  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
+  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
+#ifdef TCP_NODELAY
+  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
+#endif
+  {NULL,0,0,0,0}};
+
+
+/****************************************************************************
+  Get the next token from a string, return False if none found
+  handles double-quotes. 
+Based on a routine by GJC@VILLAGE.COM. 
+Extensively modified by Andrew.Tridgell@anu.edu.au
+****************************************************************************/
+BOOL next_token(char **ptr,char *buff,char *sep)
+{
+  char *s;
+  BOOL quoted;
+  static char *last_ptr=NULL;
+
+  if (!ptr) ptr = &last_ptr;
+  if (!ptr) return(False);
+
+  s = *ptr;
+
+  /* default to simple separators */
+  if (!sep) sep = " \t\n\r";
+
+  /* find the first non sep char */
+  while(*s && strchr(sep,*s)) s++;
+
+  /* nothing left? */
+  if (! *s) return(False);
+
+  /* copy over the token */
+  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+    {
+      if (*s == '\"') 
+       quoted = !quoted;
+      else
+       *buff++ = *s;
+    }
+
+  *ptr = (*s) ? s+1 : s;  
+  *buff = 0;
+  last_ptr = *ptr;
+
+  return(True);
+}
+       
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+       char tok[200];
+
+       while (next_token(&options,tok," \t,"))
+    {
+      int ret=0,i;
+      int value = 1;
+      char *p;
+      BOOL got_value = False;
+
+      if ((p = strchr(tok,'=')))
+       {
+         *p = 0;
+         value = atoi(p+1);
+         got_value = True;
+       }
+
+      for (i=0;socket_options[i].name;i++)
+       if (strcasecmp(socket_options[i].name,tok)==0)
+         break;
+
+      if (!socket_options[i].name)
+       {
+         printf("Unknown socket option %s\n",tok);
+         continue;
+       }
+
+      switch (socket_options[i].opttype)
+       {
+       case OPT_BOOL:
+       case OPT_INT:
+         ret = setsockopt(fd,socket_options[i].level,
+                          socket_options[i].option,(char *)&value,sizeof(int));
+         break;
+
+       case OPT_ON:
+               if (got_value)
+                       printf("syntax error - %s does not take a value\n",tok);
+
+         {
+           int on = socket_options[i].value;
+           ret = setsockopt(fd,socket_options[i].level,
+                            socket_options[i].option,(char *)&on,sizeof(int));
+         }
+         break;          
+       }
+      
+      if (ret != 0)
+       printf("Failed to set socket option %s\n",tok);
+    }
+}
+
+/*
+  connect to a udp socket
+*/
+int udp_socket_connect(int port)
+{
+       int type = SOCK_DGRAM;
+       struct sockaddr_in sock_out;
+       int res;
+       struct hostent *hp;
+       const char *host = "localhost";
+
+       res = socket(PF_INET, type, 0);
+       if (res == -1) {
+               return -1;
+       }
+
+       hp = gethostbyname(host);
+       if (!hp) {
+               fprintf(stderr,"unknown host: %s\n", host);
+               close(res);
+               return -1;
+       }
+
+       memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+       sock_out.sin_port = htons(port);
+       sock_out.sin_family = PF_INET;
+
+       if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+               fprintf(stderr,"failed to connect to %s - %s\n", host, strerror(errno));
+               close(res);
+               return -1;
+       }
+
+       return res;
+}
+
+
+/*
+  create a udp socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int udp_socket_bind(int port)
+{
+       struct hostent *hp;
+       struct sockaddr_in sock;
+       char host_name[1000];
+       int res;
+       int one=1;
+
+       /* get my host name */
+       if (gethostname(host_name, sizeof(host_name)) == -1) { 
+               fprintf(stderr,"gethostname failed\n"); 
+               return -1; 
+       } 
+
+       /* get host info */
+       if ((hp = gethostbyname(host_name)) == 0) {
+               fprintf(stderr,"gethostbyname: Unknown host %s\n",host_name);
+               return -1;
+       }
+  
+       memset((char *)&sock,0,sizeof(sock));
+       memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+       sock.sin_port = htons(port);
+       sock.sin_family = hp->h_addrtype;
+       sock.sin_addr.s_addr = INADDR_ANY;
+       res = socket(hp->h_addrtype, SOCK_DGRAM, 0);
+       if (res == -1) { 
+               fprintf(stderr,"socket failed\n"); 
+               return -1; 
+       }
+
+       setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+       /* now we've got a socket - we need to bind it */
+       if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
+               fprintf(stderr,"bind failed on port %d\n", port);
+               close(res); 
+               return -1;
+       }
+
+       return res;
+}
+
+static void worker(int port1, int port2, int w)
+{
+       int s1 = udp_socket_bind(port1);
+       int s2;
+       int count=0;
+
+       set_socket_options(s1, "SO_REUSEADDR");
+
+       sleep(2);
+
+       s2 = udp_socket_connect(port2);
+
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\r", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       if (fork() == 0) {
+               worker(1313, 1314, 0);
+       } else {
+               worker(1314, 1313, 1);
+       }
+       return 0;
+}
diff --git a/messaging/udp2.c b/messaging/udp2.c
new file mode 100644 (file)
index 0000000..cabec43
--- /dev/null
@@ -0,0 +1,313 @@
+/* 
+   measure latency of udp sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+
+typedef int BOOL;
+
+#define True 1
+#define False 0
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+  char *name;
+  int level;
+  int option;
+  int value;
+  int opttype;
+} socket_options[] = {
+  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
+  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
+  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
+#ifdef TCP_NODELAY
+  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
+#endif
+  {NULL,0,0,0,0}};
+
+
+/****************************************************************************
+  Get the next token from a string, return False if none found
+  handles double-quotes. 
+Based on a routine by GJC@VILLAGE.COM. 
+Extensively modified by Andrew.Tridgell@anu.edu.au
+****************************************************************************/
+BOOL next_token(char **ptr,char *buff,char *sep)
+{
+  char *s;
+  BOOL quoted;
+  static char *last_ptr=NULL;
+
+  if (!ptr) ptr = &last_ptr;
+  if (!ptr) return(False);
+
+  s = *ptr;
+
+  /* default to simple separators */
+  if (!sep) sep = " \t\n\r";
+
+  /* find the first non sep char */
+  while(*s && strchr(sep,*s)) s++;
+
+  /* nothing left? */
+  if (! *s) return(False);
+
+  /* copy over the token */
+  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+    {
+      if (*s == '\"') 
+       quoted = !quoted;
+      else
+       *buff++ = *s;
+    }
+
+  *ptr = (*s) ? s+1 : s;  
+  *buff = 0;
+  last_ptr = *ptr;
+
+  return(True);
+}
+       
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+       char tok[200];
+
+       while (next_token(&options,tok," \t,"))
+    {
+      int ret=0,i;
+      int value = 1;
+      char *p;
+      BOOL got_value = False;
+
+      if ((p = strchr(tok,'=')))
+       {
+         *p = 0;
+         value = atoi(p+1);
+         got_value = True;
+       }
+
+      for (i=0;socket_options[i].name;i++)
+       if (strcasecmp(socket_options[i].name,tok)==0)
+         break;
+
+      if (!socket_options[i].name)
+       {
+         printf("Unknown socket option %s\n",tok);
+         continue;
+       }
+
+      switch (socket_options[i].opttype)
+       {
+       case OPT_BOOL:
+       case OPT_INT:
+         ret = setsockopt(fd,socket_options[i].level,
+                          socket_options[i].option,(char *)&value,sizeof(int));
+         break;
+
+       case OPT_ON:
+               if (got_value)
+                       printf("syntax error - %s does not take a value\n",tok);
+
+         {
+           int on = socket_options[i].value;
+           ret = setsockopt(fd,socket_options[i].level,
+                            socket_options[i].option,(char *)&on,sizeof(int));
+         }
+         break;          
+       }
+      
+      if (ret != 0)
+       printf("Failed to set socket option %s\n",tok);
+    }
+}
+
+/*
+  connect to a udp socket
+*/
+int udp_socket_connect(const char *host, int port)
+{
+       int type = SOCK_DGRAM;
+       struct sockaddr_in sock_out;
+       int res;
+       struct hostent *hp;
+
+       res = socket(PF_INET, type, 0);
+       if (res == -1) {
+               return -1;
+       }
+
+       hp = gethostbyname(host);
+       if (!hp) {
+               fprintf(stderr,"unknown host: %s\n", host);
+               close(res);
+               return -1;
+       }
+
+       memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+       sock_out.sin_port = htons(port);
+       sock_out.sin_family = PF_INET;
+
+       if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+               fprintf(stderr,"failed to connect to %s - %s\n", host, strerror(errno));
+               close(res);
+               return -1;
+       }
+
+       return res;
+}
+
+
+/*
+  create a udp socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int udp_socket_bind(int port)
+{
+       struct hostent *hp;
+       struct sockaddr_in sock;
+       char host_name[1000];
+       int res;
+       int one=1;
+
+       /* get my host name */
+       if (gethostname(host_name, sizeof(host_name)) == -1) { 
+               fprintf(stderr,"gethostname failed\n"); 
+               return -1; 
+       } 
+
+       /* get host info */
+       if ((hp = gethostbyname(host_name)) == 0) {
+               fprintf(stderr,"gethostbyname: Unknown host %s\n",host_name);
+               return -1;
+       }
+  
+       memset((char *)&sock,0,sizeof(sock));
+       memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+       sock.sin_port = htons(port);
+       sock.sin_family = hp->h_addrtype;
+       sock.sin_addr.s_addr = INADDR_ANY;
+       res = socket(hp->h_addrtype, SOCK_DGRAM, 0);
+       if (res == -1) { 
+               fprintf(stderr,"socket failed\n"); 
+               return -1; 
+       }
+
+       setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+       /* now we've got a socket - we need to bind it */
+       if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
+               fprintf(stderr,"bind failed on port %d\n", port);
+               close(res); 
+               return -1;
+       }
+
+       listen(res, 1);
+
+       return res;
+}
+
+static void worker(const char *host, int port1, int port2, int w)
+{
+       int s1 = udp_socket_bind(port1);
+       int s2;
+       int count=0;
+
+       sleep(2);
+
+       s2 = udp_socket_connect(host, port2);
+
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\n", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       worker(argv[1], atoi(argv[2]), atoi(argv[3]), 1);
+       return 0;
+}
diff --git a/messaging/unix_dgram.c b/messaging/unix_dgram.c
new file mode 100644 (file)
index 0000000..c4b3c7d
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+   measure latency of unix domain sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+/*
+  connect to a unix domain socket
+*/
+int ux_socket_connect(const char *name)
+{
+       int fd;
+        struct sockaddr_un addr;
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+
+       fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+       if (fd == -1) {
+               return -1;
+       }
+       
+       if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+
+/*
+  create a unix domain socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int ux_socket_bind(const char *name)
+{
+       int fd;
+        struct sockaddr_un addr;
+
+       /* get rid of any old socket */
+       unlink(name);
+
+       fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+       if (fd == -1) return -1;
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+
+        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+               close(fd);
+               return -1;
+       }       
+
+       return fd;
+}
+
+static void worker(const char *n1, const char *n2, int w)
+{
+       int s1 = ux_socket_bind(n1);
+       int s2;
+       int count=0;
+
+       sleep(1);
+
+       s2 = ux_socket_connect(n2);
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\r", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       if (fork() == 0) {
+               worker("sock2.unx", "sock1.unx", 0);
+       }
+       worker("sock1.unx", "sock2.unx", 1);
+       return 0;
+}
diff --git a/messaging/unix_stream.c b/messaging/unix_stream.c
new file mode 100644 (file)
index 0000000..bd8a70b
--- /dev/null
@@ -0,0 +1,145 @@
+/* 
+   measure latency of unix domain sockets
+   tridge@samba.org July 2006
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+       gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+       gettimeofday(&tp2,NULL);
+       return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
+               (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
+}
+
+static void fatal(const char *why)
+{
+       fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
+       exit(1);
+}
+
+/*
+  connect to a unix domain socket
+*/
+int ux_socket_connect(const char *name)
+{
+       int fd;
+        struct sockaddr_un addr;
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1) {
+               return -1;
+       }
+       
+       if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+
+/*
+  create a unix domain socket and bind it
+  return a file descriptor open on the socket 
+*/
+static int ux_socket_bind(const char *name)
+{
+       int fd;
+        struct sockaddr_un addr;
+
+       /* get rid of any old socket */
+       unlink(name);
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1) return -1;
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+
+        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+               close(fd);
+               return -1;
+       }       
+
+       listen(fd, 1);
+
+       return fd;
+}
+
+/*
+  accept on a unix socket
+*/
+static int ux_socket_accept(int fd)
+{
+       struct sockaddr a;
+       socklen_t len;
+       return accept(fd, &a, &len);
+}
+
+static void worker(const char *n1, const char *n2, int w)
+{
+       int l = ux_socket_bind(n1);
+       int s2, s1;
+       int count=0;
+
+       sleep(1);
+
+       s2 = ux_socket_connect(n2);
+       s1 = ux_socket_accept(l);
+       start_timer();
+
+       while (1) {
+               char c=0;
+               if (write(s2, &c, 1) != 1) {
+                       fatal("write");
+               }
+               if (read(s1, &c, 1) != 1) {
+                       fatal("read");
+               }
+               if (w == 1 && (end_timer() > 1.0)) {
+                       printf("%8u ops/sec\r", 
+                              (unsigned)(2*count/end_timer()));
+                       fflush(stdout);
+                       start_timer();
+                       count=0;
+               }
+               count++;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       if (fork() == 0) {
+               worker("sock2.unx", "sock1.unx", 0);
+       }
+       worker("sock1.unx", "sock2.unx", 1);
+       return 0;
+}