xref: /illumos-gate/usr/src/cmd/rpcsvc/spray.c (revision ddb365bfc9e868ad24ccdcb0dc91af18b10df082)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27 /*
28  * University Copyright- Copyright (c) 1982, 1986, 1988
29  * The Regents of the University of California
30  * All Rights Reserved
31  *
32  * University Acknowledgment- Portions of this document are derived from
33  * software developed by the University of California, Berkeley, and its
34  * contributors.
35  */
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <rpc/rpc.h>
41 #include <rpcsvc/spray.h>
42 #include <sys/poll.h>
43 
44 enum clnt_stat sprayproc_spray_1nd(/*argp, clnt*/);
45 
46 #define	DEFBYTES	100000	/* default numbers of bytes to send */
47 #define	MAXPACKETLEN	1514
48 #define	SPRAYOVERHEAD	86	/* size of rpc packet when size=0 */
49 
50 static void slp(int usecs);
51 static void usage(void);
52 
53 int
54 main(int argc, char *argv[])
55 {
56 	int		c;
57 	extern char	*optarg;
58 	extern int	optind;
59 	register CLIENT *clnt;
60 	unsigned int	i;
61 	int		delay = 0;
62 	unsigned int	psec, bsec;
63 	int		buf[SPRAYMAX/4];
64 	char		msgbuf[256];
65 	unsigned int	lnth, cnt;
66 	sprayarr	arr;
67 	spraycumul	cumul;
68 	spraycumul	*co;
69 	char		*host = NULL;
70 	char		*type;
71 
72 	if (argc < 2)
73 		usage();
74 
75 	cnt = 0;
76 	lnth = SPRAYOVERHEAD;
77 	type = "netpath";
78 	while (optind < argc) {
79 		if (argv[optind][0] == '-') {
80 			if ((c = getopt(argc, argv, "d:c:t:l:")) == EOF) {
81 				break;
82 			}
83 			switch (c) {
84 				case 'd':
85 					delay = atoi(optarg);
86 					break;
87 				case 'c':
88 					cnt = (unsigned int) atoi(optarg);
89 					break;
90 				case 't':
91 					type = optarg;
92 					break;
93 				case 'l':
94 					lnth = (unsigned int) atoi(optarg);
95 					break;
96 				default:
97 					usage();
98 			}
99 		} else {
100 			host = argv[optind++];
101 		}
102 	}
103 	if (host == NULL)
104 		usage();
105 	clnt = clnt_create(host, SPRAYPROG, SPRAYVERS, type);
106 	if (clnt == (CLIENT *)NULL) {
107 		sprintf(msgbuf, "spray: cannot clnt_create %s:%s", host, type);
108 		clnt_pcreateerror(msgbuf);
109 		exit(1);
110 	}
111 	if (cnt == 0)
112 		cnt = DEFBYTES/lnth;
113 	if (lnth < SPRAYOVERHEAD)
114 		lnth = SPRAYOVERHEAD;
115 	else if (lnth >= SPRAYMAX)
116 		lnth = SPRAYMAX;
117 	if (lnth <= MAXPACKETLEN && lnth % 4 != 2)
118 		lnth = ((lnth + 5) / 4) * 4 - 2;
119 	arr.sprayarr_len = lnth - SPRAYOVERHEAD;
120 	arr.sprayarr_val = (char *)buf;
121 	printf("sending %u packets of length %u to %s ...", cnt, lnth, host);
122 	fflush(stdout);
123 	if (sprayproc_clear_1(NULL, clnt) == NULL) {
124 		clnt_perror(clnt, "SPRAYPROC_CLEAR ");
125 		exit(1);
126 	}
127 	for (i = 0; i < cnt; i++) {
128 		sprayproc_spray_1nd(&arr, clnt);
129 		if (delay > 0)
130 			slp(delay);
131 	}
132 	if ((co = sprayproc_get_1(NULL, clnt)) == NULL) {
133 		clnt_perror(clnt, "SPRAYPROC_GET ");
134 		exit(1);
135 	}
136 	cumul = *co;
137 	if (cumul.counter < cnt)
138 		printf("\n\t%d packets (%.3f%%) dropped by %s\n",
139 			cnt - cumul.counter,
140 			100.0 * (cnt - cumul.counter)/cnt, host);
141 	else
142 		printf("\n\tno packets dropped by %s\n", host);
143 	psec = (1000000.0 * cumul.counter)
144 		/ (1000000.0 * cumul.clock.sec + cumul.clock.usec);
145 	bsec = (lnth * 1000000.0 * cumul.counter)/
146 		(1000000.0 * cumul.clock.sec + cumul.clock.usec);
147 	printf("\t%u packets/sec, %u bytes/sec\n", psec, bsec);
148 	exit(0);
149 	/* NOTREACHED */
150 }
151 
152 /*
153  * A special call, where the TIMEOUT is 0. So, every call times-out.
154  */
155 static struct timeval TIMEOUT = { 0, 0 };
156 
157 enum clnt_stat
158 sprayproc_spray_1nd(argp, clnt)
159 	sprayarr *argp;
160 	CLIENT *clnt;
161 {
162 	return (clnt_call(clnt, SPRAYPROC_SPRAY, xdr_sprayarr, (caddr_t)argp,
163 			xdr_void, NULL, TIMEOUT));
164 }
165 
166 /* A cheap milliseconds sleep call */
167 static void
168 slp(usecs)
169 {
170 	static struct pollfd pfds[1] = {
171 		0, POLLIN, 0
172 	};
173 	pfds[0].fd = fileno(stdout);
174 	poll(pfds, 1, usecs/1000);
175 }
176 
177 static void
178 usage()
179 {
180 	printf("spray host [-t nettype] [-l lnth] [-c cnt] [-d delay]\n");
181 	exit(1);
182 }
183