17489343 Update solaris rds-tools to 2.0.7-1.12
authorBoris Chiu <boris.chiu@oracle.com>
Wed, 16 Oct 2013 15:44:35 -0700
changeset 1513 594764ea1267
parent 1512 f57514e19ede
child 1514 b33565a68995
17489343 Update solaris rds-tools to 2.0.7-1.12 17615235 rds-tools fails to compile on 32
components/open-fabrics/rds-tools/patches/base.patch
--- a/components/open-fabrics/rds-tools/patches/base.patch	Wed Oct 16 10:00:08 2013 -0700
+++ b/components/open-fabrics/rds-tools/patches/base.patch	Wed Oct 16 15:44:35 2013 -0700
@@ -15,7 +15,7 @@
  #include <sys/stat.h>
  #include <sys/poll.h>
  #include <ctype.h>
-@@ -22,12 +28,51 @@
+@@ -22,12 +28,27 @@
  #include <fcntl.h>
  #include <sched.h>
  #include <getopt.h>
@@ -32,57 +32,74 @@
 +#include <infiniband/ofa_solaris.h>
 +#endif
  
++#if defined(__SVR4) && defined(__sun)
  /*
-+ * Define these here until these are defined in rds.h
-+ * (rds_reset, rds_asend_args and rds_rdma_send_notify)
++ * This definition is forward looking and is not yet present
++ * in Solaris rds.h file
 + */
-+#define	SIOCRDSSETTOS		11000
-+#define	SIOCRDSGETTOS		11001
-+#define	RDS_SEND_NOTIFY_ME	0x0100
-+#define	RDS_CMSG_ASYNC_SEND	10
-+#define	RDS_CONN_RESET		8
-+
-+struct rds_reset {
-+	u_int8_t	tos;
-+#if defined(__SVR4) && defined(__sun)
-+	u_int32_t	src;
-+	u_int32_t	dst;
-+#else
-+	struct in_addr	src;
-+	struct in_addr	dst;
++#define RDS_CMSG_RDMA_SEND_STATUS RDS_CMSG_RDMA_STATUS
 +#endif
-+};
-+
-+struct rds_asend_args {
-+	u_int64_t	user_token;
-+	u_int64_t	flags;
-+};
-+
-+struct rds_rdma_send_notify {
-+	u_int64_t	user_token;
-+	int32_t		status;
-+};
-+
 +
 +/*
   *
   * TODO
   *  - checksum the data some day.
-@@ -74,11 +119,38 @@
- 	uint32_t        rdma_vector;
- 	uint32_t	rdma_alignment;
+@@ -45,8 +66,9 @@
+         M_RDMA_READ_ONLY,
+         M_RDMA_WRITE_ONLY
+ };
++#define VERSION_MAX_LEN 16 
+ 
+-struct options {
++struct options_2_0_6 {
+ 	uint32_t	req_depth;
+ 	uint32_t	req_size;
+ 	uint32_t	ack_size;
+@@ -76,9 +98,68 @@
  	uint32_t	connect_retries;
-+	uint8_t         reset;
-+	uint8_t         tos;
-+	uint8_t         async;
  } __attribute__((packed));
  
++struct options {
++	char		version[VERSION_MAX_LEN];
++        uint32_t        req_depth;
++        uint32_t        req_size;
++        uint32_t        ack_size;
++        uint32_t        rdma_size;
++        uint32_t        send_addr;
++        uint32_t        receive_addr;
++        uint16_t        starting_port;
++        uint16_t        nr_tasks;
++        uint32_t        run_time;
++        uint8_t         summary_only;
++        uint8_t         rtprio;
++        uint8_t         tracing;
++        uint8_t         verify;
++        uint8_t         show_params;
++        uint8_t         show_perfdata;
++        uint8_t         use_cong_monitor;
++        uint8_t         rdma_use_once;
++        uint8_t         rdma_use_get_mr;
++        uint8_t         rdma_use_fence;
++        uint8_t         rdma_cache_mrs;
++        uint8_t         rdma_key_o_meter;
++        uint8_t         suppress_warnings;
++        uint8_t         simplex;
++        uint8_t         rw_mode;
++        uint32_t        rdma_vector;
++        uint32_t        rdma_alignment;
++        uint32_t        connect_retries;
++        uint8_t         tos;
++        uint8_t         async;
++} __attribute__((packed));
++
 +#define MAX_BUCKETS 16
 +
  static struct options	opt;
  static int		control_fd;
 +static uint64_t         rtt_threshold;
 +static int              show_histogram;
++static int		reset_connection;
++static char		peer_version[VERSION_MAX_LEN];
  
 +static int get_bucket(uint64_t rtt_time)
 +{
@@ -107,7 +124,7 @@
  struct counter {
  	uint64_t	nr;
  	uint64_t	sum;
-@@ -102,6 +174,10 @@
+@@ -102,6 +183,10 @@
  
  #define NR_STATS S__LAST
  
@@ -118,7 +135,7 @@
  /*
   * Parents share a mapped array of these with their children.  Each child
   * gets one.  It's used to communicate between the child and the parent
-@@ -110,9 +186,11 @@
+@@ -110,9 +195,11 @@
  struct child_control {
  	pid_t pid;
  	int ready;
@@ -130,7 +147,7 @@
  } __attribute__((aligned (256))); /* arbitrary */
  
  struct soak_control {
-@@ -132,6 +210,7 @@
+@@ -132,6 +219,7 @@
   */
  #define OP_REQ		1
  #define OP_ACK		2
@@ -138,27 +155,26 @@
  
  #define RDMA_OP_READ	1
  #define RDMA_OP_WRITE	2
-@@ -143,12 +222,12 @@
-  */
- struct header {
- 	uint32_t	seq;
-+	uint8_t         op;
- 	uint32_t	from_addr;
- 	uint32_t	to_addr;
+@@ -148,7 +236,7 @@
  	uint16_t	from_port;
  	uint16_t	to_port;
  	uint16_t	index;
 -	uint8_t		op;
++	uint8_t         op;
  
  	/* RDMA related.
  	 * rdma_op must be the first field, because we
-@@ -163,11 +242,18 @@
+@@ -162,12 +250,21 @@
+ 	uint32_t	rdma_size;
  	uint32_t        rdma_vector;
  
- 	uint8_t		data[0];
-+	uint8_t        retry;
-+	uint8_t        rdma_remote_err;
+-	uint8_t		data[0];
++	/* Async send related. */
++	uint8_t         retry;
++	uint8_t         rdma_remote_err;
 +	uint8_t         pending;
++
++	uint8_t         data[0];
  } __attribute__((packed));
  
  #define MIN_MSG_BYTES		(sizeof(struct header))
@@ -171,7 +187,7 @@
  #define die(fmt...) do {		\
  	fprintf(stderr, fmt);		\
  	exit(1);			\
-@@ -254,7 +340,20 @@
+@@ -254,7 +351,20 @@
  
  	die("invalid host name or dotted quad '%s'\n", ptr);
  }
