summaryrefslogtreecommitdiff
path: root/usr.sbin/altq/altqstat
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/altq/altqstat')
-rw-r--r--usr.sbin/altq/altqstat/Makefile16
-rw-r--r--usr.sbin/altq/altqstat/altqstat.198
-rw-r--r--usr.sbin/altq/altqstat/altqstat.c226
-rw-r--r--usr.sbin/altq/altqstat/altqstat.h67
-rw-r--r--usr.sbin/altq/altqstat/qdisc_blue.c90
-rw-r--r--usr.sbin/altq/altqstat/qdisc_cbq.c160
-rw-r--r--usr.sbin/altq/altqstat/qdisc_cdnr.c153
-rw-r--r--usr.sbin/altq/altqstat/qdisc_conf.c107
-rw-r--r--usr.sbin/altq/altqstat/qdisc_fifoq.c85
-rw-r--r--usr.sbin/altq/altqstat/qdisc_hfsc.c130
-rw-r--r--usr.sbin/altq/altqstat/qdisc_priq.c117
-rw-r--r--usr.sbin/altq/altqstat/qdisc_red.c114
-rw-r--r--usr.sbin/altq/altqstat/qdisc_rio.c147
-rw-r--r--usr.sbin/altq/altqstat/qdisc_wfq.c167
-rw-r--r--usr.sbin/altq/altqstat/quip_client.c492
-rw-r--r--usr.sbin/altq/altqstat/quip_client.h49
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_ */