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