@@ -192,7 +208,7 @@
  static void usage(void)
  {
          fprintf(stderr, "rds-stress version %s\n", RDS_VERSION);
-@@ -273,6 +372,7 @@
+@@ -273,6 +383,7 @@
  	" -d [depth, 1]     request pipeline depth, nr outstanding\n"
  	" -t [nr, 1]        number of child tasks\n"
  	" -T [seconds, 0]   runtime of test, 0 means infinite\n"
@@ -200,7 +216,7 @@
  	" -D [bytes]        RDMA: size\n"
  	" -I [iovecs, 1]    RDMA: number of user buffers to target (max 512)\n"
          " -M [nr, 0]        RDMA: mode (0=readwrite,1=readonly,2=writeonly)\n"
-@@ -281,6 +381,9 @@
+@@ -281,6 +392,9 @@
  	" -c                measure cpu use with per-cpu soak processes\n"
  	" -V                trace execution\n"
  	" -z                print a summary at end of test only\n"
@@ -210,7 +226,7 @@
  	"\n"
  	"Example:\n"
  	"  recv$ rds-stress\n"
-@@ -310,7 +413,7 @@
+@@ -310,7 +424,7 @@
  static void check_parent(pid_t pid)
  {
  	if (pid != getppid())
@@ -219,7 +235,7 @@
  }
  
  /*
-@@ -334,6 +437,7 @@
+@@ -334,6 +448,7 @@
  		msg_pattern[i] = k;
  }
  
@@ -227,7 +243,7 @@
  #if __BYTE_ORDER == __LITTLE_ENDIAN
  #define htonll(x)	bswap_64(x)
  #define ntohll(x)	bswap_64(x)
-@@ -341,6 +445,7 @@
+@@ -341,6 +456,7 @@
  #define htonll(x)	(x)
  #define ntohll(x)	(x)
  #endif
@@ -235,7 +251,7 @@
  
  static void encode_hdr(struct header *dst, const struct header *hdr)
  {
-@@ -361,6 +466,7 @@
+@@ -361,6 +477,7 @@
  	dst->rdma_key = htonll(hdr->rdma_key);
  	dst->rdma_size = htonl(hdr->rdma_size);
  	dst->rdma_vector = htonl(hdr->rdma_vector);
@@ -243,7 +259,7 @@
  }
  
  static void decode_hdr(struct header *dst, const struct header *hdr)
-@@ -382,6 +488,7 @@
+@@ -382,6 +499,7 @@
  	dst->rdma_key = ntohll(hdr->rdma_key);
  	dst->rdma_size = ntohl(hdr->rdma_size);
  	dst->rdma_vector = ntohl(hdr->rdma_vector);
@@ -251,7 +267,7 @@
  }
  
  static void fill_hdr(void *message, uint32_t bytes, struct header *hdr)
-@@ -412,11 +519,19 @@
+@@ -412,11 +530,19 @@
   * Compare incoming message header with expected header. All header fields
   * are in host byte order except for address and port fields.
   */
@@ -272,7 +288,7 @@
  	if (memcmp(&msghdr, hdr, BASIC_HEADER_SIZE)) {
  #define bleh(var, disp)					\
  		disp(hdr->var),				\
-@@ -428,7 +543,7 @@
+@@ -428,7 +554,7 @@
  		 * with stdout() and we don't get things stomping on each
  		 * other
  		 */
@@ -281,7 +297,7 @@
  			"didn't contain the fields we expected:\n"
  			"    member        expected eq             got\n"
  			"       seq %15u %s %15u\n"
-@@ -438,6 +553,7 @@
+@@ -438,6 +564,7 @@
  			"   to_port %15u %s %15u\n"
  			"     index %15u %s %15u\n"
  			"        op %15u %s %15u\n",
@@ -289,7 +305,7 @@
  			bleh(seq, /**/),
  			bleh(from_addr, inet_ntoa_32),
  			bleh(from_port, ntohs),
-@@ -569,6 +685,9 @@
+@@ -569,6 +696,9 @@
  
  	fcntl(fd, F_SETFL, O_NONBLOCK);
  
@@ -299,7 +315,7 @@
  	return fd;
  }
  
-@@ -584,7 +703,11 @@
+@@ -584,7 +714,11 @@
  	if (opts->receive_addr == 0)
  		return 1;
  
@@ -311,7 +327,7 @@
  	sin.sin_port = htons(opts->starting_port);
  	sin.sin_addr.s_addr = htonl(opts->receive_addr);
  
-@@ -639,7 +762,7 @@
+@@ -639,7 +773,7 @@
  	mr_args.flags = RDS_FREE_MR_ARGS_INVALIDATE;
  #endif
  	if (setsockopt(fd, sol, RDS_FREE_MR, &mr_args, sizeof(mr_args)))
@@ -320,7 +336,7 @@
  	mrs_allocated--;
  }
  
-@@ -677,7 +800,11 @@
+@@ -677,7 +811,11 @@
  	size = sizeof(struct rdma_key_o_meter)
  			+ 2 * nr_tasks * sizeof(*kt)
  			+ 2 * RDMA_MAX_TRACKED_KEYS * sizeof(*ks);
@@ -332,7 +348,7 @@
  	if (base == MAP_FAILED)
  		die_errno("alloc_rdma_buffers: mmap failed");
  
-@@ -828,13 +955,20 @@
+@@ -828,13 +966,20 @@
  	}
  
  	if (!failed)
@@ -354,7 +370,7 @@
  	unsigned int		unacked;
  	struct sockaddr_in	src_addr;	/* same for all tasks */
  	struct sockaddr_in	dst_addr;
-@@ -846,7 +980,14 @@
+@@ -846,7 +991,14 @@
  	uint16_t		recv_index;
  	struct timeval *	send_time;
  	struct header *		ack_header;
@@ -369,7 +385,7 @@
  	/* RDMA related stuff */
  	uint64_t **		local_buf;
  	uint64_t **		rdma_buf;
-@@ -865,7 +1006,11 @@
+@@ -865,7 +1017,11 @@
  	/* We use mmap here rather than malloc, because it is always
  	 * page aligned. */
  	len = 2 * opts->nr_tasks * opts->req_depth * (opts->rdma_vector * opts->rdma_size) + sys_page_size;
@@ -381,7 +397,7 @@
  	if (base == MAP_FAILED)
  		die_errno("alloc_rdma_buffers: mmap failed");
  	memset(base, 0x2f, len);
-@@ -915,17 +1060,16 @@
+@@ -915,17 +1071,16 @@
  	if (RDMA_OP_READ == hdr->rdma_op) {
  		if (opt.verify)
  			rds_fill_buffer(rdma_addr, rdma_size, hdr->rdma_pattern);
@@ -405,7 +421,7 @@
  	}
  }
  
-@@ -947,7 +1091,7 @@
+@@ -947,7 +1102,7 @@
  		die("Unexpected RDMA op %u in request\n", in_hdr->rdma_op);
  
  
@@ -414,7 +430,7 @@
  		in_hdr->rdma_op == RDMA_OP_WRITE? "write to" : "read from",
  		rdma_size,
  		(unsigned long long) in_hdr->rdma_addr,
-@@ -966,21 +1110,33 @@
+@@ -966,21 +1121,33 @@
  	hdr->rdma_vector = in_hdr->rdma_vector;
  }
  
