diff options
Diffstat (limited to 'usr.sbin/altq/altqstat')
-rw-r--r-- | usr.sbin/altq/altqstat/Makefile | 16 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/altqstat.1 | 98 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/altqstat.c | 226 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/altqstat.h | 67 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_blue.c | 90 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_cbq.c | 160 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_cdnr.c | 153 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_conf.c | 107 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_fifoq.c | 85 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_hfsc.c | 130 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_priq.c | 117 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_red.c | 114 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_rio.c | 147 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/qdisc_wfq.c | 167 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/quip_client.c | 492 | ||||
-rw-r--r-- | usr.sbin/altq/altqstat/quip_client.h | 49 |
16 files changed, 2218 insertions, 0 deletions
diff --git a/usr.sbin/altq/altqstat/Makefile b/usr.sbin/altq/altqstat/Makefile new file mode 100644 index 00000000000..0d571b3515a --- /dev/null +++ b/usr.sbin/altq/altqstat/Makefile @@ -0,0 +1,16 @@ +# $OpenBSD: Makefile,v 1.1 2001/06/27 18:23:19 kjc Exp $ +# $NetBSD: Makefile,v 1.2 2000/12/16 18:57:35 thorpej Exp $ + +BINDIR=/usr/bin + +PROG= altqstat +SRCS= altqstat.c quip_client.c qdisc_conf.c qdisc_cbq.c qdisc_hfsc.c \ + qdisc_cdnr.c qdisc_wfq.c qdisc_fifoq.c qdisc_red.c qdisc_rio.c \ + qdisc_blue.c qdisc_priq.c + +CPPFLAGS+= -DALTQ -I${.CURDIR}/../libaltq + +DPADD+= ${LIBCURSES} +LDADD+= -lcurses + +.include <bsd.prog.mk> diff --git a/usr.sbin/altq/altqstat/altqstat.1 b/usr.sbin/altq/altqstat/altqstat.1 new file mode 100644 index 00000000000..f982a1bf153 --- /dev/null +++ b/usr.sbin/altq/altqstat/altqstat.1 @@ -0,0 +1,98 @@ +.\" $OpenBSD: altqstat.1,v 1.1 2001/06/27 18:23:19 kjc Exp $ +.\" $KAME: altqstat.1,v 1.3 2001/04/09 16:26:29 thorpej Exp $ +.\" +.\" Copyright (C) 2000 +.\" Sony Computer Science Laboratories Inc. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd December 24, 1999 +.Dt ALTQSTAT 1 +.Os BSD +.Sh NAME +.Nm altqstat +.Nd show altq status +.Sh SYNOPSIS +.Nm altqstat +.Op Fl enrs +.Op Fl c Ar count +.Op Fl w Ar wait +.Op Fl i Ar interface +.Op Fl I Ar input_interface +.Sh DESCRIPTION +The +.Nm altqstat +command displays the status of a queueing discipline. The contents +displayed by +.Nm +is specific to each queueing discipline. +.Pp +The options are as follows: +.Bl -tag -width Fl +.It Fl e +Echo communication with +.Xr altqd 8 +to standard output. This option is for debugging. +.It Fl n +Disable communication with +.Xr altqd 8 . +The interface should be explicitly specified. +.It Fl r +Enter the raw console mode to talk to +.Xr altqd 8 . +This option is for debugging queue information exchange between +.Nm +and +.Xr altqd 8 . +.It Fl s +List all interfaces, classes and filters currently installed. +.It Fl c Ar count +.Nm +exits after displaying +.Ar count +times. If no repeat +.Ar count +is specified, the default is infinity. +.It Fl w Ar wait +Pause +.Ar wait +seconds between each display. If no repeat +.Ar wait +interval is specified, the default is 5 seconds. +.It Fl i Ar interface +Show information about the specified interface. If no +.Ar interface +is specified, the default interface is the first interface returned +from +.Xr altqd 8 . +.It Fl I Ar input_interface +Show information about the specified input interface. This option is +used to specify +.Em traffic conditioner +at an input interface. +.El + +.Sh FILES +.Pa /var/run/altq_quip +.Sh SEE ALSO +.Xr altqd 8 , +.Xr altq.conf 5 diff --git a/usr.sbin/altq/altqstat/altqstat.c b/usr.sbin/altq/altqstat/altqstat.c new file mode 100644 index 00000000000..5c66b740d79 --- /dev/null +++ b/usr.sbin/altq/altqstat/altqstat.c @@ -0,0 +1,226 @@ +/* $OpenBSD: altqstat.c,v 1.1 2001/06/27 18:23:19 kjc Exp $ */ +/* $KAME: altqstat.c,v 1.4 2000/12/03 05:44:19 kawa Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/fcntl.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include <err.h> +#ifndef NO_CURSES +#include <curses.h> +#endif + +#include "quip_client.h" +#include "altqstat.h" + +#define DEV_PATH "/dev/altq" + +int qdiscfd = -1; +int show_config = 0; +int interval = 5; +int no_server = 0; +char *interface = NULL; +char *qdisc_name = NULL; + +stat_loop_t *stat_loop; + +static void sig_handler(int sig); +static void usage(void); + +static void +sig_handler(int sig) +{ + fprintf(stderr, "Exiting on signal %d\n", sig); + + close(qdiscfd); /* close altq device */ + quip_closeserver(); /* clocse socket to altqd */ +#ifndef NO_CURSES + if (qdisc_name != NULL && strcmp(qdisc_name, "wfq") == 0) + endwin(); /* wfqstat uses curses */ +#endif + exit(0); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: altqstat [-enrs] [-c count] [-w wait] [-i interface|-I input_interface]\n"); + exit(1); +} + +int +main (int argc, char **argv) +{ + int ch, raw_mode = 0; + int qtype; + int count = 0; + char device[64], qname[64], input[32]; + + while ((ch = getopt(argc, argv, "I:c:ei:nrsw:")) != -1) { + switch (ch) { + case 'I': + sprintf(input, "_%s", optarg); + interface = input; + break; + case 'c': + count = atoi(optarg); + break; + case 'e': + quip_echo = 1; + break; + case 'i': + interface = optarg; + break; + case 'n': + no_server = 1; + break; + case 'r': + raw_mode = 1; + quip_echo = 1; + break; + case 's': + show_config = 1; + break; + case 'w': + interval = atoi(optarg); + break; + default: + usage(); + break; + } + } + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + signal(SIGPIPE, sig_handler); + + if (no_server == 0) { + if (quip_openserver() < 0 && interface == NULL) + errx(1, "you have to specify interface!"); + } + + if (raw_mode == 1) { + quip_rawmode(); + quip_closeserver(); + exit(0); + } + + if (show_config) { + if (no_server) + errx(1, "no server (-n) can't be set for show config (-s)!"); + quip_printconfig(); + quip_closeserver(); + exit(0); + } + + interface = quip_selectinterface(interface); + if (interface == NULL) + errx(1, "no interface found!"); + + qtype = ifname2qdisc(interface, qname); + if (qtype == 0) + errx(1, "altq is not attached on %s!", interface); + + qdisc_name = qname; + + stat_loop = qdisc2stat_loop(qdisc_name); + if (stat_loop == NULL) + errx(1, "qdisc %s is not supported!", qdisc_name); + + printf("%s: %s on interface %s\n", + argv[0], qdisc_name, interface); + + sprintf(device, "%s/%s", DEV_PATH, qdisc_name); + if ((qdiscfd = open(device, O_RDONLY)) < 0) + err(1, "can't open %s", device); + + (*stat_loop)(qdiscfd, interface, count, interval); + /* never returns */ + + exit(0); +} + +/* calculate interval in sec */ +double +calc_interval(struct timeval *cur_time, struct timeval *last_time) +{ + double sec; + + sec = (double)(cur_time->tv_sec - last_time->tv_sec) + + (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000; + return (sec); +} + + +/* calculate rate in bps */ +double +calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval) +{ + double rate; + + rate = (double)(new_bytes - last_bytes) * 8 / interval; + return (rate); +} + +/* calculate packets in second */ +double +calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval) +{ + double pps; + + pps = (double)(new_pkts - last_pkts) / interval; + return (pps); +} + +#define R2S_BUFS 8 + +char * +rate2str(double rate) +{ + char *buf; + static char r2sbuf[R2S_BUFS][16]; /* ring bufer for up to R2S_BUFS */ + static int idx = 0; + + buf = r2sbuf[idx++]; + if (idx == R2S_BUFS) + idx = 0; + + if (rate == 0.0) + sprintf(buf, "0"); + else if (rate >= 1000000.0) + sprintf(buf, "%.2fM", rate / 1000000.0); + else + sprintf(buf, "%.2fK", rate / 1000.0); + return (buf); +} diff --git a/usr.sbin/altq/altqstat/altqstat.h b/usr.sbin/altq/altqstat/altqstat.h new file mode 100644 index 00000000000..077d15ddac3 --- /dev/null +++ b/usr.sbin/altq/altqstat/altqstat.h @@ -0,0 +1,67 @@ +/* $OpenBSD: altqstat.h,v 1.1 2001/06/27 18:23:19 kjc Exp $ */ +/* $KAME: altqstat.h,v 1.2 2000/10/18 09:15:16 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +typedef void (stat_loop_t)(int fd, const char *ifname, + int count, int interval); + +struct qdisc_conf { + const char *qdisc_name; /* e.g., cbq */ + int altqtype; /* e.g., ALTQT_CBQ */ + stat_loop_t *stat_loop; +}; + +/* + * cast u_int64_t to ull for printf, since type of u_int64_t + * is architecture dependent + */ +typedef unsigned long long ull; + +stat_loop_t cbq_stat_loop; +stat_loop_t hfsc_stat_loop; +stat_loop_t cdnr_stat_loop; +stat_loop_t wfq_stat_loop; +stat_loop_t fifoq_stat_loop; +stat_loop_t red_stat_loop; +stat_loop_t rio_stat_loop; +stat_loop_t blue_stat_loop; +stat_loop_t priq_stat_loop; + +struct redstats; + +void chandle2name(const char *ifname, u_long handle, char *name); +stat_loop_t *qdisc2stat_loop(const char *qdisc_name); +int ifname2qdisc(const char *ifname, char *qname); +double calc_interval(struct timeval *cur_time, struct timeval *last_time); +double calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval); +double calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval); +char *rate2str(double rate); +int print_redstats(struct redstats *rp); +int print_riostats(struct redstats *rp); + + + diff --git a/usr.sbin/altq/altqstat/qdisc_blue.c b/usr.sbin/altq/altqstat/qdisc_blue.c new file mode 100644 index 00000000000..f540f8b2ddf --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_blue.c @@ -0,0 +1,90 @@ +/* $OpenBSD: qdisc_blue.c,v 1.1 2001/06/27 18:23:19 kjc Exp $ */ +/* $KAME: qdisc_blue.c,v 1.2 2000/10/18 09:15:16 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_blue.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "altqstat.h" + +void +blue_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct blue_stats blue_stats; + struct timeval cur_time, last_time; + u_int64_t last_bytes; + double sec; + int cnt = count; + + strcpy(blue_stats.iface.blue_ifname, ifname); + + gettimeofday(&last_time, NULL); + last_time.tv_sec -= interval; + last_bytes = 0; + + while (count == 0 || cnt-- > 0) { + + if (ioctl(fd, BLUE_GETSTATS, &blue_stats) < 0) + err(1, "ioctl BLUE_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf(" q_len:%d , q_limit:%d, q_pmark: %d\n", + blue_stats.q_len, blue_stats.q_limit, + blue_stats.q_pmark); + printf(" xmit: %llu pkts, drop: %llu pkts (forced: %llu, early: %llu)\n", + (ull)blue_stats.xmit_packets, + (ull)blue_stats.drop_packets, + (ull)blue_stats.drop_forced, + (ull)blue_stats.drop_unforced); + if (blue_stats.marked_packets != 0) + printf(" marked: %llu\n", + (ull)blue_stats.marked_packets); + printf(" throughput: %sbps\n", + rate2str(calc_rate(blue_stats.xmit_bytes, + last_bytes, sec))); + + last_bytes = blue_stats.xmit_bytes; + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_cbq.c b/usr.sbin/altq/altqstat/qdisc_cbq.c new file mode 100644 index 00000000000..7bf6b72d90a --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_cbq.c @@ -0,0 +1,160 @@ +/* $OpenBSD: qdisc_cbq.c,v 1.1 2001/06/27 18:23:20 kjc Exp $ */ +/* $KAME: qdisc_cbq.c,v 1.3 2000/12/29 06:39:27 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_cbq.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "quip_client.h" +#include "altqstat.h" + +#define NCLASSES 64 + +#ifndef RM_FILTER_GAIN +#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */ +#endif +#ifndef RM_POWER +#define RM_POWER (1 << RM_FILTER_GAIN) +#endif + +void +cbq_stat_loop(int fd, const char *ifname, int count, int interval) +{ + class_stats_t stats1[NCLASSES], stats2[NCLASSES]; + char clnames[NCLASSES][128]; + u_long clhandles[NCLASSES]; + struct cbq_getstats get_stats; + class_stats_t *sp, *lp, *new, *last, *tmp; + struct timeval cur_time, last_time; + int i; + double flow_bps, sec; + int cnt = count; + + strcpy(get_stats.iface.cbq_ifacename, ifname); + new = &stats1[0]; + last = &stats2[0]; + + for (i = 0; i < NCLASSES; i++) + clhandles[i] = NULL_CLASS_HANDLE; + + while (count == 0 || cnt-- > 0) { + get_stats.nclasses = NCLASSES; + get_stats.stats = new; + if (ioctl(fd, CBQ_GETSTATS, &get_stats) < 0) + err(1, "ioctl CBQ_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + for (i=0; i<get_stats.nclasses; i++) { + sp = &new[i]; + lp = &last[i]; + + if (sp->handle != clhandles[i]) { + quip_chandle2name(ifname, sp->handle, + clnames[i]); + clhandles[i] = sp->handle; + continue; + } + + switch (sp->handle) { + case ROOT_CLASS_HANDLE: + printf("Root Class for Interface %s: %s\n", + ifname, clnames[i]); + break; + case DEFAULT_CLASS_HANDLE: + printf("Default Class for Interface %s: %s\n", + ifname, clnames[i]); + break; + case CTL_CLASS_HANDLE: + printf("Ctl Class for Interface %s: %s\n", + ifname, clnames[i]); + break; + default: + printf("Class %d on Interface %s: %s\n", + sp->handle, ifname, clnames[i]); + break; + } + + flow_bps = 8.0 / (double)sp->ns_per_byte + * 1000*1000*1000; + + printf("\tpriority: %d depth: %d", + sp->priority, sp->depth); + printf(" offtime: %d [us] wrr_allot: %d bytes\n", + sp->offtime, sp->wrr_allot); + printf("\tnsPerByte: %d", sp->ns_per_byte); + printf("\t(%sbps),", rate2str(flow_bps)); + printf("\tMeasured: %s [bps]\n", + rate2str(calc_rate(sp->xmit_cnt.bytes, + lp->xmit_cnt.bytes, sec))); + printf("\tpkts: %llu,\tbytes: %llu\n", + (ull)sp->xmit_cnt.packets, + (ull)sp->xmit_cnt.bytes); + printf("\tovers: %u,\toveractions: %u\n", + sp->over, sp->overactions); + printf("\tborrows: %u,\tdelays: %u\n", + sp->borrows, sp->delays); + printf("\tdrops: %llu,\tdrop_bytes: %llu\n", + (ull)sp->drop_cnt.bytes, + (ull)sp->drop_cnt.bytes); + if (sp->qtype == Q_RED) + print_redstats(sp->red); + else if (sp->qtype == Q_RIO) + print_riostats(sp->red); + + printf("\tQCount: %d,\t(qmax: %d)\n", + sp->qcnt, sp->qmax); + printf("\tAvgIdle: %d [us],\t(maxidle: %d minidle: %d [us])\n", + sp->avgidle >> RM_FILTER_GAIN, + sp->maxidle >> RM_FILTER_GAIN, + sp->minidle / RM_POWER); + } + + /* swap the buffer pointers */ + tmp = last; + last = new; + new = tmp; + + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_cdnr.c b/usr.sbin/altq/altqstat/qdisc_cdnr.c new file mode 100644 index 00000000000..8b5e525ae26 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_cdnr.c @@ -0,0 +1,153 @@ +/* $OpenBSD: qdisc_cdnr.c,v 1.1 2001/06/27 18:23:20 kjc Exp $ */ +/* $KAME: qdisc_cdnr.c,v 1.3 2000/10/18 09:15:16 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_cdnr.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "quip_client.h" +#include "altqstat.h" + +#define NELEMENTS 64 +#define MAX_PROB (128*1024) + +static char *element_names[] = { "none", "top", "element", "tbmeter", "trtcm", + "tswtcm" }; +static char *tbmprof_names[] = { "in: ", "out: " }; +static char *tcmprof_names[] = { "green: ", "yellow:", "red: " }; + +void +cdnr_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct tce_stats stats1[NELEMENTS], stats2[NELEMENTS]; + char cdnrnames[NELEMENTS][128]; + struct cdnr_get_stats get_stats; + struct tce_stats *sp, *lp, *new, *last, *tmp; + struct timeval cur_time, last_time; + double sec; + char **profile_names, _ifname[32]; + int i, j, nprofile; + int cnt = count; + + if (ifname[0] == '_') + ifname++; + sprintf(_ifname, "_%s", ifname); + + strcpy(get_stats.iface.cdnr_ifname, ifname); + new = &stats1[0]; + last = &stats2[0]; + + for (i = 0; i < NELEMENTS; i++) + stats1[i].tce_handle = stats2[i].tce_handle = CDNR_NULL_HANDLE; + + while (count == 0 || cnt-- > 0) { + get_stats.nskip = 0; + get_stats.nelements = NELEMENTS; + get_stats.tce_stats = new; + + if (ioctl(fd, CDNR_GETSTATS, &get_stats) < 0) + err(1, "ioctl CDNR_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf("actions:\n"); + printf(" pass:%llu drop:%llu mark:%llu next:%llu return:%llu none:%llu\n", + (ull)get_stats.cnts[TCACODE_PASS].packets, + (ull)get_stats.cnts[TCACODE_DROP].packets, + (ull)get_stats.cnts[TCACODE_MARK].packets, + (ull)get_stats.cnts[TCACODE_NEXT].packets, + (ull)get_stats.cnts[TCACODE_RETURN].packets, + (ull)get_stats.cnts[TCACODE_NONE].packets); + + for (i = 0; i < get_stats.nelements; i++) { + sp = &new[i]; + lp = &last[i]; + + if (sp->tce_handle != lp->tce_handle) { + quip_chandle2name(_ifname, sp->tce_handle, + cdnrnames[i]); + continue; + } + + switch (sp->tce_type) { + case TCETYPE_TBMETER: + nprofile = 2; + profile_names = tbmprof_names; + break; + case TCETYPE_TRTCM: + case TCETYPE_TSWTCM: + nprofile = 3; + profile_names = tcmprof_names; + break; + default: + profile_names = tbmprof_names; /* silence cc */ + nprofile = 0; + } + + if (nprofile == 0) + continue; + + printf("[%s: %s] handle:%#lx\n", + element_names[sp->tce_type], cdnrnames[i], + sp->tce_handle); + for (j = 0; j < nprofile; j++) { + printf(" %s %10llu pkts %16llu bytes (%sbps)\n", + profile_names[j], + (ull)sp->tce_cnts[j].packets, + (ull)sp->tce_cnts[j].bytes, + rate2str( + calc_rate(sp->tce_cnts[j].bytes, + lp->tce_cnts[j].bytes, + sec))); + } + } + printf("\n"); + + /* swap the buffer pointers */ + tmp = last; + last = new; + new = tmp; + + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_conf.c b/usr.sbin/altq/altqstat/qdisc_conf.c new file mode 100644 index 00000000000..e574d7a1af1 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_conf.c @@ -0,0 +1,107 @@ +/* $KAME: qdisc_conf.c,v 1.3 2000/10/18 09:15:16 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#if defined(__NetBSD__) || defined(__OpenBSD__) +#include <sys/ioctl.h> +#endif +#include <sys/fcntl.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <err.h> + +#include "altqstat.h" + +#define ALTQ_DEVICE "/dev/altq/altq" + +struct qdisc_conf qdisc_table[] = { + {"cbq", ALTQT_CBQ, cbq_stat_loop}, + {"hfsc", ALTQT_HFSC, hfsc_stat_loop}, + {"cdnr", ALTQT_CDNR, cdnr_stat_loop}, + {"wfq", ALTQT_WFQ, wfq_stat_loop}, + {"fifoq", ALTQT_FIFOQ, fifoq_stat_loop}, + {"red", ALTQT_RED, red_stat_loop}, + {"rio", ALTQT_RIO, rio_stat_loop}, + {"blue", ALTQT_BLUE, blue_stat_loop}, + {"priq", ALTQT_PRIQ, priq_stat_loop}, + {NULL, 0, NULL} +}; + +stat_loop_t * +qdisc2stat_loop(const char *qdisc_name) +{ + struct qdisc_conf *stat; + + for (stat = qdisc_table; stat->qdisc_name != NULL; stat++) + if (strcmp(stat->qdisc_name, qdisc_name) == 0) + return (stat->stat_loop); + return (NULL); +} + +int +ifname2qdisc(const char *ifname, char *qname) +{ + struct altqreq qtypereq; + int fd, qtype = 0; + + if (ifname[0] == '_') { + /* input interface */ + if (qname != NULL) + strcpy(qname, "cdnr"); + return (ALTQT_CDNR); + } + + strcpy(qtypereq.ifname, ifname); + if ((fd = open(ALTQ_DEVICE, O_RDONLY)) < 0) { + warn("can't open %s", ALTQ_DEVICE); + return (0); + } + if (ioctl(fd, ALTQGTYPE, &qtypereq) < 0) { + warn("ALTQGQTYPE"); + return (0); + } + close(fd); + + if (qname != NULL) { + struct qdisc_conf *stat; + + qtype = qtypereq.arg; + for (stat = qdisc_table; stat->qdisc_name != NULL; stat++) + if (stat->altqtype == qtype) + strcpy(qname, stat->qdisc_name); + } + + return (qtype); +} + diff --git a/usr.sbin/altq/altqstat/qdisc_fifoq.c b/usr.sbin/altq/altqstat/qdisc_fifoq.c new file mode 100644 index 00000000000..bea260c40b7 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_fifoq.c @@ -0,0 +1,85 @@ +/* $KAME: qdisc_fifoq.c,v 1.3 2000/10/18 09:15:16 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_fifoq.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "altqstat.h" + +void +fifoq_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct fifoq_getstats get_stats; + struct timeval cur_time, last_time; + u_int64_t last_bytes; + double sec; + int cnt = count; + + strcpy(get_stats.iface.fifoq_ifname, ifname); + + gettimeofday(&last_time, NULL); + last_time.tv_sec -= interval; + last_bytes = 0; + + while (count == 0 || cnt-- > 0) { + + if (ioctl(fd, FIFOQ_GETSTATS, &get_stats) < 0) + err(1, "ioctl FIFOQ_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf(" q_len:%d q_limit:%d period:%u\n", + get_stats.q_len, get_stats.q_limit, get_stats.period); + printf(" xmit:%llu pkts (%llu bytes) drop:%llu pkts (%llu bytes)\n", + (ull)get_stats.xmit_cnt.packets, + (ull)get_stats.xmit_cnt.bytes, + (ull)get_stats.drop_cnt.packets, + (ull)get_stats.drop_cnt.bytes); + printf(" throughput: %sbps\n", + rate2str(calc_rate(get_stats.xmit_cnt.bytes, + last_bytes, sec))); + + last_bytes = get_stats.xmit_cnt.bytes; + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_hfsc.c b/usr.sbin/altq/altqstat/qdisc_hfsc.c new file mode 100644 index 00000000000..79c6213b662 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_hfsc.c @@ -0,0 +1,130 @@ +/* $OpenBSD: qdisc_hfsc.c,v 1.1 2001/06/27 18:23:21 kjc Exp $ */ +/* $KAME: qdisc_hfsc.c,v 1.3 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_hfsc.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "quip_client.h" +#include "altqstat.h" + +#define NCLASSES 64 + +void +hfsc_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct class_stats stats1[NCLASSES], stats2[NCLASSES]; + char clnames[NCLASSES][128]; + struct hfsc_class_stats get_stats; + struct class_stats *sp, *lp, *new, *last, *tmp; + struct timeval cur_time, last_time; + int i; + double sec; + int cnt = count; + + strcpy(get_stats.iface.hfsc_ifname, ifname); + new = &stats1[0]; + last = &stats2[0]; + + /* invalidate class ids */ + for (i=0; i<NCLASSES; i++) + last[i].class_id = 999999; /* XXX */ + + while (count == 0 || cnt-- > 0) { + get_stats.nskip = 0; + get_stats.nclasses = NCLASSES; + get_stats.stats = new; + + if (ioctl(fd, HFSC_GETSTATS, &get_stats) < 0) + err(1, "ioctl HFSC_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf("\ncur_time:%#llx %u classes %u packets in the tree\n", + (ull)get_stats.cur_time, + get_stats.hif_classes, get_stats.hif_packets); + + for (i=0; i<get_stats.nclasses; i++) { + sp = &new[i]; + lp = &last[i]; + + if (sp->class_id != lp->class_id) { + quip_chandle2name(ifname, sp->class_handle, + clnames[i]); + continue; + } + + printf("[%2d %s] handle:%#lx [rt %s %ums %s][ls %s %ums %s]\n", + sp->class_id, clnames[i], sp->class_handle, + rate2str((double)sp->rsc.m1), sp->rsc.d, + rate2str((double)sp->rsc.m2), + rate2str((double)sp->fsc.m1), sp->fsc.d, + rate2str((double)sp->fsc.m2)); + printf(" measured: %sbps [rt:%s ls:%s] qlen:%2d period:%u\n", + rate2str(calc_rate(sp->total, lp->total, sec)), + rate2str(calc_rate(sp->cumul, lp->cumul, sec)), + rate2str(calc_rate(sp->total - sp->cumul, + lp->total - lp->cumul, sec)), + sp->qlength, sp->period); + printf(" packets:%llu (%llu bytes) drops:%llu\n", + (ull)sp->xmit_cnt.packets, + (ull)sp->xmit_cnt.bytes, + (ull)sp->drop_cnt.packets); + printf(" cumul:%#llx total:%#llx\n", + (ull)sp->cumul, (ull)sp->total); + printf(" vt:%#llx d:%#llx e:%#llx\n", + (ull)sp->vt, (ull)sp->d, (ull)sp->e); + if (sp->qtype == Q_RED) + print_redstats(sp->red); + else if (sp->qtype == Q_RIO) + print_riostats(sp->red); + } + + /* swap the buffer pointers */ + tmp = last; + last = new; + new = tmp; + + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_priq.c b/usr.sbin/altq/altqstat/qdisc_priq.c new file mode 100644 index 00000000000..868407eb836 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_priq.c @@ -0,0 +1,117 @@ +/* $OpenBSD: qdisc_priq.c,v 1.1 2001/06/27 18:23:21 kjc Exp $ */ +/* $KAME: qdisc_priq.c,v 1.1 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_priq.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "quip_client.h" +#include "altqstat.h" + +void +priq_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct class_stats stats1[PRIQ_MAXPRI], stats2[PRIQ_MAXPRI]; + char clnames[PRIQ_MAXPRI][128]; + struct priq_class_stats get_stats; + struct class_stats *sp, *lp, *new, *last, *tmp; + struct timeval cur_time, last_time; + int i; + double sec; + int cnt = count; + + strcpy(get_stats.iface.ifname, ifname); + new = &stats1[0]; + last = &stats2[0]; + + /* invalidate class handles */ + for (i=0; i<PRIQ_MAXPRI; i++) + last[i].class_handle = PRIQ_NULLCLASS_HANDLE; + + while (count == 0 || cnt-- > 0) { + get_stats.stats = new; + get_stats.maxpri = PRIQ_MAXPRI; + if (ioctl(fd, PRIQ_GETSTATS, &get_stats) < 0) + err(1, "ioctl PRIQ_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf("\n%s:\n", ifname); + + for (i = get_stats.maxpri; i >= 0; i--) { + sp = &new[i]; + lp = &last[i]; + + if (sp->class_handle == PRIQ_NULLCLASS_HANDLE) + continue; + + if (sp->class_handle != lp->class_handle) { + quip_chandle2name(ifname, sp->class_handle, + clnames[i]); + continue; + } + + printf("[%s] handle:%#lx pri:%d\n", + clnames[i], sp->class_handle, i); + printf(" measured: %sbps qlen:%2d period:%u\n", + rate2str(calc_rate(sp->xmitcnt.bytes, + lp->xmitcnt.bytes, sec)), + sp->qlength, sp->period); + printf(" packets:%llu (%llu bytes) drops:%llu\n", + (ull)sp->xmitcnt.packets, + (ull)sp->xmitcnt.bytes, + (ull)sp->dropcnt.packets); + if (sp->qtype == Q_RED) + print_redstats(sp->red); + else if (sp->qtype == Q_RIO) + print_riostats(sp->red); + } + + /* swap the buffer pointers */ + tmp = last; + last = new; + new = tmp; + + last_time = cur_time; + sleep(interval); + } +} diff --git a/usr.sbin/altq/altqstat/qdisc_red.c b/usr.sbin/altq/altqstat/qdisc_red.c new file mode 100644 index 00000000000..75550bb4e14 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_red.c @@ -0,0 +1,114 @@ +/* $OpenBSD: qdisc_red.c,v 1.1 2001/06/27 18:23:21 kjc Exp $ */ +/* $KAME: qdisc_red.c,v 1.2 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_red.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "altqstat.h" + +static int avg_scale = 4096; /* default fixed-point scale */ + +void +red_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct red_stats red_stats; + struct timeval cur_time, last_time; + u_int64_t last_bytes; + double sec; + int cnt = count; + + strcpy(red_stats.iface.red_ifname, ifname); + + gettimeofday(&last_time, NULL); + last_time.tv_sec -= interval; + last_bytes = 0; + + while (count == 0 || cnt-- > 0) { + + if (ioctl(fd, RED_GETSTATS, &red_stats) < 0) + err(1, "ioctl RED_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf(" weight:%d inv_pmax:%d qthresh:(%d,%d)\n", + red_stats.weight, red_stats.inv_pmax, + red_stats.th_min, red_stats.th_max); + printf(" q_len:%d (avg: %.2f), q_limit:%d\n", + red_stats.q_len, + ((double)red_stats.q_avg)/(double)avg_scale, + red_stats.q_limit); + printf(" xmit:%llu pkts, drop:%llu pkts (forced: %u, early: %u)\n", + (ull)red_stats.xmit_cnt.packets, + (ull)red_stats.drop_cnt.packets, + red_stats.drop_forced, red_stats.drop_unforced); + if (red_stats.marked_packets != 0) + printf(" marked: %u\n", red_stats.marked_packets); + printf(" throughput: %sbps\n", + rate2str(calc_rate(red_stats.xmit_cnt.bytes, + last_bytes, sec))); + if (red_stats.fv_alloc > 0) { + printf(" flowvalve: alloc:%u flows:%u\n", + red_stats.fv_alloc, red_stats.fv_flows); + printf(" predrop:%u pass:%u escape:%u\n", + red_stats.fv_predrop, red_stats.fv_pass, + red_stats.fv_escape); + } + printf("\n"); + + last_bytes = red_stats.xmit_cnt.bytes; + last_time = cur_time; + sleep(interval); + } +} + +int +print_redstats(struct redstats *rp) +{ + printf(" RED q_avg:%.2f xmit:%llu (forced:%u early:%u marked:%u)\n", + ((double)rp->q_avg)/(double)avg_scale, + (ull)rp->xmit_cnt.packets, + rp->drop_forced, + rp->drop_unforced, + rp->marked_packets); + return 0; +} diff --git a/usr.sbin/altq/altqstat/qdisc_rio.c b/usr.sbin/altq/altqstat/qdisc_rio.c new file mode 100644 index 00000000000..a7193ff8aec --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_rio.c @@ -0,0 +1,147 @@ +/* $OpenBSD: qdisc_rio.c,v 1.1 2001/06/27 18:23:21 kjc Exp $ */ +/* $KAME: qdisc_rio.c,v 1.3 2001/05/17 08:01:47 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_red.h> +#include <altq/altq_rio.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> + +#include "altqstat.h" + +static int avg_scale = 4096; /* default fixed-point scale */ + +void +rio_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct rio_stats rio_stats; + struct timeval cur_time, last_time; + u_int64_t last_bytes[3]; + double sec; + int cnt = count; + + bzero(&rio_stats, sizeof(rio_stats)); + strcpy(rio_stats.iface.rio_ifname, ifname); + + gettimeofday(&last_time, NULL); + last_time.tv_sec -= interval; + + while (count == 0 || cnt-- > 0) { + + if (ioctl(fd, RIO_GETSTATS, &rio_stats) < 0) + err(1, "ioctl RIO_GETSTATS"); + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + printf("weight:%d q_limit:%d\n", + rio_stats.weight, rio_stats.q_limit); + + printf("\t\t\tLOW DP\t\tMEDIUM DP\t\tHIGH DP\n"); + + printf("thresh (prob):\t\t[%d,%d](1/%d)\t[%d,%d](1/%d)\t\t[%d,%d](%d)\n", + rio_stats.q_params[0].th_min, + rio_stats.q_params[0].th_max, + rio_stats.q_params[0].inv_pmax, + rio_stats.q_params[1].th_min, + rio_stats.q_params[1].th_max, + rio_stats.q_params[1].inv_pmax, + rio_stats.q_params[2].th_min, + rio_stats.q_params[2].th_max, + rio_stats.q_params[2].inv_pmax); + printf("qlen (avg):\t\t%d (%.2f)\t%d (%.2f)\t\t%d (%.2f)\n", + rio_stats.q_len[0], + ((double)rio_stats.q_stats[0].q_avg)/(double)avg_scale, + rio_stats.q_len[1], + ((double)rio_stats.q_stats[1].q_avg)/(double)avg_scale, + rio_stats.q_len[2], + ((double)rio_stats.q_stats[2].q_avg)/(double)avg_scale); + printf("xmit (drop) pkts:\t%llu (%llu)\t\t%llu (%llu)\t\t\t%llu (%llu)\n", + (ull)rio_stats.q_stats[0].xmit_cnt.packets, + (ull)rio_stats.q_stats[0].drop_cnt.packets, + (ull)rio_stats.q_stats[1].xmit_cnt.packets, + (ull)rio_stats.q_stats[1].drop_cnt.packets, + (ull)rio_stats.q_stats[2].xmit_cnt.packets, + (ull)rio_stats.q_stats[2].drop_cnt.packets); + printf("(forced:early):\t\t(%u:%u)\t\t(%u:%u)\t\t\t(%u:%u)\n", + rio_stats.q_stats[0].drop_forced, + rio_stats.q_stats[0].drop_unforced, + rio_stats.q_stats[1].drop_forced, + rio_stats.q_stats[1].drop_unforced, + rio_stats.q_stats[2].drop_forced, + rio_stats.q_stats[2].drop_unforced); + if (rio_stats.q_stats[0].marked_packets != 0 + || rio_stats.q_stats[1].marked_packets != 0 + || rio_stats.q_stats[2].marked_packets != 0) + printf("marked:\t\t\t%u\t\t%u\t\t\t%u\n", + rio_stats.q_stats[0].marked_packets, + rio_stats.q_stats[1].marked_packets, + rio_stats.q_stats[2].marked_packets); + printf("throughput:\t\t%sbps\t%sbps\t\t%sbps\n\n", + rate2str(calc_rate(rio_stats.q_stats[0].xmit_cnt.bytes, + last_bytes[0], sec)), + rate2str(calc_rate(rio_stats.q_stats[1].xmit_cnt.bytes, + last_bytes[1], sec)), + rate2str(calc_rate(rio_stats.q_stats[2].xmit_cnt.bytes, + last_bytes[2], sec))); + + last_bytes[0] = rio_stats.q_stats[0].xmit_cnt.bytes; + last_bytes[1] = rio_stats.q_stats[1].xmit_cnt.bytes; + last_bytes[2] = rio_stats.q_stats[2].xmit_cnt.bytes; + last_time = cur_time; + sleep(interval); + } +} + +int +print_riostats(struct redstats *rp) +{ + int dp; + + for (dp = 0; dp < RIO_NDROPPREC; dp++) + printf(" RIO[%d] q_avg:%.2f xmit:%llu (forced: %u early:%u marked:%u)\n", + dp, + ((double)rp[dp].q_avg)/(double)avg_scale, + (ull)rp[dp].xmit_cnt.packets, + rp[dp].drop_forced, + rp[dp].drop_unforced, + rp[dp].marked_packets); + return 0; +} diff --git a/usr.sbin/altq/altqstat/qdisc_wfq.c b/usr.sbin/altq/altqstat/qdisc_wfq.c new file mode 100644 index 00000000000..f829b27e194 --- /dev/null +++ b/usr.sbin/altq/altqstat/qdisc_wfq.c @@ -0,0 +1,167 @@ +/* $KAME: qdisc_wfq.c,v 1.2 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <altq/altq.h> +#include <altq/altq_wfq.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <err.h> +#ifndef NO_CURSES +#include <curses.h> +#endif + +#include "altqstat.h" + +struct wfqinfo { + int qid; + queue_stats stats; + u_quad_t last_bytes; + double bps; +}; + +#define NTOP 10 +static int ntop = NTOP; + +void +wfq_stat_loop(int fd, const char *ifname, int count, int interval) +{ + struct wfq_getstats wfq_stats; + struct timeval cur_time, last_time; + int i, j, k, nqueues; + double sec; + struct wfqinfo *qinfo, **top; + int cnt = count; + + strcpy(wfq_stats.iface.wfq_ifacename, ifname); + + /* + * first, find out how many queues are available + */ + for (i = 0; i < MAX_QSIZE; i++) { + wfq_stats.qid = i; + if (ioctl(fd, WFQ_GET_STATS, &wfq_stats) < 0) + break; + } + nqueues = i; + printf("wfq on %s: %d queues are used\n", ifname, nqueues); + + if ((qinfo = malloc(nqueues * sizeof(struct wfqinfo))) == NULL) + err(1, "malloc failed!"); + if ((top = malloc(ntop * sizeof(struct wfqinfo *))) == NULL) + err(1, "malloc failed!"); + +#ifndef NO_CURSES + sleep(2); /* wait a bit before clearing the screen */ + + initscr(); +#endif + + gettimeofday(&last_time, NULL); + last_time.tv_sec -= interval; + + while (count == 0 || cnt-- > 0) { + + for (j = 0; j < ntop; j++) + top[j] = NULL; + + for (i = 0; i < nqueues; i++) { + wfq_stats.qid = i; + if (ioctl(fd, WFQ_GET_STATS, &wfq_stats) < 0) + err(1, "ioctl WFQ_GET_STATS"); + + qinfo[i].qid = i; + qinfo[i].stats = wfq_stats.stats; + } + + gettimeofday(&cur_time, NULL); + sec = calc_interval(&cur_time, &last_time); + + /* + * calculate the throughput of each queue + */ + for (i = 0; i < nqueues; i++) { + qinfo[i].bps = calc_rate(qinfo[i].stats.xmit_cnt.bytes, + qinfo[i].last_bytes, sec); + qinfo[i].last_bytes = qinfo[i].stats.xmit_cnt.bytes; + + for (j = 0; j < ntop; j++) { + if (top[j] == NULL) { + top[j] = &qinfo[i]; + break; + } + if (top[j]->bps < qinfo[i].bps || + (top[j]->bps == qinfo[i].bps && + top[j]->stats.xmit_cnt.packets < + qinfo[i].stats.xmit_cnt.packets)) { + for (k = ntop-1; k > j; k--) + top[k] = top[k-1]; + top[j] = &qinfo[i]; + break; + } + } + } + + /* + * display top + */ + printf("[QID] WEIGHT QSIZE(KB) SENT(pkts) (KB) DROP(pkts) (KB) bps\n\r"); + + for (j = 0; j < ntop; j++) { + if (top[j] != NULL) + printf("[%4d] %4d %4d %10llu %14llu %10llu %14llu %9s\n\r", + top[j]->qid, + top[j]->stats.weight, + top[j]->stats.bytes / 1024, + (ull)top[j]->stats.xmit_cnt.packets, + (ull)top[j]->stats.xmit_cnt.bytes /1024, + (ull)top[j]->stats.drop_cnt.packets, + (ull)top[j]->stats.drop_cnt.bytes /1024, + rate2str(top[j]->bps)); + else + printf("\n"); + } +#ifndef NO_CURSES + refresh(); + mvcur(ntop+1, 0, 0, 0); +#endif + + last_time = cur_time; + sleep(interval); + } + +} diff --git a/usr.sbin/altq/altqstat/quip_client.c b/usr.sbin/altq/altqstat/quip_client.c new file mode 100644 index 00000000000..10d4cd16271 --- /dev/null +++ b/usr.sbin/altq/altqstat/quip_client.c @@ -0,0 +1,492 @@ +/* $OpenBSD: quip_client.c,v 1.1 2001/06/27 18:23:22 kjc Exp $ */ +/* $KAME: quip_client.c,v 1.2 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include <err.h> + +#include "quip_client.h" +#include "altqstat.h" + +/* + * quip (queue information protocol) is a http-like protocol + * in order to retrieve information from the server. + * a unix domain TCP socket "/var/run/altq_quip" is used for + * clinet-server style communication. + * + * there are 2 quip message types: request and response. + * request format: (only single-line request message is used at this moment) + * request-line + * + * request-line = <method> <operation>[?<query>] <quip-version> + * <method> = GET (only GET is defined at this moment) + * <operation> = list | handle-to-name | qdisc | filter + * query format is operation dependent but most query takes + * <interface> or <class> or <filter>. + * <interface> = <if_name> + * <class> = <if_name>:<class_path>/<class_name> + * <filter> = <if_name>:<class_path>/<class_name>:<filter_name> + * "list" operation accepts "*" as a wildcard. + * + * response format: + * status-line + * response-headers (0 or more) + * <blank line> + * body + * + * status-line = <quip-version> <status-code> <reason phrase> + * response-header = Content-Length:<value> + * + * "Content-Length" specifies the length of the message body. + * + * example: + * to retrieve a list of classes (handle and name) on interface "fxp0": + * a request message looks like, + * GET list?fxp0:* QUIP/1.0<cr> + * a response message looks like, + * QUIP/1.0 200 OK<cr> + * Content-Length:86<cr> + * <cr> + * 0000000000 fxp0:/root<cr> + * 0xc0d1be00 fxp0:/root/parent<cr> + * 0xc0d1ba00 fxp0:/root/parent/child<cr> + * + * other examples: + * list all interfaces, classes, and filters: + * GET list QUIP/1.0<cr> + * list all interfaces: + * GET list?* QUIP/1.0<cr> + * list all classes: + * GET list?*:* QUIP/1.0<cr> + * list all filters: + * GET list?*:*:* QUIP/1.0<cr> + * convert class handle to class name: + * GET handle-to-name?fxp0:0xc0d1be00 QUIP/1.0<cr> + * convert filter handle to filter name: + * GET handle-to-name?fxp0::0x1000000a QUIP/1.0<cr> + */ + +enum nametype { INTERFACE, CLASS, FILTER, CONDITIONER }; + +static FILE *server = NULL; +int quip_echo = 0; + +static char *extract_ifname(const char *name); + +int +quip_openserver(void) +{ + struct sockaddr_un addr; + int fd; + + if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) + err(1, "can't open socket"); + + bzero(&addr, sizeof(addr)); + addr.sun_family = AF_LOCAL; + strcpy(addr.sun_path, QUIP_PATH); + + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + fprintf(stderr, "can't talk to altqd!\n" + "probably, altqd is not running\n"); + return (-1); + } + + if ((server = fdopen(fd, "r+")) == NULL) { + warn("fdopen: can't open stream to the quip server"); + return (-1); + } + return (0); +} + +int +quip_closeserver(void) +{ + if (server != NULL) + return fclose(server); + return (0); +} + +void +quip_sendrequest(FILE *fp, const char *request) +{ + char buf[1024], *cp; + int n; + + if ((cp = strstr(request, "QUIP")) == NULL) { + cp = strchr(request, '\n'); + n = cp - request; + strncpy(buf, request, n); + n += sprintf(buf + n, " QUIP/1.0"); + strcpy(buf + n, cp); + } + else + strcpy(buf, request); + + if (fputs(buf, fp) != 0) + err(1, "fputs"); + if (fflush(fp) != 0) + err(1, "fflush"); + if (quip_echo) { + fputs("<< ", stdout); + fputs(buf, stdout); + } +} + +/* + * recv_response receives a response message from the server + * and returns status_code. + */ +int +quip_recvresponse(FILE *fp, char *header, char *body, int *blen) +{ + char buf[1024], version[64]; + int code, resid; + int end_of_header = 0; + + if (blen != NULL) + *blen = 0; + code = 0; + resid = 0; + while (fgets(buf, 1024, fp) != 0) { + if (quip_echo) { + fputs("> ", stdout); + fputs(buf, stdout); + } + + if (!end_of_header) { + /* process message header */ + if (header != NULL) + header += sprintf(header, "%s", buf); + + if (code == 0) { + /* status line expected */ + if (buf[0] == '\n') { + /* ignore blank lines */ + } + else if (sscanf(buf, "%s %d", + version, &code) != 2) { + /* can't get result code */ + fpurge(fp); + return (-1); + } + } + else { + /* entity header expected */ + char *field, *cp; + + if (buf[0] == '\n') { + /* end of header */ + end_of_header = 1; + if (resid == 0) + /* no message body */ + return (code); + } + + cp = buf; + field = strsep(&cp, ":"); + if (strcmp(field, "Content-Length") == 0) { + sscanf(cp, "%d", &resid); + if (blen != NULL) + *blen = resid; + } + } + } + else { + /* process message body */ + int len; + + if (body != NULL) { + len = sprintf(body, "%s", buf); + body += len; + } + else + len = strlen(buf); + resid -= len; + if (resid <= 0) + return (code); + } + } + return (-1); +} + +void +quip_rawmode(void) +{ + char line[1024]; + int result_code; + + printf(">>>Entering the raw interactive mode to the server:\n\n"); + if (server == NULL) { + printf("No server available!\n"); + return; + } + + while (1) { + printf("%% "); fflush(stdout); + /* read a line from stdin */ + if (fgets(line, 1024, stdin) == NULL) + break; + + if (line[0] == '\n') { + /* if a blank line, echo locally */ + fputs(line, stdout); + continue; + } + if (line[0] == 'q') { + printf("Exit\n"); + break; + } + + /* send the input line to the server */ + quip_sendrequest(server, line); + + /* get a response message from the server */ + result_code = quip_recvresponse(server, NULL, NULL, NULL); + } +} + +char * +quip_selectinterface(char *ifname) +{ + char buf[8192], *cp; + int result_code, len; + u_int if_index; + static char interface[64]; + + if (server == NULL) + return (ifname); + + /* get an inferface list from the server */ + quip_sendrequest(server, "GET list?*\n"); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get interface list"); + + cp = buf; + while (1) { + if (sscanf(cp, "%x %s", &if_index, interface) != 2) + break; + if (ifname == NULL) { + /* if name isn't specified, return the 1st entry */ + return (interface); + } + if (strcmp(ifname, interface) == 0) + /* found the matching entry */ + + return (interface); + if ((cp = strchr(cp+1, '\n')) == NULL) + break; + } + errx(1, "can't get interface"); + return (NULL); +} + +char * +quip_selectqdisc(char *ifname, char *qdisc_name) +{ + char buf[8192], req[256]; + int result_code, len; + static char qdisc[64]; + + if (server == NULL) { + if (ifname == NULL || qdisc_name == NULL) + errx(1, "when disabling server communication,\n" + "specify both interface (-i) and qdisc (-q)!"); + return (qdisc_name); + } + + /* get qdisc info from the server */ + sprintf(req, "GET qdisc?%s\n", ifname); + quip_sendrequest(server, req); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get qdisc info"); + + if (sscanf(buf, "%s", qdisc) != 1) + errx(1, "can't get qdisc name"); + + if (qdisc_name != NULL && strcmp(qdisc, qdisc_name) != 0) + errx(1, "qdisc %s on %s doesn't match specified qdisc %s", + qdisc, ifname, qdisc_name); + + return (qdisc); +} + +void +quip_chandle2name(const char *ifname, u_long handle, char *name) +{ + char buf[8192], req[256], *cp; + int result_code, len; + + name[0] = '\0'; + if (server == NULL) + return; + + /* get class name from the server */ + sprintf(req, "GET handle-to-name?%s:%#lx\n", ifname, handle); + quip_sendrequest(server, req); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get class name"); + + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + if ((cp = strrchr(buf, '/')) != NULL) + strcpy(name, cp+1); +} + +void +quip_printqdisc(const char *ifname) +{ + char buf[8192], req[256], *cp; + int result_code, len; + + if (server == NULL) { + printf("No server available!\n"); + return; + } + + /* get qdisc info from the server */ + sprintf(req, "GET qdisc?%s\n", ifname); + quip_sendrequest(server, req); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get qdisc info"); + + /* replace newline by space */ + cp = buf; + while ((cp = strchr(cp, '\n')) != NULL) + *cp = ' '; + + printf(" qdisc:%s\n", buf); +} + +void +quip_printfilter(const char *ifname, const u_long handle) +{ + char buf[8192], req[256], *cp; + int result_code, len; + + /* get qdisc info from the server */ + sprintf(req, "GET filter?%s::%#lx\n", ifname, handle); + quip_sendrequest(server, req); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get filter info"); + + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + printf("%s", buf); +} + +static char * +extract_ifname(const char *name) +{ + char *cp; + int len; + static char ifname[64]; + + if ((cp = strchr(name, ':')) != NULL) + len = cp - name; + else + len = strlen(name); + len = MIN(len, 63); + strncpy(ifname, name, len); + ifname[len] = '\0'; + return (ifname); +} + +void +quip_printconfig(void) +{ + char buf[8192], name[256], *cp, *p, *flname; + int result_code, len; + enum nametype type; + u_long handle; + + /* get a total list from the server */ + quip_sendrequest(server, "GET list\n"); + + result_code = quip_recvresponse(server, NULL, buf, &len); + if (result_code != 200) + errx(1, "can't get total list"); + + printf("------------ current configuration ------------"); + + cp = buf; + while (1) { + if (sscanf(cp, "%lx %s", &handle, name) != 2) + break; + + if ((p = strchr(name, ':')) == NULL) + type = INTERFACE; + else if (strchr(p+1, ':') == NULL) + type = CLASS; + else + type = FILTER; + + switch (type) { + case INTERFACE: + printf("\ninterface: %s (index:%lu)\n", + name, handle); + quip_printqdisc(name); + break; + case CLASS: + printf("class: %s (handle:%#lx)\n", + name, handle); + break; + case FILTER: + flname = strrchr(name, ':') + 1; + printf(" filter: name:%s [", flname); + quip_printfilter(extract_ifname(name), handle); + printf("] (handle:%#lx)\n", handle); + break; + case CONDITIONER: + break; + } + + if ((cp = strchr(cp+1, '\n')) == NULL) + break; + } + printf("-----------------------------------------------\n\n"); +} + diff --git a/usr.sbin/altq/altqstat/quip_client.h b/usr.sbin/altq/altqstat/quip_client.h new file mode 100644 index 00000000000..7a107b999af --- /dev/null +++ b/usr.sbin/altq/altqstat/quip_client.h @@ -0,0 +1,49 @@ +/* $OpenBSD: quip_client.h,v 1.1 2001/06/27 18:23:22 kjc Exp $ */ +/* $KAME: quip_client.h,v 1.2 2000/10/18 09:15:17 kjc Exp $ */ +/* + * Copyright (C) 1999-2000 + * Sony Computer Science Laboratories, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _QUIP_CLIENT_H_ +#define _QUIP_CLIENT_H_ + +/* unix domain socket for quip */ +#define QUIP_PATH "/var/run/altq_quip" + +extern int quip_echo; + +int quip_openserver(void); +int quip_closeserver(void); +void quip_sendrequest(FILE *fp, const char *request); +int quip_recvresponse(FILE *fp, char *header, char *body, int *blen); +void quip_rawmode(void); +char *quip_selectinterface(char *ifname); +char *quip_selectqdisc(char *ifname, char *qdisc_name); +void quip_chandle2name(const char *ifname, u_long handle, char *name); +void quip_printqdisc(const char *ifname); +void quip_printfilter(const char *ifname, const u_long handle); +void quip_printconfig(void); + +#endif /* _QUIP_CLIENT_H_ */ |