8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppstats / pppstats.c
blobb29c7a80d4d2b88604563bba26490875e1e5c58e
1 /*
2 * print PPP statistics:
3 * pppstats [-a|-d] [-v|-r|-z] [-c count] [-w wait] [interface]
5 * -a Show absolute values rather than deltas
6 * -d Show data rate (kB/s) rather than bytes
7 * -v Show more stats for VJ TCP header compression
8 * -r Show compression ratio
9 * -z Show compression statistics instead of default display
11 * History:
12 * perkins@cps.msu.edu: Added compression statistics and alternate
13 * display. 11/94
14 * Brad Parker (brad@cayman.com) 6/92
16 * from the original "slstats" by Van Jacobson
18 * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
19 * All rights reserved.
21 * Copyright (c) 1989 Regents of the University of California.
22 * All rights reserved.
24 * Redistribution and use in source and binary forms are permitted
25 * provided that the above copyright notice and this paragraph are
26 * duplicated in all such forms and that any documentation,
27 * advertising materials, and other materials related to such
28 * distribution and use acknowledge that the software was developed
29 * by the University of California, Berkeley. The name of the
30 * University may not be used to endorse or promote products derived
31 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
34 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
37 #ifndef __STDC__
38 #define const
39 #endif
41 #pragma ident "%Z%%M% %I% %E% SMI"
43 #ifndef lint
44 static const char rcsid[] = "$Id: pppstats.c,v 1.27 1999/08/13 06:46:23 paulus Exp $";
45 #endif
47 #include <stdio.h>
48 #include <stddef.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <errno.h>
53 #include <signal.h>
54 #include <fcntl.h>
55 #include <unistd.h>
56 #include <sys/param.h>
57 #include <sys/types.h>
58 #include <sys/ioctl.h>
60 #ifndef STREAMS
61 #if defined(_linux_) && defined(__powerpc__) \
62 && (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
63 /* kludge alert! */
64 #undef __GLIBC__
65 #endif
66 #include <sys/socket.h> /* *BSD, Linux, NeXT, Ultrix etc. */
67 #ifndef _linux_
68 #include <net/if.h>
69 #include <net/ppp_defs.h>
70 #include <net/if_ppp.h>
71 #else
72 /* Linux */
73 #if __GLIBC__ >= 2
74 #include <asm/types.h> /* glibc 2 conflicts with linux/types.h */
75 #include <net/if.h>
76 #else
77 #include <linux/types.h>
78 #include <linux/if.h>
79 #endif
80 #include <linux/ppp_defs.h>
81 #include <linux/if_ppp.h>
82 #endif /* _linux_ */
84 #else /* STREAMS */
85 #include <sys/stropts.h> /* SVR4, Solaris 2, SunOS 4, OSF/1, etc. */
86 #include <net/ppp_defs.h>
87 #include <net/pppio.h>
89 #ifdef PPPIO_GETSTAT64
90 #define ppp_stats64 ppp_stats64
91 #endif
92 #endif /* STREAMS */
94 #ifndef ppp_stats64
95 #define ppp_stats64 ppp_stats
96 #endif
98 static int vflag, rflag, zflag; /* select type of display */
99 static int aflag; /* print absolute values, not deltas */
100 static int dflag; /* print data rates, not bytes */
101 static int interval, count;
102 static int infinite;
103 static int unit;
104 static int s; /* socket or /dev/ppp file descriptor */
105 static int signalled; /* set if alarm goes off "early" */
106 static char *progname;
107 static char *interface;
109 #if defined(SUNOS4) || defined(ULTRIX) || defined(NeXT)
110 extern int optind;
111 extern char *optarg;
112 #endif
115 * If PPP_DRV_NAME is not defined, use the legacy "ppp" as the
116 * device name.
118 #if !defined(PPP_DRV_NAME)
119 #define PPP_DRV_NAME "ppp"
120 #endif /* !defined(PPP_DRV_NAME) */
122 static void usage __P((void));
123 static void catchalarm __P((int));
124 static void get_ppp_stats __P((struct ppp_stats64 *));
125 static void get_ppp_cstats __P((struct ppp_comp_stats *));
126 static void intpr __P((void));
128 int main __P((int, char *argv[]));
130 static void
131 usage()
133 (void) fprintf(stderr,
134 "Usage: %s [-a|-d] [-v|-r|-z] [-c count] [-w wait] [interface]\n",
135 progname);
136 exit(1);
140 * Called if an interval expires before intpr has completed a loop.
141 * Sets a flag to not wait for the alarm.
143 /* ARGSUSED */
144 static void
145 catchalarm(arg)
146 int arg;
148 signalled = 1;
152 #ifndef STREAMS
153 static void
154 get_ppp_stats(curp)
155 struct ppp_stats64 *curp;
157 struct ifpppstatsreq req;
159 (void) memset (&req, 0, sizeof (req));
161 #ifdef _linux_
162 req.stats_ptr = (caddr_t) &req.stats;
163 #undef ifr_name
164 #define ifr_name ifr__name
165 #endif
167 strncpy(req.ifr_name, interface, sizeof(req.ifr_name));
168 if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
169 (void) fprintf(stderr, "%s: ", progname);
170 if (errno == ENOTTY)
171 (void) fprintf(stderr, "kernel support missing\n");
172 else
173 perror("couldn't get PPP statistics");
174 exit(1);
176 *curp = req.stats;
179 static void
180 get_ppp_cstats(csp)
181 struct ppp_comp_stats *csp;
183 struct ifpppcstatsreq creq;
185 (void) memset (&creq, 0, sizeof (creq));
187 #ifdef _linux_
188 creq.stats_ptr = (caddr_t) &creq.stats;
189 #undef ifr_name
190 #define ifr_name ifr__name
191 #endif
193 strncpy(creq.ifr_name, interface, sizeof(creq.ifr_name));
194 if (ioctl(s, SIOCGPPPCSTATS, &creq) < 0) {
195 (void) fprintf(stderr, "%s: ", progname);
196 if (errno == ENOTTY) {
197 (void) fprintf(stderr, "no kernel compression support\n");
198 if (zflag)
199 exit(1);
200 rflag = 0;
201 } else {
202 perror("couldn't get PPP compression stats");
203 exit(1);
207 #ifdef _linux_
208 if (creq.stats.c.bytes_out == 0) {
209 creq.stats.c.bytes_out = creq.stats.c.comp_bytes + creq.stats.c.inc_bytes;
210 creq.stats.c.in_count = creq.stats.c.unc_bytes;
212 if (creq.stats.c.bytes_out == 0)
213 creq.stats.c.ratio = 0.0;
214 else
215 creq.stats.c.ratio = 256.0 * creq.stats.c.in_count /
216 creq.stats.c.bytes_out;
218 if (creq.stats.d.bytes_out == 0) {
219 creq.stats.d.bytes_out = creq.stats.d.comp_bytes + creq.stats.d.inc_bytes;
220 creq.stats.d.in_count = creq.stats.d.unc_bytes;
222 if (creq.stats.d.bytes_out == 0)
223 creq.stats.d.ratio = 0.0;
224 else
225 creq.stats.d.ratio = 256.0 * creq.stats.d.in_count /
226 creq.stats.d.bytes_out;
227 #endif
229 *csp = creq.stats;
232 #else /* STREAMS */
234 static int
235 strioctl(fd, cmd, ptr, ilen, olen)
236 int fd, cmd, ilen, olen;
237 char *ptr;
239 struct strioctl str;
241 str.ic_cmd = cmd;
242 str.ic_timout = 0;
243 str.ic_len = ilen;
244 str.ic_dp = ptr;
245 if (ioctl(fd, I_STR, &str) == -1)
246 return -1;
247 if (str.ic_len != olen)
248 (void) fprintf(stderr,
249 "strioctl: expected %d bytes, got %d for cmd %x\n",
250 olen, str.ic_len, cmd);
251 return 0;
254 static void
255 get_ppp_stats(curp)
256 struct ppp_stats64 *curp;
258 #ifdef PPPIO_GETSTAT64
259 struct ppp_stats oldstat;
260 if (strioctl(s, PPPIO_GETSTAT64, (char *)curp, 0, sizeof(*curp)) >= 0)
261 return;
262 if (strioctl(s, PPPIO_GETSTAT, (char *)&oldstat, 0, sizeof(oldstat)) >= 0) {
263 curp->p.ppp_ibytes = oldstat.p.ppp_ibytes;
264 curp->p.ppp_ipackets = oldstat.p.ppp_ipackets;
265 curp->p.ppp_ierrors = oldstat.p.ppp_ierrors;
266 curp->p.ppp_obytes = oldstat.p.ppp_obytes;
267 curp->p.ppp_opackets = oldstat.p.ppp_opackets;
268 curp->p.ppp_oerrors = oldstat.p.ppp_oerrors;
269 curp->vj = oldstat.vj;
270 return;
272 #else
273 if (strioctl(s, PPPIO_GETSTAT, (char *)curp, 0, sizeof(*curp)) >= 0)
274 return;
275 #endif
277 (void) fprintf(stderr, "%s: ", progname);
278 if (errno == EINVAL)
279 (void) fprintf(stderr, "kernel support missing\n");
280 else
281 perror("couldn't get PPP statistics");
282 exit(1);
285 static void
286 get_ppp_cstats(csp)
287 struct ppp_comp_stats *csp;
289 if (strioctl(s, PPPIO_GETCSTAT, (char *)csp, 0, sizeof(*csp)) < 0) {
290 (void) fprintf(stderr, "%s: ", progname);
291 if (errno == ENOTTY) {
292 (void) fprintf(stderr, "no kernel compression support\n");
293 if (zflag)
294 exit(1);
295 rflag = 0;
296 } else {
297 perror("couldn't get PPP compression statistics");
298 exit(1);
303 #endif /* STREAMS */
305 #define MAX0(a) ((int)(a) > 0? (a): 0)
306 #define V(offset) MAX0(cur.offset - old.offset)
307 #define W(offset) MAX0(ccs.offset - ocs.offset)
309 #define RATIO(c, i, u) ((c) == 0? 1.0: (u) / ((double)(c) + (i)))
310 #define CRATE(x) RATIO(W(x.comp_bytes), W(x.inc_bytes), W(x.unc_bytes))
312 #define KBPS(n) ((n) / (interval * 1000.0))
315 * Print a running summary of interface statistics.
316 * Repeat display every interval seconds, showing statistics
317 * collected over that interval. Assumes that interval is non-zero.
318 * First line printed is cumulative.
320 static void
321 intpr()
323 register int line = 0;
324 sigset_t oldmask, mask;
325 char *bunit;
326 int ratef = 0;
327 struct ppp_stats64 cur, old;
328 struct ppp_comp_stats ccs, ocs;
330 (void) memset(&old, 0, sizeof(old));
331 (void) memset(&ocs, 0, sizeof(ocs));
333 for (;;) {
334 get_ppp_stats(&cur);
335 if (zflag || rflag)
336 get_ppp_cstats(&ccs);
338 (void)signal(SIGALRM, catchalarm);
339 signalled = 0;
340 (void)alarm(interval);
342 if ((line % 20) == 0) {
343 if (zflag) {
344 (void) printf("IN: COMPRESSED INCOMPRESSIBLE COMP | ");
345 (void) printf("OUT: COMPRESSED INCOMPRESSIBLE COMP\n");
346 bunit = dflag? "KB/S": "BYTE";
347 (void) printf(" %s PACK %s PACK RATIO | ", bunit,
348 bunit);
349 (void) printf(" %s PACK %s PACK RATIO", bunit,
350 bunit);
351 } else {
352 (void) printf("%8.8s %6.6s %6.6s",
353 "IN", "PACK", "VJCOMP");
355 if (!rflag)
356 (void) printf(" %6.6s %6.6s", "VJUNC", "VJERR");
357 if (vflag)
358 (void) printf(" %6.6s %6.6s", "VJTOSS", "NON-VJ");
359 if (rflag)
360 (void) printf(" %6.6s %6.6s", "RATIO", "UBYTE");
361 (void) printf(" | %8.8s %6.6s %6.6s",
362 "OUT", "PACK", "VJCOMP");
364 if (!rflag)
365 (void) printf(" %6.6s %6.6s", "VJUNC", "NON-VJ");
366 if (vflag)
367 (void) printf(" %6.6s %6.6s", "VJSRCH", "VJMISS");
368 if (rflag)
369 (void) printf(" %6.6s %6.6s", "RATIO", "UBYTE");
371 (void) putchar('\n');
374 if (zflag) {
375 if (ratef) {
376 (void) printf("%8.3f %6u %8.3f %6u %6.2f",
377 KBPS(W(d.comp_bytes)),
378 W(d.comp_packets),
379 KBPS(W(d.inc_bytes)),
380 W(d.inc_packets),
381 ccs.d.ratio / 256.0);
382 (void) printf(" | %8.3f %6u %8.3f %6u %6.2f",
383 KBPS(W(c.comp_bytes)),
384 W(c.comp_packets),
385 KBPS(W(c.inc_bytes)),
386 W(c.inc_packets),
387 ccs.c.ratio / 256.0);
388 } else {
389 (void) printf("%8u %6u %8u %6u %6.2f",
390 W(d.comp_bytes),
391 W(d.comp_packets),
392 W(d.inc_bytes),
393 W(d.inc_packets),
394 ccs.d.ratio / 256.0);
395 (void) printf(" | %8u %6u %8u %6u %6.2f",
396 W(c.comp_bytes),
397 W(c.comp_packets),
398 W(c.inc_bytes),
399 W(c.inc_packets),
400 ccs.c.ratio / 256.0);
403 } else {
404 if (ratef)
405 (void) printf("%8.3f", KBPS(V(p.ppp_ibytes)));
406 else
407 (void) printf("%8" PPP_COUNTER_F, V(p.ppp_ibytes));
408 (void) printf(" %6" PPP_COUNTER_F " %6u",
409 V(p.ppp_ipackets),
410 V(vj.vjs_compressedin));
411 if (!rflag)
412 (void) printf(" %6u %6u",
413 V(vj.vjs_uncompressedin),
414 V(vj.vjs_errorin));
415 if (vflag)
416 (void) printf(" %6u %6" PPP_COUNTER_F,
417 V(vj.vjs_tossed),
418 V(p.ppp_ipackets) - V(vj.vjs_compressedin)
419 - V(vj.vjs_uncompressedin) - V(vj.vjs_errorin));
420 if (rflag) {
421 (void) printf(" %6.2f ", CRATE(d));
422 if (ratef)
423 (void) printf("%6.2f", KBPS(W(d.unc_bytes)));
424 else
425 (void) printf("%6u", W(d.unc_bytes));
427 if (ratef)
428 (void) printf(" | %8.3f", KBPS(V(p.ppp_obytes)));
429 else
430 (void) printf(" | %8" PPP_COUNTER_F, V(p.ppp_obytes));
431 (void) printf(" %6" PPP_COUNTER_F " %6u",
432 V(p.ppp_opackets),
433 V(vj.vjs_compressed));
434 if (!rflag)
435 (void) printf(" %6u %6" PPP_COUNTER_F,
436 V(vj.vjs_packets) - V(vj.vjs_compressed),
437 V(p.ppp_opackets) - V(vj.vjs_packets));
438 if (vflag)
439 (void) printf(" %6u %6u",
440 V(vj.vjs_searches),
441 V(vj.vjs_misses));
442 if (rflag) {
443 (void) printf(" %6.2f ", CRATE(c));
444 if (ratef)
445 (void) printf("%6.2f", KBPS(W(c.unc_bytes)));
446 else
447 (void) printf("%6u", W(c.unc_bytes));
452 (void) putchar('\n');
453 (void) fflush(stdout);
454 line++;
456 count--;
457 if (!infinite && !count)
458 break;
460 (void) sigemptyset(&mask);
461 (void) sigaddset(&mask, SIGALRM);
462 (void) sigprocmask(SIG_BLOCK, &mask, &oldmask);
463 if (!signalled) {
464 (void) sigemptyset(&mask);
465 (void) sigsuspend(&mask);
467 (void) sigprocmask(SIG_SETMASK, &oldmask, NULL);
468 signalled = 0;
469 (void)alarm(interval);
471 if (!aflag) {
472 old = cur;
473 ocs = ccs;
474 ratef = dflag;
480 main(argc, argv)
481 int argc;
482 char *argv[];
484 int c;
485 #ifdef STREAMS
486 char *dev;
487 #endif
489 interface = PPP_DRV_NAME "0";
490 if ((progname = strrchr(argv[0], '/')) == NULL)
491 progname = argv[0];
492 else
493 ++progname;
495 while ((c = getopt(argc, argv, "advrzc:w:")) != -1) {
496 switch (c) {
497 case 'a':
498 ++aflag;
499 break;
500 case 'd':
501 ++dflag;
502 break;
503 case 'v':
504 ++vflag;
505 break;
506 case 'r':
507 ++rflag;
508 break;
509 case 'z':
510 ++zflag;
511 break;
512 case 'c':
513 count = atoi(optarg);
514 if (count <= 0)
515 usage();
516 break;
517 case 'w':
518 interval = atoi(optarg);
519 if (interval <= 0)
520 usage();
521 break;
522 default:
523 usage();
526 argc -= optind;
527 argv += optind;
529 if (!interval && count)
530 interval = 5;
531 if (interval && !count)
532 infinite = 1;
533 if (!interval && !count)
534 count = 1;
535 if (aflag)
536 dflag = 0;
538 if (argc > 1)
539 usage();
540 if (argc > 0)
541 interface = argv[0];
543 if (sscanf(interface, PPP_DRV_NAME "%d", &unit) != 1) {
544 (void) fprintf(stderr, "%s: invalid interface '%s' specified\n",
545 progname, interface);
548 #ifndef STREAMS
550 struct ifreq ifr;
552 s = socket(AF_INET, SOCK_DGRAM, 0);
553 if (s < 0) {
554 (void) fprintf(stderr, "%s: ", progname);
555 perror("couldn't create IP socket");
556 exit(1);
559 #ifdef _linux_
560 #undef ifr_name
561 #define ifr_name ifr_ifrn.ifrn_name
562 #endif
563 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
564 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
565 (void) fprintf(stderr, "%s: nonexistent interface '%s' specified\n",
566 progname, interface);
567 exit(1);
571 #else /* STREAMS */
572 #ifdef __osf__
573 dev = "/dev/streams/ppp";
574 #else
575 dev = "/dev/" PPP_DRV_NAME;
576 #endif
577 if ((s = open(dev, O_RDONLY)) < 0) {
578 (void) fprintf(stderr, "%s: couldn't open ", progname);
579 perror(dev);
580 exit(1);
582 if (strioctl(s, PPPIO_ATTACH, (char *)&unit, sizeof(int), 0) < 0) {
583 (void) fprintf(stderr, "%s: " PPP_DRV_NAME "%d is not available\n",
584 progname, unit);
585 exit(1);
588 #endif /* STREAMS */
590 intpr();
591 return (0);