@@ -454,20 +470,21 @@
  	if (status) {
  		const char *errmsg;
  
-@@ -987,10 +1143,10 @@
+@@ -987,20 +1154,50 @@
  		switch (status) {
  		case RDS_RDMA_REMOTE_ERROR:
  			errmsg = "remote error"; break;
 -		case RDS_RDMA_CANCELED:
 -			errmsg = "operation was cancelled"; break;
- 		case RDS_RDMA_DROPPED:
+-		case RDS_RDMA_DROPPED:
++		case RDS_RDMA_SEND_DROPPED:
  			errmsg = "operation was dropped"; break;
-+		case RDS_RDMA_CANCELED:
+-		case RDS_RDMA_OTHER_ERROR:
++		case RDS_RDMA_SEND_CANCELED:
 +			errmsg = "operation was cancelled"; break;
- 		case RDS_RDMA_OTHER_ERROR:
++		case RDS_RDMA_SEND_OTHER_ERROR:
  			errmsg = "other error"; break;
  		default:
-@@ -997,10 +1153,38 @@
  			errmsg = "unknown error"; break;
  		}
  
@@ -480,7 +497,7 @@
 +				errmsg);
 +
 +		if (hdr &&
-+			(status == RDS_RDMA_DROPPED ||
++			(status == RDS_RDMA_SEND_DROPPED ||
 +			 status == RDS_RDMA_REMOTE_ERROR)) {
 +
 +			if (hdr->seq == seq) {
@@ -501,14 +518,16 @@
 +		} else if (hdr) {
 +			hdr->pending = 0;
 +			hdr->retry = 0;
++			hdr->rdma_remote_err = 0;
 +		}
 +	} else if (hdr) {
 +		hdr->pending = 0;
 +		hdr->retry = 0;
++		hdr->rdma_remote_err = 0;
  	}
  
  	t->rdma_inflight[i] = 0;
-@@ -1007,6 +1191,9 @@
+@@ -1007,6 +1204,9 @@
  	t->drain_rdmas = 0;
  }
  
