xref: /illumos-gate/usr/src/cmd/rpcsvc/spray.c (revision 4f364e7c95ee7fd9d5bbeddc1940e92405bb0e72)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <rpc/rpc.h>
43 #include <rpcsvc/spray.h>
44 #include <sys/poll.h>
45 
46 enum clnt_stat sprayproc_spray_1nd(/*argp, clnt*/);
47 
48 #define	DEFBYTES	100000	/* default numbers of bytes to send */
49 #define	MAXPACKETLEN	1514
50 #define	SPRAYOVERHEAD	86	/* size of rpc packet when size=0 */
51 
52 static void slp(int usecs);
53 static void usage(void);
54 
55 int
56 main(int argc, char *argv[])
57 {
58 	int		c;
59 	extern char	*optarg;
60 	extern int	optind;
61 	register CLIENT *clnt;
62 	unsigned int	i;
63 	int		delay = 0;
64 	unsigned int	psec, bsec;
65 	int		buf[SPRAYMAX/4];
66 	char		msgbuf[256];
67 	unsigned int	lnth, cnt;
68 	sprayarr	arr;
69 	spraycumul	cumul;
70 	spraycumul	*co;
71 	char		*host = NULL;
72 	char		*type;
73 
74 	if (argc < 2)
75 		usage();
76 
77 	cnt = 0;
78 	lnth = SPRAYOVERHEAD;
79 	type = "netpath";
80 	while (optind < argc) {
81 		if (argv[optind][0] == '-') {
82 			if ((c = getopt(argc, argv, "d:c:t:l:")) == EOF) {
83 				break;
84 			}
85 			switch (c) {
86 				case 'd':
87 					delay = atoi(optarg);
88 					break;
89 				case 'c':
90 					cnt = (unsigned int) atoi(optarg);
91 					break;
92 				case 't':
93 					type = optarg;
94 					break;
95 				case 'l':
96 					lnth = (unsigned int) atoi(optarg);
97 					break;
98 				default:
99 					usage();
100 			}
101 		} else {
102 			host = argv[optind++];
103 		}
104 	}
105 	if (host == NULL)
106 		usage();
107 	clnt = clnt_create(host, SPRAYPROG, SPRAYVERS, type);
108 	if (clnt == (CLIENT *)NULL) {
109 		sprintf(msgbuf, "spray: cannot clnt_create %s:%s", host, type);
110 		clnt_pcreateerror(msgbuf);
111 		exit(1);
112 	}
113 	if (cnt == 0)
114 		cnt = DEFBYTES/lnth;
115 	if (lnth < SPRAYOVERHEAD)
116 		lnth = SPRAYOVERHEAD;
117 	else if (lnth >= SPRAYMAX)
118 		lnth = SPRAYMAX;
119 	if (lnth <= MAXPACKETLEN && lnth % 4 != 2)
120 		lnth = ((lnth + 5) / 4) * 4 - 2;
121 	arr.sprayarr_len = lnth - SPRAYOVERHEAD;
122 	arr.sprayarr_val = (char *)buf;
123 	printf("sending %u packets of length %u to %s ...", cnt, lnth, host);
124 	fflush(stdout);
125 	if (sprayproc_clear_1(NULL, clnt) == NULL) {
126 		clnt_perror(clnt, "SPRAYPROC_CLEAR ");
127 		exit(1);
128 	}
129 	for (i = 0; i < cnt; i++) {
130 		sprayproc_spray_1nd(&arr, clnt);
131 		if (delay > 0)
132 			slp(delay);
133 	}
134 	if ((co = sprayproc_get_1(NULL, clnt)) == NULL) {
135 		clnt_perror(clnt, "SPRAYPROC_GET ");
136 		exit(1);
137 	}
138 	cumul = *co;
139 	if (cumul.counter < cnt)
140 		printf("\n\t%d packets (%.3f%%) dropped by %s\n",
141 			cnt - cumul.counter,
142 			100.0 * (cnt - cumul.counter)/cnt, host);
143 	else
144 		printf("\n\tno packets dropped by %s\n", host);
145 	psec = (1000000.0 * cumul.counter)
146 		/ (1000000.0 * cumul.clock.sec + cumul.clock.usec);
147 	bsec = (lnth * 1000000.0 * cumul.counter)/
148 		(1000000.0 * cumul.clock.sec + cumul.clock.usec);
149 	printf("\t%u packets/sec, %u bytes/sec\n", psec, bsec);
150 	exit(0);
151 	/* NOTREACHED */
152 }
153 
154 /*
155  * A special call, where the TIMEOUT is 0. So, every call times-out.
156  */
157 static struct timeval TIMEOUT = { 0, 0 };
158 
159 enum clnt_stat
160 sprayproc_spray_1nd(argp, clnt)
161 	sprayarr *argp;
162 	CLIENT *clnt;
163 {
164 	return (clnt_call(clnt, SPRAYPROC_SPRAY, xdr_sprayarr, (caddr_t)argp,
165 			xdr_void, NULL, TIMEOUT));
166 }
167 
168 /* A cheap milliseconds sleep call */
169 static void
170 slp(usecs)
171 {
172 	static struct pollfd pfds[1] = {
173 		0, POLLIN, 0
174 	};
175 	pfds[0].fd = fileno(stdout);
176 	poll(pfds, 1, usecs/1000);
177 }
178 
179 static void
180 usage()
181 {
182 	printf("spray host [-t nettype] [-l lnth] [-c cnt] [-d delay]\n");
183 	exit(1);
184 }
185