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 }