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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Display synchronous serial line statistics 28 */ 29 30 #include <sys/types.h> 31 #include <ctype.h> 32 #include <unistd.h> 33 #include <sys/ioctl.h> 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <sys/stream.h> 38 #include <sys/stropts.h> 39 #include <fcntl.h> 40 #include <sys/ser_sync.h> 41 #include <libdlpi.h> 42 43 static struct scc_mode sm; 44 static struct sl_stats st; 45 46 static void usage(void); 47 static void sample(int count, int period); 48 49 static char sername[DLPI_LINKNAME_MAX]; 50 static int fd; 51 52 int 53 main(int argc, char **argv) 54 { 55 char *cp; 56 char serdevice[DLPI_LINKNAME_MAX]; 57 int do_clear = 0; 58 int period = 0; 59 int isize, osize; 60 int count; 61 int retval; 62 struct strioctl sioc; 63 uint_t ppa; 64 dlpi_handle_t dh; 65 66 if (argc == 1) { 67 usage(); 68 exit(1); 69 } 70 argc--; /* skip the command name */ 71 argv++; 72 73 /* 74 * The following loop processes command line arguments. 75 * If the argument begins with a '-', it is trated as an option. 76 * The only option currently implemented is "-c" (clears statistics). 77 * If the argument begins with a numeral, it is treated as an interval. 78 * Intervals must be positive integers greater than zero. 79 * Any argument that survives this is treated as a device name to be 80 * found under /dev. 81 */ 82 while (argc > 0) { 83 if (argv[0][0] == '-') { 84 if (argc == 1) { 85 usage(); 86 exit(1); 87 } 88 if (argv[0][1] != 'c') { 89 usage(); 90 exit(1); 91 } 92 do_clear = 1; 93 } else if ((argv[0][0] >= '0') && (argv[0][0] <= '9')) { 94 period = atoi(*argv); 95 if (period == 0) { 96 (void) fprintf(stderr, 97 "syncstat: bad interval: %s\n", *argv); 98 exit(1); 99 } 100 } else { 101 if (snprintf(sername, sizeof (sername), "%s", 102 *argv) >= sizeof (sername)) { 103 (void) fprintf(stderr, "syncstat: invalid " 104 "device name (too long) %s\n", *argv); 105 exit(1); 106 } 107 } 108 argc--; 109 argv++; 110 } 111 112 for (cp = sername; (*cp) && (!isdigit(*cp)); cp++) {} 113 if (*cp == '\0') { /* hit the end without finding a number */ 114 (void) fprintf(stderr, 115 "syncstat: %s missing minor device number\n", sername); 116 exit(1); 117 } 118 119 if ((retval = dlpi_open(sername, &dh, DLPI_SERIAL)) != DLPI_SUCCESS) { 120 (void) fprintf(stderr, "syncstat: dlpi_open %s: %s\n", sername, 121 dlpi_strerror(retval)); 122 exit(1); 123 } 124 125 (void) dlpi_parselink(sername, serdevice, &ppa); 126 (void) printf("syncstat: control device: %s, ppa=%u\n", serdevice, ppa); 127 128 fd = dlpi_fd(dh); 129 sioc.ic_cmd = S_IOCGETMODE; 130 sioc.ic_timout = -1; 131 sioc.ic_len = sizeof (struct scc_mode); 132 sioc.ic_dp = (char *)&sm; 133 if (ioctl(fd, I_STR, &sioc) < 0) { 134 perror("S_IOCGETMODE"); 135 (void) fprintf(stderr, 136 "syncstat: can't get sync mode info for %s\n", sername); 137 exit(1); 138 } 139 if (do_clear) { 140 sioc.ic_cmd = S_IOCCLRSTATS; 141 sioc.ic_timout = -1; 142 sioc.ic_len = sizeof (struct sl_stats); 143 sioc.ic_dp = (char *)&st; 144 if (ioctl(fd, I_STR, &sioc) < 0) { 145 perror("S_IOCCLRSTATS"); 146 (void) fprintf(stderr, 147 "syncstat: can't clear stats for %s\n", sername); 148 exit(1); 149 } 150 } 151 152 sioc.ic_cmd = S_IOCGETSTATS; 153 sioc.ic_timout = -1; 154 sioc.ic_len = sizeof (struct sl_stats); 155 sioc.ic_dp = (char *)&st; 156 if (ioctl(fd, I_STR, &sioc) < 0) { 157 perror("S_IOCGETSTATS"); 158 (void) fprintf(stderr, "syncstat: can't get stats for %s\n", 159 sername); 160 exit(1); 161 } 162 if (period) { 163 if (sm.sm_baudrate == 0) { 164 (void) fprintf(stderr, "syncstat: baud rate not set\n"); 165 exit(1); 166 } 167 for (count = 0; ; count++) { 168 (void) fflush(stdout); 169 (void) sleep(period); 170 sample(count, period); 171 } 172 } 173 isize = osize = 0; 174 if (st.opack) 175 osize = st.ochar / st.opack; 176 if (st.ipack) 177 isize = st.ichar / st.ipack; 178 (void) printf(" speed ipkts opkts undrun ovrrun abort " 179 "crc isize osize\n"); 180 (void) printf(" %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", sm.sm_baudrate, 181 st.ipack, st.opack, st.underrun, st.overrun, st.abort, st.crc, 182 isize, osize); 183 return (0); 184 } 185 186 static void 187 sample(int count, int period) 188 { 189 struct sl_stats nst; 190 struct strioctl sioc; 191 int iutil, outil; 192 193 sioc.ic_cmd = S_IOCGETSTATS; 194 sioc.ic_timout = -1; 195 sioc.ic_len = sizeof (struct sl_stats); 196 sioc.ic_dp = (char *)&nst; 197 if (ioctl(fd, I_STR, &sioc) < 0) { 198 perror("S_IOCGETSTATS"); 199 (void) fprintf(stderr, "syncstat: can't get stats for %s\n", 200 sername); 201 exit(1); 202 } 203 204 st.ipack = nst.ipack - st.ipack; 205 st.opack = nst.opack - st.opack; 206 st.ichar = nst.ichar - st.ichar; 207 st.ochar = nst.ochar - st.ochar; 208 st.crc = nst.crc - st.crc; 209 st.overrun = nst.overrun - st.overrun; 210 st.underrun = nst.underrun - st.underrun; 211 st.abort = nst.abort - st.abort; 212 iutil = 8 * st.ichar / period; 213 iutil = 100 * iutil / sm.sm_baudrate; 214 outil = 8 * st.ochar / period; 215 outil = 100 * outil / sm.sm_baudrate; 216 if ((count % 20) == 0) 217 (void) printf(" ipkts opkts undrun ovrrun abort " 218 "crc iutil outil\n"); 219 (void) printf(" %7d %7d %7d %7d %7d %7d %6d%% %6d%%\n", st.ipack, 220 st.opack, st.underrun, st.overrun, st.abort, st.crc, iutil, outil); 221 222 st = nst; 223 } 224 225 static void 226 usage() 227 { 228 (void) fprintf(stderr, "Usage: syncstat [-c] device [period]\n"); 229 } 230