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
main(int argc,char * argv[])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
sprayproc_spray_1nd(argp,clnt)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
slp(usecs)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
usage()180 usage()
181 {
182 printf("spray host [-t nettype] [-l lnth] [-c cnt] [-d delay]\n");
183 exit(1);
184 }
185