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