xref: /netbsd/usr.sbin/altq/altqstat/altqstat.c (revision bf9ec67e)
1 /*	$NetBSD: altqstat.c,v 1.5 2002/03/05 04:11:52 itojun Exp $	*/
2 /*	$KAME: altqstat.c,v 1.7 2001/11/19 09:14:22 kjc Exp $	*/
3 /*
4  * Copyright (C) 1999-2000
5  *	Sony Computer Science Laboratories, Inc.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/fcntl.h>
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <err.h>
40 #ifndef NO_CURSES
41 #include <curses.h>
42 #endif
43 
44 #include "quip_client.h"
45 #include "altqstat.h"
46 
47 #define DEV_PATH	"/dev/altq"
48 
49 int qdiscfd = -1;
50 int show_config = 0;
51 int interval = 5;
52 int no_server = 0;
53 char *interface = NULL;
54 char *qdisc_name = NULL;
55 
56 stat_loop_t *stat_loop;
57 
58 static void sig_handler(int);
59 static void usage(void);
60 
61 static void
62 sig_handler(int sig)
63 {
64 	char buf[8192];
65 
66 	snprintf(buf, sizeof buf, "Exiting on signal %d\n", sig);
67 	write(STDERR_FILENO, buf, strlen(buf));
68 
69 #ifndef NO_CURSES
70 	/* XXX signal race */
71 	if (qdisc_name != NULL && strcmp(qdisc_name, "wfq") == 0)
72 		endwin();	/* wfqstat uses curses */
73 #endif
74 	_exit(0);
75 }
76 
77 static void
78 usage(void)
79 {
80 	fprintf(stderr, "usage: altqstat [-enrs] [-c count] [-w wait] [-i interface|-I input_interface]\n");
81 	exit(1);
82 }
83 
84 int
85 main (int argc, char **argv)
86 {
87 	int ch, raw_mode = 0;
88 	int qtype;
89 	int count = 0;
90 	char device[64], qname[64], input[32];
91 
92 	while ((ch = getopt(argc, argv, "I:c:ei:nrsw:")) != -1) {
93 		switch (ch) {
94 		case 'I':
95 			snprintf(input, sizeof(input), "_%s", optarg);
96 			interface = input;
97 			break;
98 		case 'c':
99 			count = atoi(optarg);
100 			break;
101 		case 'e':
102 			quip_echo = 1;
103 			break;
104 		case 'i':
105 			interface = optarg;
106 			break;
107 		case 'n':
108 			no_server = 1;
109 			break;
110 		case 'r':
111 			raw_mode = 1;
112 			quip_echo = 1;
113 			break;
114 		case 's':
115 			show_config = 1;
116 			break;
117 		case 'w':
118 			interval = atoi(optarg);
119 			break;
120 		default:
121 			usage();
122 			break;
123 		}
124 	}
125 
126 	signal(SIGINT, sig_handler);
127 	signal(SIGTERM, sig_handler);
128 	signal(SIGPIPE, sig_handler);
129 
130 	if (no_server == 0) {
131 		if (quip_openserver() < 0 && interface == NULL)
132 			errx(1, "you have to specify interface!");
133 	}
134 
135 	if (raw_mode == 1) {
136 		quip_rawmode();
137 		quip_closeserver();
138 		exit(0);
139 	}
140 
141 	if (show_config) {
142 		if (no_server)
143 			errx(1, "no server (-n) can't be set for show config (-s)!");
144 		quip_printconfig();
145 		quip_closeserver();
146 		exit(0);
147 	}
148 
149 	interface = quip_selectinterface(interface);
150 	if (interface == NULL)
151 		errx(1, "no interface found!");
152 
153 	qtype = ifname2qdisc(interface, qname);
154 	if (qtype == 0)
155 		errx(1, "altq is not attached on %s!", interface);
156 
157 	qdisc_name = qname;
158 
159 	stat_loop = qdisc2stat_loop(qdisc_name);
160 	if (stat_loop == NULL)
161 		errx(1, "qdisc %s is not supported!", qdisc_name);
162 
163 	printf("%s: %s on interface %s\n",
164 	       argv[0], qdisc_name, interface);
165 
166 	snprintf(device, sizeof(device), "%s/%s", DEV_PATH, qdisc_name);
167 	if ((qdiscfd = open(device, O_RDONLY)) < 0)
168 		err(1, "can't open %s", device);
169 
170 	(*stat_loop)(qdiscfd, interface, count, interval);
171 	/* never returns */
172 
173 	exit(0);
174 }
175 
176 /* calculate interval in sec */
177 double
178 calc_interval(struct timeval *cur_time, struct timeval *last_time)
179 {
180 	double sec;
181 
182 	sec = (double)(cur_time->tv_sec - last_time->tv_sec) +
183 	    (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000;
184 	return (sec);
185 }
186 
187 
188 /* calculate rate in bps */
189 double
190 calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval)
191 {
192 	double rate;
193 
194 	rate = (double)(new_bytes - last_bytes) * 8 / interval;
195 	return (rate);
196 }
197 
198 /* calculate packets in second */
199 double
200 calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval)
201 {
202 	double pps;
203 
204 	pps = (double)(new_pkts - last_pkts) / interval;
205 	return (pps);
206 }
207 
208 #define	R2S_BUFS	8
209 #define	RATESTR_MAX	16
210 char *
211 rate2str(double rate)
212 {
213 	char *buf;
214 	static char r2sbuf[R2S_BUFS][RATESTR_MAX];  /* ring bufer */
215 	static int idx = 0;
216 
217 	buf = r2sbuf[idx++];
218 	if (idx == R2S_BUFS)
219 		idx = 0;
220 
221 	if (rate == 0.0)
222 		snprintf(buf, RATESTR_MAX, "0");
223 	else if (rate >= 1000000.0)
224 		snprintf(buf, RATESTR_MAX, "%.2fM", rate / 1000000.0);
225 	else
226 		snprintf(buf, RATESTR_MAX, "%.2fK", rate / 1000.0);
227 	return (buf);
228 }
229