@@ -518,7 +537,7 @@
  #define MSG_MAXIOVLEN 2
  
  /*
-@@ -1018,11 +1205,14 @@
+@@ -1018,11 +1218,14 @@
  	static char ctlbuf[1024];
  	struct cmsghdr *cmsg;
  
@@ -538,7 +557,7 @@
  	cmsg->cmsg_type = type;
  	cmsg->cmsg_len = CMSG_LEN(size);
  	memcpy(CMSG_DATA(cmsg), ptr, size);
-@@ -1034,7 +1224,7 @@
+@@ -1034,7 +1237,7 @@
   * the ACK packet.
   */
  static void rdma_build_cmsg_xfer(struct msghdr *msg, const struct header *hdr,
@@ -547,7 +566,7 @@
  {
  
  #define RDS_MAX_IOV 512 /* FIX_ME - put this into rds.h or use socket max ?*/
-@@ -1048,7 +1238,7 @@
+@@ -1048,7 +1251,7 @@
  	rdma_size = hdr->rdma_size;
  	rdma_vector = hdr->rdma_vector;
  
@@ -556,7 +575,7 @@
  			user_token,
  			(unsigned long long) hdr->rdma_key,
  			rdma_size, local_buf,
-@@ -1102,6 +1292,15 @@
+@@ -1102,6 +1305,15 @@
  	rdma_put_cmsg(msg, RDS_CMSG_RDMA_ARGS, &args, sizeof(args));
  }
  
@@ -572,7 +591,7 @@
  static void rdma_build_cmsg_dest(struct msghdr *msg, rds_rdma_cookie_t rdma_dest)
  {
  	rdma_put_cmsg(msg, RDS_CMSG_RDMA_DEST, &rdma_dest, sizeof(rdma_dest));
-@@ -1174,19 +1373,17 @@
+@@ -1174,19 +1386,17 @@
  	hdr->index = qindex;
  }
  
@@ -597,7 +616,7 @@
  	fill_hdr(buf, size, hdr);
  
  	memset(&msg, 0, sizeof(msg));
-@@ -1198,27 +1395,10 @@
+@@ -1198,27 +1408,10 @@
  	iov.iov_base = buf;
  	iov.iov_len = size;
  
@@ -627,7 +646,7 @@
  		unsigned int qindex = hdr->index;
  
  		if (t->rdma_inflight[qindex] != 0) {
-@@ -1230,16 +1410,35 @@
+@@ -1230,16 +1423,35 @@
  			 *
  			 * We return one of the more obscure error messages,
  			 * which we recognize and handle in the top loop. */
@@ -665,7 +684,7 @@
  	ret = sendmsg(fd, &msg, 0);
  	if (ret < 0) {
  		if (errno != EAGAIN && errno != ENOBUFS)
-@@ -1256,10 +1455,41 @@
+@@ -1256,10 +1468,41 @@
  		 * lower 32bit of the cookie */
  		rdma_key_o_meter_add(cookie);
  	}
@@ -707,7 +726,7 @@
  static int send_one(int fd, struct task *t,
  		struct options *opts,
  		struct child_control *ctl)
-@@ -1266,12 +1496,16 @@
+@@ -1266,12 +1509,16 @@
  {
  	struct timeval start;
  	struct timeval stop;
@@ -727,7 +746,7 @@
  				opts->rdma_size,
  				opts->req_depth,
  				opts->rw_mode,
-@@ -1279,7 +1513,7 @@
+@@ -1279,7 +1526,7 @@
  
  
  	gettimeofday(&start, NULL);
@@ -736,7 +755,7 @@
  	gettimeofday(&stop, NULL);
  
  	if (ret < 0)
-@@ -1302,10 +1536,15 @@
+@@ -1302,10 +1549,15 @@
  		struct child_control *ctl)
  {
  	struct header *hdr = &t->ack_header[qindex];
@@ -753,7 +772,7 @@
  	if (ret < 0)
  		return ret;
  	if (ret != opts->ack_size)
-@@ -1324,6 +1563,8 @@
+@@ -1324,6 +1576,8 @@
  		break;
  	}
  
@@ -762,7 +781,7 @@
  	return ret;
  }
  
-@@ -1354,8 +1595,49 @@
+@@ -1354,8 +1608,49 @@
  			struct child_control *ctl,
  			int can_send, int do_work)
  {
@@ -812,7 +831,7 @@
  	while (do_work && t->pending < opts->req_depth) {
  		if (!can_send)
  			goto eagain;
-@@ -1375,7 +1657,8 @@
+@@ -1375,7 +1670,8 @@
  		rds_rdma_cookie_t *cookie,
  		struct sockaddr_in *sin,
  		struct timeval *tstamp,
@@ -822,9 +841,13 @@
  {
  	struct cmsghdr *cmsg;
  	char cmsgbuf[256];
-@@ -1400,13 +1683,13 @@
+@@ -1398,15 +1694,16 @@
+ 
+ 	if (ret < 0)
  		return ret;
- 	if (ret && ret < sizeof(struct header))
+-	if (ret && ret < sizeof(struct header))
++	if (ret && !strcmp(RDS_VERSION, peer_version) &&
++		ret < sizeof(struct header))
  		die("recvmsg() returned short data: %zd", ret);
 -	if (msg.msg_namelen < sizeof(struct sockaddr_in))
 +	if (ret && msg.msg_namelen < sizeof(struct sockaddr_in))
@@ -838,7 +861,12 @@
  
  		if (cmsg->cmsg_level != sol)
  			continue;
-@@ -1436,7 +1719,7 @@
+@@ -1432,11 +1729,11 @@
+ 			memcpy(cookie, CMSG_DATA(cmsg), sizeof(*cookie));
+ 			break;
+ 
+-		case RDS_CMSG_RDMA_STATUS:
++		case RDS_CMSG_RDMA_SEND_STATUS:
  			if (cmsg->cmsg_len < CMSG_LEN(sizeof(notify)))
  				die("RDS_CMSG_RDMA_DEST data too small");
  			memcpy(&notify, CMSG_DATA(cmsg), sizeof(notify));
@@ -847,7 +875,7 @@
  			break;
  		}
  	}
-@@ -1445,7 +1728,8 @@
+@@ -1445,7 +1742,8 @@
  
  static int recv_one(int fd, struct task *tasks,
  			struct options *opts,
@@ -857,7 +885,7 @@
  {
  	char buf[max(opts->req_size, opts->ack_size)];
  	rds_rdma_cookie_t rdma_dest = 0;
-@@ -1456,15 +1740,18 @@
+@@ -1456,15 +1754,18 @@
  	uint16_t expect_index;
  	int task_index;
  	ssize_t ret;
@@ -878,7 +906,7 @@
  
  	/* check the incoming sequence number */
  	task_index = ntohs(sin.sin_port) - opts->starting_port - 1;
-@@ -1508,16 +1795,32 @@
+@@ -1508,16 +1809,32 @@
  	hdr.to_port = t->src_addr.sin_port;
  	hdr.index = expect_index;
  
@@ -918,7 +946,7 @@
  		if (in_hdr.rdma_key)
  			rdma_process_ack(fd, &in_hdr, ctl);
  	} else {
-@@ -1549,6 +1852,7 @@
+@@ -1549,6 +1866,7 @@
  }
  
  static void run_child(pid_t parent_pid, struct child_control *ctl,
@@ -926,7 +954,7 @@
  		      struct options *opts, uint16_t id, int active)
  {
  	struct sockaddr_in sin;
-@@ -1559,8 +1863,15 @@
+@@ -1559,8 +1877,15 @@
  	struct task tasks[opts->nr_tasks];
  	struct timeval start;
          int do_work = opts->simplex ? active : 1;
@@ -942,7 +970,7 @@
  	sin.sin_port = htons(opts->starting_port + 1 + id);
  	sin.sin_addr.s_addr = htonl(opts->receive_addr);
  
-@@ -1572,7 +1883,11 @@
+@@ -1572,7 +1897,11 @@
  	for (i = 0; i < opts->nr_tasks; i++) {
  		tasks[i].nr = i;
  		tasks[i].src_addr = sin;
@@ -954,7 +982,7 @@
  		tasks[i].dst_addr.sin_addr.s_addr = htonl(opts->send_addr);
  		tasks[i].dst_addr.sin_port = htons(opts->starting_port + 1 + i);
  		tasks[i].send_time = alloca(opts->req_depth * sizeof(struct timeval));
-@@ -1581,6 +1896,15 @@
+@@ -1581,6 +1910,15 @@
  		tasks[i].rdma_buf = alloca(opts->req_depth * sizeof(uint64_t *));
  		tasks[i].local_buf = alloca(opts->req_depth * sizeof(uint64_t *));
  		tasks[i].ack_header = alloca(opts->req_depth * sizeof(struct header));
@@ -970,7 +998,7 @@
  		tasks[i].rdma_next_op = (i & 1)? RDMA_OP_READ : RDMA_OP_WRITE;
  	}
  
-@@ -1611,7 +1935,7 @@
+@@ -1611,7 +1949,7 @@
  
  		check_parent(parent_pid);
  
@@ -979,7 +1007,7 @@
  		if (ret < 0) {
  			if (errno == EINTR)
  				continue;
-@@ -1621,10 +1945,14 @@
+@@ -1621,10 +1959,14 @@
  		pfd.events = POLLIN;
  
  		if (pfd.revents & POLLIN) {
@@ -995,7 +1023,7 @@
  		/* keep the pipeline full */
  		can_send = !!(pfd.revents & POLLOUT);
  		for (i = 0, t = tasks; i < opts->nr_tasks; i++, t++) {
-@@ -1633,6 +1961,7 @@
+@@ -1633,6 +1975,7 @@
  			if (t->drain_rdmas)
  				continue;
  			if (send_anything(fd, t, opts, ctl, can_send, do_work) < 0) {
@@ -1003,7 +1031,7 @@
  				pfd.events |= POLLOUT;
  
  				/* If the send queue is full, we will see EAGAIN.
-@@ -1665,8 +1994,12 @@
+@@ -1665,8 +2008,12 @@
  	uint32_t i;
  
  	len = opts->nr_tasks * sizeof(*ctl);
@@ -1016,7 +1044,7 @@
  	if (ctl == MAP_FAILED)
  		die("mmap of %u child control structs failed", opts->nr_tasks);
  
-@@ -1688,7 +2021,7 @@
+@@ -1688,7 +2035,7 @@
  				control_fd = -1;
  			}
  			rdma_key_o_meter_set_self(i);
@@ -1025,7 +1053,7 @@
  			exit(0);
  		}
  		ctl[i].pid = pid;
-@@ -1699,7 +2032,7 @@
+@@ -1699,7 +2046,7 @@
  			continue;
  		pid = waitpid(-1, NULL, WNOHANG);
  		if (pid)
@@ -1034,7 +1062,7 @@
  		sleep(1);
  		i--; /* try this child again */
  	}
-@@ -1823,6 +2156,7 @@
+@@ -1823,6 +2170,7 @@
  
  	if (disable)
  		return;
@@ -1042,7 +1070,7 @@
  	if ((fp = fopen("/proc/stat", "r")) == NULL) {
  		fprintf(stderr, "Cannot open /proc/stat (%s) - "
  				"not printing cpu stats\n",
-@@ -1856,10 +2190,37 @@
+@@ -1856,10 +2204,37 @@
  		}
  	}
  	fclose(fp);
@@ -1080,7 +1108,7 @@
  	} else {
  		struct sys_stats sys;
  		unsigned long sum = 0;
-@@ -1884,6 +2245,7 @@
+@@ -1884,6 +2259,7 @@
  		 *  5	irq
  		 *  6	softirq
  		 */
@@ -1088,7 +1116,7 @@
  		printf(",%f,%f,%f,%f,%Lu",
  			(sys.times[0] + sys.times[1]) * scale,
  			sys.times[2] * scale,
-@@ -1890,6 +2252,14 @@
+@@ -1890,6 +2266,14 @@
  			(sys.times[3] + sys.times[4]) * scale,
  			(sys.times[5] + sys.times[6]) * scale,
  			sys.intr);
@@ -1103,7 +1131,7 @@
  	}
  	prev = current;
  }
-@@ -1903,6 +2273,10 @@
+@@ -1903,6 +2287,10 @@
  	static socklen_t buflen = 0;
  	static int sock_fd = -1;
  	int i, count, item_size;
@@ -1114,7 +1142,7 @@
  
  	if (sock_fd < 0) {
  		sock_fd = socket(pf, SOCK_SEQPACKET, 0);
-@@ -1912,6 +2286,7 @@
+@@ -1912,6 +2300,7 @@
  
  	/* We should only loop once on the first call; after that the
  	 * buffer requirements for RDS counters should not change. */
@@ -1122,7 +1150,7 @@
  	while ((item_size = getsockopt(sock_fd, sol, RDS_INFO_COUNTERS, curr, &buflen)) < 0) {
  		if (errno != ENOSPC)
  			die_errno("getsockopt(RDS_INFO_COUNTERS) failed");
-@@ -1919,7 +2294,29 @@
+@@ -1919,7 +2308,29 @@
  		if (!curr)
  			die_errno("Cannot allocate buffer for stats counters");
  	}
@@ -1152,7 +1180,7 @@
  	if (item_size > sizeof(*ctr))
  		die("Bad counter item size in RDS_INFO_COUNTERS (got %d, max %zd)\n",
  				item_size, sizeof(*ctr));
-@@ -1932,8 +2329,11 @@
+@@ -1932,8 +2343,11 @@
  	}
  
  	for (i = 0; i < count; ++i)
@@ -1165,7 +1193,7 @@
  	gettimeofday(&now, NULL);
  
  	if (initialize) {
-@@ -1957,6 +2357,10 @@
+@@ -1957,6 +2371,10 @@
  	memcpy(prev, ctr, count * sizeof(*ctr));
  	last_ts = now;
  
@@ -1176,7 +1204,7 @@
  	get_stats(initialize);
  }
  
-@@ -1967,7 +2371,7 @@
+@@ -1967,7 +2385,7 @@
  
  	pid = waitpid(-1, &status, wflags);
  	if (pid < 0)
@@ -1185,7 +1213,7 @@
  	if (pid == 0)
  		return 0;
  
-@@ -1975,15 +2379,15 @@
+@@ -1975,15 +2393,15 @@
  		if (WEXITSTATUS(status) == 0)
  			return 1;
  		die("child pid %u exited with status %d\n",
@@ -1204,7 +1232,7 @@
  }
  
  static void release_children_and_wait(struct options *opts,
-@@ -1995,9 +2399,13 @@
+@@ -1995,9 +2413,13 @@
  	struct counter summary[NR_STATS];
  	struct timeval start, end, now, first_ts, last_ts;
  	double cpu_total = 0;
@@ -1219,7 +1247,7 @@
  	gettimeofday(&start, NULL);
  	start.tv_sec += 2;
  	for (i = 0; i < opts->nr_tasks; i++)
-@@ -2139,7 +2547,12 @@
+@@ -2139,7 +2561,12 @@
  	control_fd = -1;
  
  	if (nr_running) {
@@ -1232,7 +1260,7 @@
  			kill(ctl[i].pid, SIGTERM);
  		stop_soakers(soak_arr);
  	}
-@@ -2167,6 +2580,19 @@
+@@ -2167,6 +2594,19 @@
  			avg(&summary[S_SENDMSG_USECS]),
  			avg(&summary[S_RTT_USECS]),
  			soak_arr? scale * cpu_total : -1.0);
@@ -1252,27 +1280,60 @@
  	}
  }
  
-@@ -2262,6 +2688,9 @@
+@@ -2220,6 +2660,21 @@
+ {
+ 	ssize_t ret;
+ 
++	if (size == sizeof(struct options)) {
++		memset(ptr, 0, size);
++		ret = read(fd, peer_version, VERSION_MAX_LEN);
++		if (ret != VERSION_MAX_LEN)
++			die_errno("Failed to read version");
++
++		if (strcmp(peer_version, RDS_VERSION)) {
++			ptr += ret;
++			memcpy(ptr, peer_version, VERSION_MAX_LEN);
++			size = sizeof(struct options_2_0_6) - ret;
++		} else
++			size -= ret;
++		ptr += ret;
++	}
++
+ 	while (size) {
+ 		ret = read(fd, ptr, size);
+ 		if (ret < 0)
+@@ -2233,6 +2688,7 @@
+ 
+ static void encode_options(struct options *dst, const struct options *src)
+ {
++	memcpy(dst->version, src->version, VERSION_MAX_LEN);
+ 	dst->req_depth = htonl(src->req_depth);
+ 	dst->req_size = htonl(src->req_size);
+ 	dst->ack_size = htonl(src->ack_size);
+@@ -2262,10 +2718,13 @@
          dst->simplex = src->simplex;                    /* byte sized */
          dst->rw_mode = src->rw_mode;                    /* byte sized */
          dst->rdma_vector = htonl(src->rdma_vector);
 +	dst->tos = src->tos;
-+	dst->reset = src->reset;
 +	dst->async = src->async;
  }
  
  static void decode_options(struct options *dst, const struct options *src)
-@@ -2295,6 +2724,9 @@
+ {
++	memcpy(dst->version, src->version, VERSION_MAX_LEN);
+ 	dst->req_depth = ntohl(src->req_depth);
+ 	dst->req_size = ntohl(src->req_size);
+ 	dst->ack_size = ntohl(src->ack_size);
+@@ -2295,6 +2754,8 @@
          dst->simplex = src->simplex;                    /* byte sized */
          dst->rw_mode = src->rw_mode;                    /* byte sized */
  	dst->rdma_vector = ntohl(src->rdma_vector);
 +	dst->tos = src->tos;
-+	dst->reset = src->reset;
 +	dst->async = src->async;
  }
  
  static void verify_option_encdec(const struct options *opts)
-@@ -2316,6 +2748,30 @@
+@@ -2316,6 +2777,25 @@
  		die("encode/decode check of options struct failed");
  }
  
@@ -1289,13 +1350,8 @@
 +	fd = bound_socket(pf, SOCK_SEQPACKET, 0, &sin);
 +
 +	val.tos = opts->tos;
-+#if defined(__SVR4) && defined(__sun)
-+	val.src = htonl(opts->receive_addr);
-+	val.dst = htonl(opts->send_addr);
-+#else
 +	val.src.s_addr = htonl(opts->receive_addr);
 +	val.dst.s_addr = htonl(opts->send_addr);
-+#endif
 +	if (setsockopt(fd, sol, RDS_CONN_RESET, &val, sizeof(val)))
 +		die_errno("setsockopt RDS_CONN_RESET failed");
 +}
@@ -1303,11 +1359,11 @@
  static int active_parent(struct options *opts, struct soak_control *soak_arr)
  {
  	struct options enc_options;
-@@ -2324,6 +2780,11 @@
+@@ -2324,6 +2804,11 @@
  	int fd;
  	uint8_t ok;
  
-+	if (opts->reset) {
++	if (reset_connection) {
 +		reset_conn(opts);
 +		return 0;
 +	}
@@ -1315,7 +1371,20 @@
  	if (opts->show_params) {
  		unsigned int k;
  
-@@ -2517,7 +2978,11 @@
+@@ -2387,7 +2872,11 @@
+ 	 * We just tell the peer what options to use.
+ 	 */
+ 	encode_options(&enc_options, opts);
+-	peer_send(fd, &enc_options, sizeof(struct options));
++	if (opts->tos || opts->async)
++		peer_send(fd, &enc_options, sizeof(struct options));
++	else
++		peer_send(fd, &enc_options.req_depth,
++				sizeof(struct options_2_0_6));
+ 
+ 	printf("negotiated options, tasks will start in 2 seconds\n");
+ 	ctl = start_children(opts, 1);
+@@ -2517,7 +3006,11 @@
  	/* an extra terminating entry which will be all 0s */
  	len = (nr_soak + 1) * sizeof(struct soak_control);
  	soak_arr = mmap(NULL, len, PROT_READ|PROT_WRITE,
@@ -1327,7 +1396,7 @@
  	if (soak_arr == MAP_FAILED)
  		die("mmap of %ld soak control structs failed", nr_soak);
  
-@@ -2572,6 +3037,10 @@
+@@ -2572,6 +3065,10 @@
  	OPT_CONNECT_RETRIES,
  	OPT_USE_CONG_MONITOR,
  	OPT_PERFDATA,
@@ -1338,7 +1407,7 @@
  };
  
  static struct option long_options[] = {
-@@ -2584,11 +3053,13 @@
+@@ -2584,11 +3081,13 @@
  { "send-addr",		required_argument,	NULL,	's'	},
  { "port",		required_argument,	NULL,	'p'	},
  { "time",		required_argument,	NULL,	'T'	},
@@ -1352,7 +1421,7 @@
  
  { "rdma-use-once",	required_argument,	NULL,	OPT_RDMA_USE_ONCE },
  { "rdma-use-get-mr",	required_argument,	NULL,	OPT_RDMA_USE_GET_MR },
-@@ -2601,6 +3072,10 @@
+@@ -2601,6 +3100,10 @@
  { "show-perfdata",	no_argument,		NULL,	OPT_PERFDATA },
  { "connect-retries",	required_argument,	NULL,	OPT_CONNECT_RETRIES },
  { "use-cong-monitor",	required_argument,	NULL,	OPT_USE_CONG_MONITOR },
@@ -1363,7 +1432,7 @@
  
  { NULL }
  };
-@@ -2640,6 +3115,8 @@
+@@ -2640,6 +3143,8 @@
  	opts.use_cong_monitor = 1;
  	opts.rdma_use_fence = 1;
  	opts.rdma_cache_mrs = 0;
@@ -1372,15 +1441,16 @@
  	opts.rdma_alignment = 0;
  	opts.rdma_key_o_meter = 0;
  	opts.show_params = 0;
-@@ -2648,11 +3125,16 @@
+@@ -2648,11 +3153,17 @@
          opts.simplex = 0;
          opts.rw_mode = 0;
  	opts.rdma_vector = 1;
 +        rtt_threshold = ~0U;
 +        show_histogram = 0;
 +	opts.tos = 0;
-+	opts.reset = 0;
++	reset_connection = 0;
 +	opts.async = 0;
++	strcpy(opts.version, RDS_VERSION);
  
  	while(1) {
  		int c, index;
@@ -1390,7 +1460,7 @@
  				long_options, &index);
  		if (c == -1)
  			break;
-@@ -2702,6 +3184,9 @@
+@@ -2702,6 +3213,9 @@
  			case 'T':
  				opts.run_time = parse_ull(optarg, (uint32_t)~0);
  				break;
@@ -1400,7 +1470,7 @@
  			case 'z':
  				opts.summary_only = 1;
  				break;
-@@ -2711,9 +3196,25 @@
+@@ -2711,9 +3225,25 @@
  			case 'V':
  				opts.tracing = 1;
  				break;
@@ -1418,7 +1488,7 @@
  				opts.use_cong_monitor = parse_ull(optarg, 1);
  				break;
 +			case OPT_RESET:
-+				opts.reset = 1;
++				reset_connection = 1;
 +				break;
 +			case OPT_ASYNC:
 +				opts.async = 1;
@@ -1426,7 +1496,7 @@
  			case OPT_RDMA_USE_ONCE:
  				opts.rdma_use_once = parse_ull(optarg, 1);
  				break;
-@@ -2786,6 +3287,7 @@
+@@ -2786,6 +3316,7 @@
  	if (opts.rdma_size && 0)
  		opts.rdma_size = (opts.rdma_size + 4095) & ~4095;
  
@@ -1493,7 +1563,71 @@
  /* Like inet_ntoa, but can be re-entered several times without clobbering
   * the previously returned string. */
  static const char *paddr(int af, const void *addrp)
-@@ -234,8 +250,10 @@
+@@ -134,18 +150,20 @@
+ {
+ 	struct rds_info_connection conn;
+ 
+-	printf("\nRDS Connections:\n%15s %15s %16s %16s %3s\n",
+-		"LocalAddr", "RemoteAddr", "NextTX", "NextRX", "Flg");
++	printf("\nRDS Connections:\n%15s %15s %4s %16s %16s %4s\n",
++		"LocalAddr", "RemoteAddr", "Tos", "NextTX", "NextRX", "Flgs");
+ 	
+ 	for_each(conn, data, each, len) {
+-		printf("%15s %15s %16"PRIu64" %16"PRIu64" %c%c%c\n",
++		printf("%15s %15s %4u %16"PRIu64" %16"PRIu64" %c%c%c%c\n",
+ 			ipv4addr(conn.laddr),
+ 			ipv4addr(conn.faddr),
++			conn.tos,
+ 			conn.next_tx_seq,
+ 			conn.next_rx_seq,
+ 			rds_conn_flag(conn, SENDING, 's'),
+ 			rds_conn_flag(conn, CONNECTING, 'c'),
+-			rds_conn_flag(conn, CONNECTED, 'C'));
++			rds_conn_flag(conn, CONNECTED, 'C'),
++			rds_conn_flag(conn, ERROR, 'E'));
+ 	}
+ }
+ 
+@@ -153,16 +171,17 @@
+ {
+ 	struct rds_info_message msg;
+ 
+-	printf("\n%s Message Queue:\n%15s %5s %15s %5s %16s %10s\n",
++	printf("\n%s Message Queue:\n%15s %5s %15s %5s %4s %16s %10s\n",
+ 		(char *)extra,
+-		"LocalAddr", "LPort", "RemoteAddr", "RPort", "Seq", "Bytes");
++		"LocalAddr", "LPort", "RemoteAddr", "RPort", "Tos","Seq", "Bytes");
+ 	
+ 	for_each(msg, data, each, len) {
+-		printf("%15s %5u %15s %5u %16"PRIu64" %10u\n",
++		printf("%15s %5u %15s %5u %4u %16"PRIu64" %10u\n",
+ 			ipv4addr(msg.laddr),
+ 			ntohs(msg.lport),
+ 			ipv4addr(msg.faddr),
+ 			ntohs(msg.fport),
++			msg.tos,
+ 			msg.seq, msg.len);
+ 	}
+ }
+@@ -191,13 +210,14 @@
+ {
+ 	struct rds_info_rdma_connection ic;
+ 
+-	printf("\nRDS IB Connections:\n%15s %15s %32s %32s\n",
+-		"LocalAddr", "RemoteAddr", "LocalDev", "RemoteDev");
++	printf("\nRDS IB Connections:\n%15s %15s %4s %3s %32s %32s\n",
++		"LocalAddr", "RemoteAddr", "Tos", "SL", "LocalDev", "RemoteDev");
+ 
+ 	for_each(ic, data, each, len) {
+-		printf("%15s %15s %32s %32s",
++		printf("%15s %15s %4u %3u %32s %32s",
+ 			ipv4addr(ic.src_addr),
+ 			ipv4addr(ic.dst_addr),
++			ic.tos,ic.sl,
+ 			ipv6addr(ic.src_gid),
+ 			ipv6addr(ic.dst_gid));
+ 
+@@ -234,8 +254,10 @@
  		print_msgs, "Send", 0 },
  	['t'] = { RDS_INFO_RETRANS_MESSAGES, "retransmit queue messages",
  		  print_msgs, "Retransmit", 0 },
@@ -1504,7 +1638,7 @@
  	['I'] = { RDS_INFO_IB_CONNECTIONS, "IB transport connections",
  		  print_ib_conns, NULL, 0 },
  };
-@@ -266,6 +284,9 @@
+@@ -266,6 +288,9 @@
  	char optstring[258] = "v+";
  	int given_options = 0;
  	socklen_t len = 0;
@@ -1514,7 +1648,7 @@
  	void *data = NULL;
  	int fd;
  	int each;
-@@ -322,6 +343,7 @@
+@@ -322,6 +347,7 @@
  		    (given_options && !infos[i].option_given))
  			continue;
  
@@ -1522,7 +1656,7 @@
  		/* read in the info until we get a full snapshot */
  		while ((each = getsockopt(fd, sol, infos[i].opt_val, data,
  				   &len)) < 0) {
-@@ -345,15 +367,47 @@
+@@ -345,15 +371,47 @@
  				return 1;
  			}
  		}
@@ -1674,7 +1808,7 @@
 diff -r -u /tmp/rds-tools-2.0.4/rds-info.1 rds-tools-2.0.7/rds-info.1
 --- /tmp/rds-tools-2.0.4/rds-info.1	Wed Aug  4 15:25:11 2010
 +++ rds-tools-2.0.7/rds-info.1	Thu Feb 24 13:27:51 2011
-@@ -1,162 +1,150 @@
+@@ -1,162 +1,160 @@
 -.Dd October 30, 2006
 -.Dt RDS-INFO 1
 -.Os
@@ -1777,6 +1911,8 @@
 +.IP	RemoteAddr
  The IP address of the remote end of the connection.  
 -.It NextTX
++.IP	Tos
++The type of service value for this connection.
 +.IP	NextTX
  The sequence number that will be given to the next message that is sent
  over the connection.
@@ -1808,6 +1944,8 @@
 +.IP 		C
 +	The connection to the remote host is connected
 +	and active.
++.IP 		E
++	The connection to the remote host is in error.
 +
 +.TP
 +\fB\-r\fR, \fB\-s\fR, \fB\-t\fR
@@ -1824,6 +1962,8 @@
  The remote IP address and port associated with the message. For sent messages
  this is the destination address, for receive messages it is the source address.
 -.It Seq
++.IP	Tos
++The type of service for this message.
 +.IP	Seq
  The sequence number of the message.
 -.It Bytes
@@ -1850,6 +1990,10 @@
 +.IP	RemoteAddr
  The remote IP address of this connection.
 -.It LocalDev
++.IP	Tos
++The type of service value for this connection.
++.IP	SL
++The QoS Service Level for this connection.
 +.IP	LocalDev
  The local IB Global Identifier, printed in IPv6 address syntax.
 -.It RemoteDev
@@ -1903,7 +2047,7 @@
 diff -r -u /tmp/rds-tools-2.0.4/rds-ping.1 rds-tools-2.0.7/rds-ping.1
 --- /tmp/rds-tools-2.0.4/rds-ping.1	Wed Aug  4 15:25:11 2010
 +++ rds-tools-2.0.7/rds-ping.1	Thu Feb 24 13:27:52 2011
-@@ -1,69 +1,54 @@
+@@ -1,69 +1,63 @@
 -.Dd Apr 22, 2008
 -.Dt RDS-PING 1
 -.Os
@@ -1928,7 +2072,11 @@
 -Its interface is designed to operate pretty much the standard
 -.Xr ping 8
 +.SH SYNOPSIS
-+.B rds-ping [-c count] [-i interval] [-I local_addr] remote_addr
++.HP
++.nf
++rds-ping [-c count] [-Q tos] [-i interval] [-I local_addr]
++    remote_addr
++.fi
 +
 +.SH DESCRIPTION
 +.PP
@@ -1961,6 +2109,11 @@
 -.Nm rds-ping
 -will pick the local source address for the RDS socket based
 +.TP
++\fB\-Q tos
++By default, rds-ping sends the ping requests on base (tos = 0) RDS connection.
++With this option, the requests are sent on RDS connection with the specified tos
++value.  Valid values are 0-255.
++.TP
 +\fB\-I address
 +By default, rds-ping will pick the local source address for the RDS socket based
  on routing information for the destination address (i.e. if
@@ -2021,10 +2174,11 @@
 diff -r -u /tmp/rds-tools-2.0.4/rds-ping.c rds-tools-2.0.7/rds-ping.c
 --- /tmp/rds-tools-2.0.4/rds-ping.c	Wed Aug  4 15:25:10 2010
 +++ rds-tools-2.0.7/rds-ping.c	Thu Feb 24 13:27:52 2011
-@@ -48,7 +48,11 @@
+@@ -48,7 +48,12 @@
  #include <sys/poll.h>
  #include <fcntl.h>
  #include <getopt.h>
++#include <sys/ioctl.h>
 +#if defined(__SVR4) && defined(__sun)
 +#include <sys/rds.h>
 +#else
@@ -2033,7 +2187,58 @@
  
  #include "pfhack.h"
  
-@@ -155,7 +159,12 @@
+@@ -67,6 +72,7 @@
+ static unsigned long	opt_count;
+ static struct in_addr	opt_srcaddr;
+ static struct in_addr	opt_dstaddr;
++static uint8_t		opt_tos = 0;
+ 
+ /* For reasons of simplicity, RDS ping does not use a packet
+  * payload that is being echoed, the way ICMP does.
+@@ -91,6 +97,7 @@
+ static int	parse_timeval(const char *, struct timeval *);
+ static int	parse_long(const char *ptr, unsigned long *);
+ static int	parse_addr(const char *ptr, struct in_addr *);
++static unsigned long long	parse_ull(char *ptr, unsigned long long max);
+ 
+ int
+ main(int argc, char **argv)
+@@ -97,7 +104,7 @@
+ {
+ 	int c;
+ 
+-	while ((c = getopt(argc, argv, "c:i:I:")) != -1) {
++	while ((c = getopt(argc, argv, "c:i:I:Q:")) != -1) {
+ 		switch (c) {
+ 		case 'c':
+ 			if (!parse_long(optarg, &opt_count))
+@@ -114,6 +121,9 @@
+ 				die("Bad wait time <%s>\n", optarg);
+ 			break;
+ 
++		case 'Q':
++			opt_tos = parse_ull(optarg, 255);
++			break;
+ 		default:
+ 			usage("Unknown option");
+ 		}
+@@ -142,6 +152,9 @@
+ 	struct timeval	next_ts;
+ 	struct socket	socket[NSOCKETS];
+ 	struct pollfd	pfd[NSOCKETS];
++#if !(defined(__SVR4) && defined(__sun))
++	int             pending[NSOCKETS];
++#endif
+ 	int		i, next = 0;
+ 
+ 	for (i = 0; i < NSOCKETS; ++i) {
+@@ -152,10 +165,18 @@
+ 		socket[i].fd = fd;
+ 		pfd[i].fd = fd;
+ 		pfd[i].events = POLLIN;
++#if !(defined(__SVR4) && defined(__sun))
++		pending[i] = 0;
++#endif
  	}
  
  	memset(&sin, 0, sizeof(sin));
@@ -2046,16 +2251,57 @@
  	sin.sin_addr = opt_dstaddr;
  
  	gettimeofday(&next_ts, NULL);
-@@ -181,7 +190,7 @@
+@@ -180,14 +201,32 @@
+ 			if (opt_count && sent >= opt_count)
  				break;
  
- 			timeradd(&next_ts, &opt_wait, &next_ts);
+-			timeradd(&next_ts, &opt_wait, &next_ts);
 -			if (sendto(sp->fd, NULL, 0, 0, (struct sockaddr *) &sin, sizeof(sin)))
-+			if (sendto(sp->fd, NULL, 0, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0)
- 				err = errno;
- 			sp->sent_id = ++sent;
- 			sp->sent_ts = now;
-@@ -258,7 +267,11 @@
+-				err = errno;
+-			sp->sent_id = ++sent;
+-			sp->sent_ts = now;
+-			sp->nreplies = 0;
+-			next = (next + 1) % NSOCKETS;
++			timeradd(&now, &opt_wait, &next_ts);
++#if !(defined(__SVR4) && defined(__sun))
++			if (!pending[next]) {
++#endif
++				memset(&sin, 0, sizeof(sin));
++#if defined(__SVR4) && defined(__sun)
++				sin.sin_family = AF_INET_OFFLOAD;
++#else
++				sin.sin_family = AF_INET;
++#endif
++				sin.sin_addr = opt_dstaddr;
+ 
++				if (sendto(sp->fd, NULL, 0, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0)
++					err = errno;
++				sp->sent_id = ++sent;
++				sp->sent_ts = now;
++				sp->nreplies = 0;
++#if !(defined(__SVR4) && defined(__sun))
++				if (!err)
++					pending[next] = 1;
++#endif
++				next = (next + 1) % NSOCKETS;
++#if !(defined(__SVR4) && defined(__sun))
++			}
++#endif
++
+ 			if (err) {
+ 				static unsigned int nerrs = 0;
+ 
+@@ -223,6 +262,9 @@
+ 					report_packet(sp, &now, NULL, errno);
+ 			} else {
+ 				report_packet(sp, &now, &from.sin_addr, 0);
++#if !(defined(__SVR4) && defined(__sun))
++				pending[i] = 0;
++#endif
+ 				recv++;
+ 			}
+ 		}
+@@ -258,7 +300,11 @@
  	int pf;
  
  	memset(&sin, 0, sizeof(sin));
@@ -2067,7 +2313,7 @@
  
  #ifdef DYNAMIC_PF_RDS
          pf = discover_pf_rds();
-@@ -278,6 +291,9 @@
+@@ -278,6 +324,9 @@
  		if (ufd < 0)
  			die_errno("unable to create UDP socket");
  		sin.sin_addr = *dst;
@@ -2077,7 +2323,7 @@
  		sin.sin_port = htons(1);
  		if (connect(ufd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
  			die_errno("unable to connect to %s",
-@@ -289,6 +305,9 @@
+@@ -289,6 +338,9 @@
  
  		*src = sin.sin_addr;
  		close(ufd);
@@ -2087,6 +2333,58 @@
  	}
  
  	sin.sin_addr = *src;
+@@ -297,6 +349,9 @@
+ 	if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)))
+ 		die_errno("bind() failed");
+ 
++	if (opt_tos && ioctl(fd, SIOCRDSSETTOS, &opt_tos)) 
++		die_errno("ERROR: failed to set TOS\n");
++
+ 	return fd;
+ }
+ 
+@@ -309,7 +364,8 @@
+ 		"%s\nUsage: rds-ping [options] dst_addr\n"
+ 		"Options:\n"
+ 		" -c count      limit packet count\n"
+-		" -I interface  source IP address\n",
++		" -I interface  source IP address\n"
++		" -Q tos	type of service\n",
+ 		complaint);
+ 	exit(1);
+ }
+@@ -384,3 +440,31 @@
+ 	return 0;
+ }
+ 
++static unsigned long long parse_ull(char *ptr, unsigned long long max)
++{
++	unsigned long long val;
++	char *endptr;
++
++	val = strtoull(ptr, &endptr, 0);
++	switch (*endptr) {
++	case 'k': case 'K':
++		val <<= 10;
++		endptr++;
++		break;
++
++	case 'm': case 'M':
++		val <<= 20;
++		endptr++;
++		break;
++
++	case 'g': case 'G':
++		val <<= 30;
++		endptr++;
++		break;
++	}
++
++	if (*ptr && !*endptr && val <= max)
++		return val;
++
++	die("invalid number '%s'\n", ptr);
++}
 diff -r -u /tmp/rds-tools-2.0.4/Makefile.in rds-tools-2.0.7/Makefile.in
 --- /tmp/rds-tools-2.0.4/Makefile.in	Wed Aug  4 15:25:11 2010
 +++ rds-tools-2.0.7/Makefile.in	Thu Feb 24 13:27:51 2011
@@ -2271,7 +2569,7 @@
 +.nf
 +rds-stress [-p port_number] -r [receive_address] [-s send_address]
 +      [-Q tos] [-a ack_bytes] [-q request_bytes] [-D rdma_bytes]
-+      [-d queue_depth] [-t nr_tasks] [-c] [-R] [-V] [-v]
++      [-d queue_depth] [-t nr_tasks] [-T time] [-c] [-R] [-V] [-v]
 +.fi
  
 -.Sh DESCRIPTION
@@ -2374,7 +2672,7 @@
 +.TP
 +\fB\-Q tos
 +Uses the RDS connection between IP addresses with the specified tos value. By 
-+default, the base (tos = 0) RDS connection is used.
++default, the base (tos = 0) RDS connection is used.  Valid values are 0-255.
 +.TP
 +\fB\-a ack_bytes
  This specifies the size of the ack messages, in bytes. There is a minimum size