diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2003-01-09 17:33:21 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2003-01-09 17:33:21 +0000 |
commit | ad5f03ac09ff82fbd25e08695ca1e59e87b3ae77 (patch) | |
tree | a28eb3fbe5e7a90783d6e580defd1d0421584dc0 /sbin/pfctl | |
parent | c47d7f93536d14c6893f5d473cc90350959c804a (diff) |
first attack at pfctl queue statistics, to be displayed with pfctl -vsq
This commit is dedicated to the cute KLM girls who made part of this
possible with giving me a seat in the plane where you actually have enough
place to hack. Thanks, girls.
ok markus@ dhartmei@
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/Makefile | 4 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 37 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.h | 17 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_altq.c | 100 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_qstats.c | 277 |
5 files changed, 285 insertions, 150 deletions
diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile index 73c1a969f0a..073484f978a 100644 --- a/sbin/pfctl/Makefile +++ b/sbin/pfctl/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.11 2003/01/03 21:37:44 cedric Exp $ +# $OpenBSD: Makefile,v 1.12 2003/01/09 17:33:19 henning Exp $ PROG= pfctl SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c -SRCS+= pfctl_radix.c pfctl_table.c +SRCS+= pfctl_radix.c pfctl_table.c pfctl_qstats.c CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized CFLAGS+= -Wstrict-prototypes YFLAGS= diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 3e673c6a8cb..ded52ec4e3d 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.126 2003/01/09 10:40:44 cedric Exp $ */ +/* $OpenBSD: pfctl.c,v 1.127 2003/01/09 17:33:19 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -67,7 +67,6 @@ void pfctl_clear_pool(struct pf_pool *); void pfctl_print_rule_counters(struct pf_rule *, int); int pfctl_show_rules(int, int, int); int pfctl_show_nat(int, int); -int pfctl_show_altq(int); int pfctl_show_states(int, u_int8_t, int); int pfctl_show_status(int); int pfctl_show_timeouts(int); @@ -604,36 +603,6 @@ pfctl_show_rules(int dev, int opts, int format) } int -pfctl_show_altq(int dev) -{ - struct pf_altq_node *root = NULL; - - struct pfioc_altq pa; - u_int32_t mnr, nr; - - if (!altqsupport) - return (-1); - memset(&pa, 0, sizeof(pa)); - if (ioctl(dev, DIOCGETALTQS, &pa)) { - warn("DIOCGETALTQS"); - return (-1); - } - mnr = pa.nr; - for (nr = 0; nr < mnr; ++nr) { - pa.nr = nr; - if (ioctl(dev, DIOCGETALTQ, &pa)) { - warn("DIOCGETALTQ"); - return (-1); - } - pfctl_insert_altq_node(&root, pa.altq); - } - for (; root != NULL; root = root->next) - pfctl_print_altq_node(root, 0); - pfctl_free_altq_node(root); - return (0); -} - -int pfctl_show_nat(int dev, int opts) { struct pfioc_rule pr; @@ -1467,7 +1436,7 @@ main(int argc, char *argv[]) pfctl_show_nat(dev, opts); break; case 'q': - pfctl_show_altq(dev); + pfctl_show_altq(dev, opts); break; case 's': pfctl_show_states(dev, 0, opts); @@ -1484,7 +1453,7 @@ main(int argc, char *argv[]) case 'a': pfctl_show_rules(dev, opts, 0); pfctl_show_nat(dev, opts); - pfctl_show_altq(dev); + pfctl_show_altq(dev, opts); pfctl_show_states(dev, 0, opts); pfctl_show_status(dev); pfctl_show_rules(dev, opts, 1); diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index 0d6f1f3161b..dd37cffb94b 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.h,v 1.4 2003/01/09 10:40:44 cedric Exp $ */ +/* $OpenBSD: pfctl.h,v 1.5 2003/01/09 17:33:19 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -58,6 +58,7 @@ int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *, int pfctl_clear_tables(int); int pfctl_show_tables(int); int pfctl_command_tables(int, char *[], char *, char *, char *, int); +int pfctl_show_altq(int, int); #ifndef DEFAULT_PRIORITY #define DEFAULT_PRIORITY 1 @@ -75,20 +76,6 @@ struct segment { double x, y, d, m; }; -struct pf_altq_node { - struct pf_altq altq; - struct pf_altq_node *next; - struct pf_altq_node *children; -}; - -void pfctl_insert_altq_node(struct pf_altq_node **, - const struct pf_altq); -struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *, - const char *, const char *); -void pfctl_print_altq_node(const struct pf_altq_node *, - unsigned); -void pfctl_free_altq_node(struct pf_altq_node *); - int check_commit_altq(int, int); void pfaltq_store(struct pf_altq *); void pfaltq_free(struct pf_altq *); diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c index 73e53532c03..c31af54f90c 100644 --- a/sbin/pfctl/pfctl_altq.c +++ b/sbin/pfctl/pfctl_altq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_altq.c,v 1.30 2003/01/05 02:17:09 dhartmei Exp $ */ +/* $OpenBSD: pfctl_altq.c,v 1.31 2003/01/09 17:33:19 henning Exp $ */ /* * Copyright (C) 2002 @@ -1003,104 +1003,6 @@ sc_x2y(struct service_curve *sc, double x) return (y); } -void -pfctl_insert_altq_node(struct pf_altq_node **root, - const struct pf_altq altq) -{ - struct pf_altq_node *node; - - node = calloc(1, sizeof(struct pf_altq_node)); - if (node == NULL) - err(1, "pfctl_insert_altq_node: calloc"); - memcpy(&node->altq, &altq, sizeof(struct pf_altq)); - node->next = node->children = NULL; - - if (*root == NULL) - *root = node; - else if (!altq.parent[0]) { - struct pf_altq_node *prev = *root; - - while (prev->next != NULL) - prev = prev->next; - prev->next = node; - } else { - struct pf_altq_node *parent; - - parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname); - if (parent == NULL) - errx(1, "parent %s not found", altq.parent); - if (parent->children == NULL) - parent->children = node; - else { - struct pf_altq_node *prev = parent->children; - - while (prev->next != NULL) - prev = prev->next; - prev->next = node; - } - } -} - -struct pf_altq_node * -pfctl_find_altq_node(struct pf_altq_node *root, const char *qname, - const char *ifname) -{ - struct pf_altq_node *node, *child; - - for (node = root; node != NULL; node = node->next) { - if (!strcmp(node->altq.qname, qname) && - !(strcmp(node->altq.ifname, ifname))) - return (node); - if (node->children != NULL) { - child = pfctl_find_altq_node(node->children, qname, - ifname); - if (child != NULL) - return (child); - } - } - return (NULL); -} - -void -pfctl_print_altq_node(const struct pf_altq_node *node, unsigned level) -{ - const struct pf_altq_node *child; - - if (node == NULL) - return; - - print_altq(&node->altq, level); - - if (node->children != NULL) { - printf("{"); - for (child = node->children; child != NULL; - child = child->next) { - printf("%s", child->altq.qname); - if (child->next != NULL) - printf(", "); - } - printf("}"); - } - printf("\n"); - for (child = node->children; child != NULL; - child = child->next) - pfctl_print_altq_node(child, level+1); -} - -void -pfctl_free_altq_node(struct pf_altq_node *node) -{ - while (node != NULL) { - struct pf_altq_node *prev; - - if (node->children != NULL) - pfctl_free_altq_node(node->children); - prev = node; - node = node->next; - free(prev); - } -} - /* * misc utilities */ diff --git a/sbin/pfctl/pfctl_qstats.c b/sbin/pfctl/pfctl_qstats.c new file mode 100644 index 00000000000..e63b76bdbdc --- /dev/null +++ b/sbin/pfctl/pfctl_qstats.c @@ -0,0 +1,277 @@ +/* $OpenBSD: pfctl_qstats.c,v 1.1 2003/01/09 17:33:20 henning Exp $ */ + +/* + * Copyright (c) 2003 Henning Brauer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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 THE COPYRIGHT HOLDERS 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 THE + * COPYRIGHT HOLDERS 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/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <net/pfvar.h> +#include <arpa/inet.h> + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <altq/altq.h> +#include <altq/altq_cbq.h> +#include <altq/altq_priq.h> +#include <altq/altq_hfsc.h> + +#include "pfctl_parser.h" +#include "pfctl.h" + +union class_stats { + class_stats_t cbq_stats; + struct priq_classstats priq_stats; + struct hfsc_classstats hfsc_stats; + struct timeval timestamp; +}; + +struct pf_altq_node { + struct pf_altq altq; + struct pf_altq_node *next; + struct pf_altq_node *children; + union class_stats qstats; + union class_stats qstats_last; +}; + +int pfctl_update_qstats(int, struct pf_altq_node **); +void pfctl_insert_altq_node(struct pf_altq_node **, + const struct pf_altq, const union class_stats); +struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *, + const char *, const char *); +void pfctl_print_altq_node(int, const struct pf_altq_node *, + unsigned, int); +void print_cbqstats(class_stats_t); +void pfctl_free_altq_node(struct pf_altq_node *); +void pfctl_print_altq_nodestat(int, + const struct pf_altq_node *); + +int +pfctl_show_altq(int dev, int opts) +{ + struct pf_altq_node *root = NULL, *node; + + if (pfctl_update_qstats(dev, &root)) + return (-1); + + for (node = root; node != NULL; node = node->next) + pfctl_print_altq_node(dev, node, 0, opts & PF_OPT_VERBOSE); + pfctl_free_altq_node(root); + return (0); +} + +int +pfctl_update_qstats(int dev, struct pf_altq_node **root) +{ + struct pf_altq_node *node; + struct pfioc_altq pa; + struct pfioc_qstats pq; + u_int32_t mnr, nr; + union class_stats qstats; + + memset(&pa, 0, sizeof(pa)); + memset(&pq, 0, sizeof(pq)); + memset(&qstats, 0, sizeof(qstats)); + if (ioctl(dev, DIOCGETALTQS, &pa)) { + warn("DIOCGETALTQS"); + return (-1); + } + mnr = pa.nr; + for (nr = 0; nr < mnr; ++nr) { + pa.nr = nr; + if (ioctl(dev, DIOCGETALTQ, &pa)) { + warn("DIOCGETALTQ"); + return (-1); + } + if (pa.altq.qid > 0) { + pq.nr = nr; + pq.ticket = pa.ticket; + pq.buf = &qstats; + pq.nbytes = sizeof(qstats); + if (ioctl(dev, DIOCGETQSTATS, &pq)) { + warn("DIOCGETQSTATS"); + return (-1); + } + gettimeofday(&qstats.timestamp, NULL); + if ((node = pfctl_find_altq_node(*root, pa.altq.qname, + pa.altq.ifname)) != NULL) { + memcpy(&node->qstats_last, &node->qstats, + sizeof(union class_stats)); + memcpy(&node->qstats, &qstats, + sizeof(union class_stats)); + } else + pfctl_insert_altq_node(root, pa.altq, qstats); + } + } + return (0); +} + +void +pfctl_insert_altq_node(struct pf_altq_node **root, + const struct pf_altq altq, const union class_stats qstats) +{ + struct pf_altq_node *node; + + node = calloc(1, sizeof(struct pf_altq_node)); + if (node == NULL) { + errx(1, "pfctl_insert_altq_node: calloc"); + return; + } + memcpy(&node->altq, &altq, sizeof(struct pf_altq)); + memcpy(&node->qstats, &qstats, sizeof(union class_stats)); + node->next = node->children = NULL; + + if (*root == NULL) + *root = node; + else if (!altq.parent[0]) { + struct pf_altq_node *prev = *root; + + while (prev->next != NULL) + prev = prev->next; + prev->next = node; + } else { + struct pf_altq_node *parent; + + parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname); + if (parent == NULL) { + errx(1, "parent %s not found", altq.parent); + return; + } + if (parent->children == NULL) + parent->children = node; + else { + struct pf_altq_node *prev = parent->children; + + while (prev->next != NULL) + prev = prev->next; + prev->next = node; + } + } +} + +struct pf_altq_node * +pfctl_find_altq_node(struct pf_altq_node *root, const char *qname, + const char *ifname) +{ + struct pf_altq_node *node, *child; + + for (node = root; node != NULL; node = node->next) { + if (!strcmp(node->altq.qname, qname) + && !(strcmp(node->altq.ifname, ifname))) + return (node); + if (node->children != NULL) { + child = pfctl_find_altq_node(node->children, qname, + ifname); + if (child != NULL) + return (child); + } + } + return (NULL); +} + +void +pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level, + int verbose) +{ + const struct pf_altq_node *child; + + if (node == NULL) + return; + + print_altq(&node->altq, level); + + if (node->children != NULL) { + printf("{"); + for (child = node->children; child != NULL; + child = child->next) { + printf("%s", child->altq.qname); + if (child->next != NULL) + printf(", "); + } + printf("}"); + } + printf("\n"); + + if (verbose) + pfctl_print_altq_nodestat(dev, node); + + for (child = node->children; child != NULL; + child = child->next) + pfctl_print_altq_node(dev, child, level+1, verbose); +} + +void +pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a) +{ + if (a->altq.qid == 0) + return; + + switch (a->altq.scheduler) { + case ALTQT_CBQ: + print_cbqstats(a->qstats.cbq_stats); + break; + case ALTQT_PRIQ: + break; + } +} + +void +print_cbqstats(class_stats_t qstats) +{ + printf("[ pkts: %10llu bytes: %10llu " + "dropped pkts: %6llu bytes: %6llu ]\n", + qstats.xmit_cnt.packets, qstats.xmit_cnt.bytes, + qstats.drop_cnt.packets, qstats.drop_cnt.bytes); + printf("[ qcount: %3d/%3d borrows: %6u suspends: %6u ]\n", + qstats.qcnt, qstats.qmax, qstats.borrows, qstats.delays); +} + + +void +pfctl_free_altq_node(struct pf_altq_node *node) +{ + while (node != NULL) { + struct pf_altq_node *prev; + + if (node->children != NULL) + pfctl_free_altq_node(node->children); + prev = node; + node = node->next; + free(prev); + } +} |