[httperf] More than one IP

Martin Arlitt arlitt at granite.hpl.hp.com
Thu Jul 8 09:47:49 PDT 2004


Rivalino

below is a patch to allow httperf to use more than one source IP address
(assuming that the client machine is configured to support those
addresses).  please be sure to use this only on an isolated network.

you need to patch three files to implement this:
httperf.h
httperf.c
core.c

the patch also contains a fix for a problem with gen/wsesslog.c.  that's
not needed for supporting multiple IP addresses, but is a good idea if you
use sessions.

the patch includes two different ways for specifying the addresses.  the
code enclosed by "MULTIPLE_SRC_ADDRS_OPTION" enables the command line
option "--src-addrs", which allows you to specify the addresses on the
command line.  e.g., --src-addrs=192.168.1.1,192.168.1.2,192.168.1.3

the code enclosed by "MULTIPLE_SRC_ADDRS_FILE_OPTION" enables the command
line option "--src-addrs-file".  this option requires a filename.  in the
file you specify one IP address per line.  This is useful if you want to
use lots of client IP addresses.

to compile the patched version of httperf you will need to add the
appropriate CPPFLAG, or remove the ifdefs corresponding to the option you
want to use.

to configure multiple IP addresses on the client's NIC, use:

# /sbin/ip address add <ip_address> dev <interface>

e.g.,
# /sbin/ip address add 192.168.1.1 dev eth0
# /sbin/ip address add 192.168.1.2 dev eth0

then run httperf

./httperf --server=<server> --src-addrs=192.168.1.1,192.168.1.2 --hog --num-conns=2

note that you need to specify the --hog option (for the implementation
below at least).  also, you will need to issue at least N connections in
order to see connections from N different client IP addresses.  this
implementation cycles through the IP addresses in round-robin fashion.

the implementation below allows 16 addresses to be specified on the
command line, or 32768 in a file.

Martin

------------------------------------------------------------------

