xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/syncstat.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
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 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Display synchronous serial line statistics
31  */
32 
33 #include <sys/types.h>
34 #include <ctype.h>
35 #include <unistd.h>
36 #include <sys/ioctl.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <sys/stream.h>
41 #include <sys/stropts.h>
42 #include <fcntl.h>
43 #include <sys/ser_sync.h>
44 #include <libdlpi.h>
45 
46 #define	MAXWAIT 15
47 
48 static struct scc_mode sm;
49 static struct sl_stats st;
50 
51 static void usage(void);
52 static void sample(int count, int period);
53 
54 /*
55  * errstr is MAXPATHLEN + 11; 11 = 10 for "syncstat: " + null
56  */
57 static char errstr[11 + MAXPATHLEN] = "syncstat: /dev/";
58 static char *ifdevice = errstr + 10;
59 static char *ifname = errstr + 15;
60 static int fd;
61 
62 int
63 main(int argc, char **argv)
64 {
65 	int len;
66 	char *cp;
67 	int do_clear = 0;
68 	int period = 0;
69 	int isize, osize;
70 	int count;
71 	struct strioctl sioc;
72 	ulong_t ppa;
73 
74 	if (argc == 1) {
75 		usage();
76 		exit(1);
77 	}
78 	argc--;				/* skip the command name */
79 	argv++;
80 
81 	/*
82 	 * The following loop processes command line arguments.
83 	 * If the argument begins with a '-', it is trated as an option.
84 	 * The only option currently implemented is "-c" (clears statistics).
85 	 * If the argument begins with a numeral, it is treated as an interval.
86 	 * Intervals must be positive integers greater than zero.
87 	 * Any argument that survives this is treated as a device name to be
88 	 * found under /dev.
89 	 */
90 	while (argc > 0) {
91 		if (argv[0][0] == '-') {
92 			if (argc == 1) {
93 				usage();
94 				exit(1);
95 			}
96 			if (argv[0][1] != 'c') {
97 				usage();
98 				exit(1);
99 			}
100 			do_clear = 1;
101 		} else if ((argv[0][0] >= '0') && (argv[0][0] <= '9')) {
102 			period = atoi(*argv);
103 			if (period == 0) {
104 				(void) fprintf(stderr,
105 					"syncstat: bad interval: %s\n", *argv);
106 				exit(1);
107 			}
108 		} else {
109 			len = sizeof (errstr) - strlen(errstr);
110 			if (snprintf(ifname, len, "%s", *argv) >= len) {
111 				(void) fprintf(stderr,
112 				    "syncstat: invalid device name "
113 				    "(too long) %s\n", *argv);
114 				    exit(1);
115 			}
116 		}
117 		argc--;
118 		argv++;
119 	}
120 
121 	for (cp = ifname; (*cp) && (!isdigit(*cp)); cp++) {}
122 	if (*cp == '\0') {	/* hit the end without finding a number */
123 		(void) fprintf(stderr,
124 			"syncstat: %s missing minor device number\n", ifname);
125 		exit(1);
126 	}
127 	ppa = strtoul(cp, NULL, 10);
128 	*cp = '\0';	/* drop number, leaving name of clone device. */
129 	fd = open(ifdevice, O_RDWR);
130 	if (fd < 0) {
131 		perror(errstr);
132 		exit(1);
133 	}
134 
135 	if (dlpi_attach(fd, MAXWAIT, ppa) != 0) {
136 		perror("syncstat: dlpi_attach");
137 		exit(1);
138 	}
139 
140 	(void) printf("syncstat: control device: %s, ppa=%ld\n", ifdevice, ppa);
141 
142 	sioc.ic_cmd = S_IOCGETMODE;
143 	sioc.ic_timout = -1;
144 	sioc.ic_len = sizeof (struct scc_mode);
145 	sioc.ic_dp = (char *)&sm;
146 	if (ioctl(fd, I_STR, &sioc) < 0) {
147 		perror("S_IOCGETMODE");
148 		(void) fprintf(stderr,
149 			"syncstat: can't get sync mode info for %s\n",
150 			ifname);
151 		exit(1);
152 	}
153 	if (do_clear) {
154 		sioc.ic_cmd = S_IOCCLRSTATS;
155 		sioc.ic_timout = -1;
156 		sioc.ic_len = sizeof (struct sl_stats);
157 		sioc.ic_dp = (char *)&st;
158 		if (ioctl(fd, I_STR, &sioc) < 0) {
159 			perror("S_IOCCLRSTATS");
160 			(void) fprintf(stderr,
161 				"syncstat: can't clear stats for %s\n",
162 				ifname);
163 			exit(1);
164 		}
165 	}
166 
167 	sioc.ic_cmd = S_IOCGETSTATS;
168 	sioc.ic_timout = -1;
169 	sioc.ic_len = sizeof (struct sl_stats);
170 	sioc.ic_dp = (char *)&st;
171 	if (ioctl(fd, I_STR, &sioc) < 0) {
172 		perror("S_IOCGETSTATS");
173 		(void) fprintf(stderr, "syncstat: can't get stats for %s\n",
174 			ifname);
175 		exit(1);
176 	}
177 	if (period) {
178 		if (sm.sm_baudrate == 0) {
179 			(void) fprintf(stderr, "syncstat: baud rate not set\n");
180 			exit(1);
181 		}
182 		for (count = 0; ; count++) {
183 			(void) fflush(stdout);
184 			(void) sleep(period);
185 			sample(count, period);
186 		}
187 	}
188 	isize = osize = 0;
189 	if (st.opack)
190 		osize = st.ochar / st.opack;
191 	if (st.ipack)
192 		isize = st.ichar / st.ipack;
193 	(void) printf(
194 "    speed   ipkts   opkts  undrun  ovrrun   abort     crc   isize   osize\n");
195 	(void) printf(" %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
196 		sm.sm_baudrate,
197 		st.ipack,
198 		st.opack,
199 		st.underrun,
200 		st.overrun,
201 		st.abort,
202 		st.crc,
203 		isize, osize);
204 	return (0);
205 }
206 
207 static void
208 sample(int count, int period)
209 {
210 	struct sl_stats nst;
211 	struct strioctl sioc;
212 	int iutil, outil;
213 
214 	sioc.ic_cmd = S_IOCGETSTATS;
215 	sioc.ic_timout = -1;
216 	sioc.ic_len = sizeof (struct sl_stats);
217 	sioc.ic_dp = (char *)&nst;
218 	if (ioctl(fd, I_STR, &sioc) < 0) {
219 		perror("S_IOCGETSTATS");
220 		(void) fprintf(stderr, "syncstat: can't get stats for %s\n",
221 			ifname);
222 		exit(1);
223 	}
224 
225 	st.ipack = nst.ipack - st.ipack;
226 	st.opack = nst.opack - st.opack;
227 	st.ichar = nst.ichar - st.ichar;
228 	st.ochar = nst.ochar - st.ochar;
229 	st.crc = nst.crc - st.crc;
230 	st.overrun = nst.overrun - st.overrun;
231 	st.underrun = nst.underrun - st.underrun;
232 	st.abort = nst.abort - st.abort;
233 	iutil = 8 * st.ichar / period;
234 	iutil = 100 * iutil / sm.sm_baudrate;
235 	outil = 8 * st.ochar / period;
236 	outil = 100 * outil / sm.sm_baudrate;
237 	if ((count % 20) == 0) (void) printf(
238 "    ipkts   opkts  undrun  ovrrun   abort     crc   iutil   outil\n");
239 	(void) printf(" %7d %7d %7d %7d %7d %7d %6d%% %6d%%\n",
240 		st.ipack,
241 		st.opack,
242 		st.underrun,
243 		st.overrun,
244 		st.abort,
245 		st.crc,
246 		iutil, outil);
247 
248 	st = nst;
249 }
250 
251 static void
252 usage()
253 {
254 	(void) fprintf(stderr, "%s\n",
255 		"Usage: syncstat [-c] device [period]");
256 }
257