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
main(int argc,char * argv[])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
sprayproc_spray_1nd(sprayarr * argp,CLIENT * clnt)158 sprayproc_spray_1nd(sprayarr *argp, CLIENT *clnt)
159 {
160 return (clnt_call(clnt, SPRAYPROC_SPRAY, xdr_sprayarr, (caddr_t)argp,
161 xdr_void, NULL, TIMEOUT));
162 }
163
164 /* A cheap milliseconds sleep call */
165 static void
slp(int usecs)166 slp(int usecs)
167 {
168 static struct pollfd pfds[1] = {
169 0, POLLIN, 0
170 };
171 pfds[0].fd = fileno(stdout);
172 poll(pfds, 1, usecs/1000);
173 }
174
175 static void
usage()176 usage()
177 {
178 printf("spray host [-t nettype] [-l lnth] [-c cnt] [-d delay]\n");
179 exit(1);
180 }
181