diff -urN httperf-0.8/core.c httperf-0.8.mod/core.c
--- httperf-0.8/core.c	2000-10-31 16:57:50.000000000 -0700
+++ httperf-0.8.mod/core.c	2004-07-08 10:24:28.000000000 -0600
@@ -881,6 +881,30 @@

   if (param.hog)
     {
+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+      if(param.src_addrs.num_addrs > 0)
+	{
+	  /* determine client address to use */
+              myaddr.sin_addr.s_addr =
+                param.src_addrs.src_addr[param.src_addrs.next_addr].s_addr;
+              param.src_addrs.next_addr =
+                (param.src_addrs.next_addr+1) % param.src_addrs.num_addrs;
+	}
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+      if(param.src_addrs_file.num_addrs > 0)
+	{
+	  /* determine client address to use */
+              myaddr.sin_addr.s_addr =
+                param.src_addrs_file.src_addr
+		[param.src_addrs_file.next_addr].s_addr;
+
+              param.src_addrs_file.next_addr =
+                (param.src_addrs_file.next_addr+1)
+                % param.src_addrs_file.num_addrs;
+	}
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
+
       while (1)
 	{
 	  myport = port_get ();
diff -urN httperf-0.8/gen/wsesslog.c httperf-0.8.mod/gen/wsesslog.c
--- httperf-0.8/gen/wsesslog.c	2000-10-11 17:40:46.000000000 -0600
+++ httperf-0.8.mod/gen/wsesslog.c	2003-07-29 13:14:58.000000000 -0600
@@ -312,6 +312,9 @@
   sess = session_get_sess_from_call (call);
   priv = SESS_PRIVATE_DATA (sess);

+  if (sess->failed)
+    return;
+
   ++priv->num_calls_destroyed;

   if (priv->num_calls_destroyed >= priv->total_num_reqs)
diff -urN httperf-0.8/httperf.c httperf-0.8.mod/httperf.c
--- httperf-0.8/httperf.c	2000-10-31 13:20:00.000000000 -0700
+++ httperf-0.8.mod/httperf.c	2004-07-08 10:23:55.000000000 -0600
@@ -117,6 +117,12 @@
     {"rate",	     required_argument,	(int *) &param.rate,		0},
     {"recv-buffer",  required_argument, (int *) &param.recv_buffer_size, 0},
     {"retry-on-failure", no_argument,	&param.retry_on_failure,	1},
+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+    {"src-addrs",     required_argument, (int *) &param.src_addrs,       0},
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+    {"src-addrs-file",required_argument, (int *) &param.src_addrs_file, 0},
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
     {"send-buffer",  required_argument, (int *) &param.send_buffer_size, 0},
     {"server",	     required_argument, (int *) &param.server,		0},
     {"server-name",  required_argument, (int *) &param.server_name,	0},
@@ -151,6 +157,12 @@
 	  "\t[--port N] "
 	  "[--print-reply [header|body]] [--print-request [header|body]]\n"
 	  "\t[--rate X] [--recv-buffer N] [--retry-on-failure] "
+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+          "\t[--src-addrs A1,...,An]\n"
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+          "\t[--src-addrs-file file]\n"
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
 	  "[--send-buffer N]\n"
 	  "\t[--server S] [--server-name S] [--session-cookies]\n"
 #ifdef HAVE_SSL
@@ -220,6 +232,22 @@
   void *flag;
   Time t;

+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+  struct in_addr src_addr;
+  int result;
+  int numSrcs;
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+  FILE *fp;
+  char line[1000];
+  char ip_addr[1000];
+
+  struct in_addr src_addr;
+  int result;
+  int numSrcs;
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
+
 #ifdef __FreeBSD__
   /* This works around a bug in earlier versions of FreeBSD that cause
      non-finite IEEE arithmetic to cause SIGFPE instead of the
@@ -359,6 +387,105 @@
 		  exit (1);
 		}
 	    }
+
+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+          else if (flag == &param.src_addrs)
+            {
+              name = "bad source address";
+              numSrcs=0;
+
+              while(numSrcs < MAX_SRC_ADDRS)
+                {
+                  /* determine address */
+                  if((end = strchr(optarg, ',')) == NULL)
+                    {
+                      /* last address */
+                      numSrcs = MAX_SRC_ADDRS;
+                    }
+                  else
+                    {
+                      *end++ = '\0';
+                    }
+
+                  /* convert the address */
+                  result = inet_aton(optarg, &src_addr);
+                  if(result == 0)
+                    {
+                      fprintf(stderr,"%s: %s in --src-addrs arg "
+                              "(rest: '%s')\n",
+                              prog_name, name, end);
+                      exit(1);
+                    }
+
+                  /* store the address */
+                  param.src_addrs.src_addr
+                    [param.src_addrs.num_addrs++].s_addr = src_addr.s_addr;
+
+                  /* advance to next address */
+                  optarg = end;
+                }
+            }
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+          else if (flag == &param.src_addrs_file)
+            {
+              param.src_addrs_file.name = optarg;
+
+              name = "bad source address";
+              numSrcs=0;
+
+              /* open file with source IP addresses */
+              if((fp = fopen(param.src_addrs_file.name, "r")) == NULL)
+                {
+		  fprintf(stderr, "%s: can't open %s\n",
+			  prog_name, param.src_addrs_file.name);
+                  exit(1);
+                }
+
+              fgets(line, sizeof(line), fp);
+
+              while(!feof(fp))
+                {
+                  /* skip comments */
+                  if (line[0] == '#')
+		    continue;
+
+		  if(sscanf(line, "%s", ip_addr) == 1)
+		    {
+		      if(numSrcs >= MAX_SRC_FILE_ADDRS)
+			{
+			  fprintf(stderr,"%s: too many ip addresses "
+				  "in %s\n",
+				  prog_name, param.src_addrs_file.name);
+			  exit(1);
+			}
+
+		      /* convert the address */
+		      result = inet_aton(ip_addr, &src_addr);
+		      if(result == 0)
+			{
+			  fprintf(stderr,"%s: invalid ip address %s in %s\n ",
+				  prog_name, ip_addr,
+				  param.src_addrs_file.name);
+			  exit(1);
+			}
+
+		      /* store the address */
+		      param.src_addrs_file.src_addr
+			[param.src_addrs_file.num_addrs++].s_addr =
+			src_addr.s_addr;
+
+		      numSrcs++;
+		    }
+
+		  /* advance to next address */
+		  fgets(line, sizeof(line), fp);
+		}
+	      /* close the file of ip addresses */
+	      fclose(fp);
+	    }
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
+
 	  else if (flag == &param.print_request || flag == &param.print_reply)
 	    {
 	      int val;
diff -urN httperf-0.8/httperf.h httperf-0.8.mod/httperf.h
--- httperf-0.8/httperf.h	2000-10-31 13:32:09.000000000 -0700
+++ httperf-0.8.mod/httperf.h	2004-07-08 09:51:53.000000000 -0600
@@ -31,6 +31,18 @@
 #include <sys/types.h>
 #include <sys/resource.h>

+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
+
 #define VERSION	"0.8"

 typedef double Time;
@@ -96,6 +108,14 @@
 #define PRINT_HEADER	(1 << 0)
 #define PRINT_BODY	(1 << 1)

+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+#define MAX_SRC_ADDRS 16
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+#define MAX_SRC_FILE_ADDRS 32769
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
+
 typedef struct Cmdline_Params
   {
     int http_version;	/* (default) HTTP protocol version */
@@ -167,6 +187,27 @@
 	double target_miss_rate;
       }
     wset;
+
+#ifdef MULTIPLE_SRC_ADDRS_OPTION
+    struct
+    {
+      int next_addr;
+      int num_addrs;
+      struct in_addr src_addr[MAX_SRC_ADDRS];
+    }
+    src_addrs;
+#endif /* MULTIPLE_SRC_ADDRS_OPTION */
+
+#ifdef MULTIPLE_SRC_ADDRS_FILE_OPTION
+    struct
+    {
+      char *name;
+      int next_addr;
+      int num_addrs;
+      struct in_addr src_addr[MAX_SRC_FILE_ADDRS];
+    }
+    src_addrs_file;
+#endif /* MULTIPLE_SRC_ADDRS_FILE_OPTION */
   }
 Cmdline_Params;




More information about the httperf mailing list