diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2002-11-18 22:49:16 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2002-11-18 22:49:16 +0000 |
commit | 01ef9d16c38b163d3c0ff2b7acf62320a761e02e (patch) | |
tree | dc08b27c8ceac5342b0d765c949abca499288ec1 /sbin/pfctl | |
parent | 323c41ca9bc0986dc2a83bb659368c38dfaf02e1 (diff) |
altq and pf merged
this isn't 100% done yet: the print_ stuff isn't finished, some features
will be added later, and there is no documetation yet, but committing now
enables a few more people to work on.
print_altq_node stuff hacked by Daniel at euroBSDcon; lotsa stuff from kjc,
debugging help also pb and camiel. lots of good ideas by theo.
"commit now" theo philipp daniel
Diffstat (limited to 'sbin/pfctl')
-rw-r--r-- | sbin/pfctl/Makefile | 10 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 334 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 111 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_altq.c | 593 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_altq.h | 104 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 4 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.h | 6 |
7 files changed, 1152 insertions, 10 deletions
diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile index bbf184e5364..57253ec473b 100644 --- a/sbin/pfctl/Makefile +++ b/sbin/pfctl/Makefile @@ -1,9 +1,13 @@ -# $OpenBSD: Makefile,v 1.8 2002/09/14 17:51:53 henning Exp $ +# $OpenBSD: Makefile,v 1.9 2002/11/18 22:49:15 henning Exp $ PROG= pfctl -SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c -CFLAGS+= -Wall +SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c +CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized +CFLAGS+= -Wstrict-prototypes YFLAGS= MAN= pfctl.8 + +LDADD+= -lm +DPADD+= ${LIBM} .include <bsd.prog.mk> diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index ecc9b9c1aca..60a9019ead0 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.186 2002/11/13 22:44:11 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.187 2002/11/18 22:49:15 henning Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -50,6 +50,7 @@ #include <grp.h> #include "pfctl_parser.h" +#include "pfctl_altq.h" static struct pfctl *pf = NULL; static FILE *fin = NULL; @@ -153,6 +154,26 @@ struct peer { struct node_port *port; }; +struct node_queue { + char queue[PF_QNAME_SIZE]; + char parent[PF_QNAME_SIZE]; + char ifname[IFNAMSIZ]; + struct node_queue *next; + struct node_queue *tail; +} *queues = NULL; + +struct node_queue_opt { + int qtype; + union { /* options for other schedulers will follow */ + struct cbq_opts cbq_opts; + } data; +}; + +struct node_queue_bw { + u_int32_t bw_absolute; + u_int16_t bw_percent; +}; + int yyerror(char *, ...); int rule_consistent(struct pf_rule *); int nat_consistent(struct pf_nat *); @@ -176,6 +197,9 @@ void expand_rule(struct pf_rule *, struct node_if *, struct node_proto *, struct node_host *, struct node_port *, struct node_host *, struct node_port *, struct node_uid *, struct node_gid *, struct node_icmp *); +void expand_altq(struct pf_altq *, struct node_if *, struct node_queue *); +int expand_queue(struct pf_altq *, struct node_queue *, + struct node_queue_bw); int check_rulestate(int); int kw_cmp(const void *, const void *); int lookup(char *); @@ -187,7 +211,6 @@ struct node_host *host(char *, int); int atoul(char *, u_long *); int getservice(char *); - struct sym { struct sym *next; int used; @@ -251,6 +274,9 @@ typedef struct { u_int8_t log; u_int8_t quick; } logquick; + struct node_queue *queue; + struct node_queue_opt queue_options; + struct node_queue_bw queue_bwspec; } v; int lineno; } YYSTYPE; @@ -266,6 +292,9 @@ typedef struct { %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY %token REQUIREORDER YES %token ANTISPOOF FOR +%token ALTQ SCHEDULER CBQ BANDWIDTH TBRSIZE +%token QUEUE PRIORITY QLIMIT +%token DEFAULT CONTROL BORROW RED ECN RIO %token <v.string> STRING %token <v.i> PORTUNARY PORTBINARY %type <v.interface> interface if_list if_item_not if_item @@ -289,6 +318,12 @@ typedef struct { %type <v.state_opt> state_opt_spec state_opt_list state_opt_item %type <v.logquick> logquick %type <v.interface> antispoof_ifspc antispoof_iflst +%type <v.number> priority qlimit tbrsize +%type <v.string> qname +%type <v.queue> qassign qassign_list qassign_item +%type <v.queue_options> schedtype +%type <v.number> cbqflags_list cbqflags_item +%type <v.queue_bwspec> bandwidth %% ruleset : /* empty */ @@ -299,6 +334,8 @@ ruleset : /* empty */ | ruleset binatrule '\n' | ruleset rdrrule '\n' | ruleset pfrule '\n' + | ruleset altqif '\n' + | ruleset queuespec '\n' | ruleset varset '\n' | ruleset antispoof '\n' | ruleset error '\n' { errors++; } @@ -467,8 +504,169 @@ antispoof_iflst : if_item { $$ = $1; } } ; + +/* altq stuff */ + +altqif : ALTQ interface SCHEDULER schedtype bandwidth tbrsize + qassign { + struct pf_altq a; + + memset(&a, 0, sizeof(a)); + if ($4.qtype == ALTQT_NONE) { + yyerror("no scheduler specified!"); + YYERROR; + } + a.scheduler = $4.qtype; + a.pq_u.cbq_opts.flags = $4.data.cbq_opts.flags; + if ((a.ifbandwidth = $5.bw_absolute) == 0) { + yyerror("interface bandwidth must be absolute"); + YYERROR; + } + a.tbrsize = $6; + expand_altq(&a, $2, $7); + } + ; + +qassign : /* empty */ { $$ = NULL; } + | QUEUE qassign_item { $$ = $2; } + | QUEUE '{' qassign_list '}' { $$ = $3; } + ; + +qassign_list : qassign_item { $$ = $1; } + | qassign_list comma qassign_item { + $1->tail->next = $3; + $1->tail = $3; + $$ = $1; + } + ; + +qassign_item : STRING { + $$ = malloc(sizeof(struct node_queue)); + if ($$ == NULL) + err(1, "queue_item: malloc"); + strlcpy($$->queue, $1, PF_QNAME_SIZE); + $$->next = NULL; + $$->tail = $$; + } + ; + +queuespec : QUEUE STRING bandwidth priority qlimit schedtype qassign { + struct pf_altq a; + + memset(&a, 0, sizeof(a)); + + if (strlen($2) >= PF_QNAME_SIZE) { + yyerror("queue name too long (max " + "%d chars)", PF_QNAME_SIZE-1); + YYERROR; + } + strlcpy(a.qname, $2, sizeof(a.qname)); + if ($4 > 255) { + yyerror("priority out of range: max 255"); + YYERROR; + } + a.priority = $4; + a.qlimit = $5; + a.scheduler = $6.qtype; + a.pq_u.cbq_opts.flags = $6.data.cbq_opts.flags; + if (expand_queue(&a, $7, $3)) + YYERROR; + + } + ; + +schedtype : /* empty */ { $$.qtype = ALTQT_NONE; } + | CBQ { $$.qtype = ALTQT_CBQ; } + | CBQ '(' cbqflags_list ')' { + $$.qtype = ALTQT_CBQ; + $$.data.cbq_opts.flags = $3; + } + ; + +cbqflags_list : cbqflags_item { $$ |= $1; } + | cbqflags_list comma cbqflags_item { $$ |= $3; } + ; + + +cbqflags_item : DEFAULT { $$ = CBQCLF_DEFCLASS; } + | CONTROL { $$ = CBQCLF_CTLCLASS; } + | BORROW { $$ = CBQCLF_BORROW; } + | RED { $$ = CBQCLF_RED; } + | ECN { $$ = CBQCLF_RED|CBQCLF_ECN; } + | RIO { $$ = CBQCLF_RIO; } + ; + +bandwidth : /* empty */ { + $$.bw_absolute = 0; + $$.bw_percent = 0; + } + | BANDWIDTH STRING { + double bps; + char *cp; + + $$.bw_percent = 0; + + bps = strtod($2, &cp); + if (cp != NULL) { + if (!strcmp(cp, "b")) { + /* nothing */ + } else if (!strcmp(cp, "Kb")) + bps *= 1024; + else if (!strcmp(cp, "Mb")) + bps *= 1024 * 1024; + else if (!strcasecmp(cp, "Gb")) + bps *= 1024 * 1024 * 1024; + else if (*cp == '%') { + if (bps < 0 || bps > 100) { + yyerror("bandwidth spec " + "out of range"); + YYERROR; + } + $$.bw_percent = bps; + bps = 0; + } else { + yyerror("unknown unit %s", cp); + YYERROR; + } + } + $$.bw_absolute = (u_int32_t)bps; + } + ; + +priority : /* empty */ { $$ = 0; } + | PRIORITY number { + if ($2 > 255) { + yyerror("priority out of range: max 255"); + YYERROR; + } + $$ = $2; + } + ; + +qlimit : /* empty */ { $$ = 0; } + | QLIMIT number { + if ($2 > 65535) { + yyerror("qlimit out of range: max 65535"); + YYERROR; + } + $$ = $2; + } + ; + + +tbrsize : /* empty */ { $$ = 0; } + | number { + if ($1 > 65535) { + yyerror("tbrsize too big: max 65535"); + YYERROR; + } + $$ = $1; + } + ; + pfrule : action dir logquick interface route af proto fromto uids gids flags icmpspec tos keep fragment allowopts label + qname { struct pf_rule r; struct node_state_opt *o; @@ -585,6 +783,16 @@ pfrule : action dir logquick interface route af proto fromto free($17); } + if ($18) { + if (strlen($18) >= PF_QNAME_SIZE) { + yyerror("rule qname too long (max " + "%d chars)", PF_QNAME_SIZE-1); + YYERROR; + } + strlcpy(r.qname, $18, sizeof(r.qname)); + free($18); + } + expand_rule(&r, $4, $7, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9, $10, $12); } @@ -1328,6 +1536,14 @@ label : /* empty */ { $$ = NULL; } } } ; +qname : /* empty */ { $$ = NULL; } + | QUEUE STRING { + if (($$ = strdup($2)) == NULL) { + yyerror("qname strdup() failed"); + YYERROR; + } + } + ; no : /* empty */ { $$ = 0; } | NO { $$ = 1; } @@ -2056,6 +2272,102 @@ expand_label(char *label, const char *ifname, sa_family_t af, } void +expand_altq(struct pf_altq *a, struct node_if *interfaces, + struct node_queue *nqueues) +{ + struct pf_altq pa, pb; + char qname[PF_QNAME_SIZE]; + struct node_queue *n; + + LOOP_THROUGH(struct node_if, interface, interfaces, + memcpy(&pa, a, sizeof(struct pf_altq)); + strlcpy(pa.ifname, interface->ifname, IFNAMSIZ); + + if (interface->not) + yyerror("altq on ! <interface> is not supported"); + else { + eval_pfaltq(pf, &pa); + pfctl_add_altq(pf, &pa); + + /* now create a root queue */ + memset(&pb, 0, sizeof(struct pf_altq)); + strlcpy(qname, "root_", sizeof(qname)); + strlcat(qname, interface->ifname, sizeof(qname)); + strlcpy(pb.qname, qname, PF_QNAME_SIZE); + strlcpy(pb.ifname, interface->ifname, IFNAMSIZ); + pb.qlimit = pa.qlimit; + pb.scheduler = pa.scheduler; + pb.pq_u.cbq_opts.flags = pa.pq_u.cbq_opts.flags; + eval_pfqueue(pf, &pb, pa.ifbandwidth, 0); + pfctl_add_altq(pf, &pb); + + LOOP_THROUGH(struct node_queue, queue, nqueues, + n = calloc(1, sizeof(struct node_queue)); + if (n == NULL) + err(1, "expand_altq: malloc"); + strlcpy(n->parent, qname, PF_QNAME_SIZE); + strlcpy(n->queue, queue->queue, PF_QNAME_SIZE); + strlcpy(n->ifname, interface->ifname, IFNAMSIZ); + n->next = NULL; + n->tail = n; + if (queues == NULL) + queues = n; + else { + queues->tail->next = n; + queues->tail = n; + } + ); + } + ); + FREE_LIST(struct node_if, interfaces); + FREE_LIST(struct node_queue, nqueues); +} + +int +expand_queue(struct pf_altq *a, struct node_queue *nqueues, + struct node_queue_bw bwspec) +{ + struct node_queue *n; + u_int8_t added = 0; + + LOOP_THROUGH(struct node_queue, tqueue, queues, + if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE)) { + /* found ourselve in queues */ + LOOP_THROUGH(struct node_queue, queue, nqueues, + n = malloc(sizeof(struct node_queue)); + if (n == NULL) + err(1, "expand_queue: malloc"); + strlcpy(n->parent, a->qname, PF_QNAME_SIZE); + strlcpy(n->queue, queue->queue, PF_QNAME_SIZE); + strlcpy(n->ifname, tqueue->ifname, IFNAMSIZ); + n->next = NULL; + n->tail = n; + if (queues == NULL) + queues = n; + else { + queues->tail->next = n; + queues->tail = n; + } + ); + FREE_LIST(struct node_queue, nqueues); + strlcpy(a->ifname, tqueue->ifname, IFNAMSIZ); + strlcpy(a->parent, tqueue->parent, PF_QNAME_SIZE); + + eval_pfqueue(pf, a, bwspec.bw_absolute, + bwspec.bw_percent); + pfctl_add_altq(pf, a); + added++; + } + ); + + if (!added) { + yyerror("queue has no parent"); + return (1); + } else + return (0); +} + +void expand_rule(struct pf_rule *r, struct node_if *interfaces, struct node_proto *protos, struct node_host *src_hosts, struct node_port *src_ports, @@ -2067,9 +2379,11 @@ expand_rule(struct pf_rule *r, int nomatch = 0, added = 0; char ifname[IF_NAMESIZE]; char label[PF_RULE_LABEL_SIZE]; + char qname[PF_QNAME_SIZE]; u_int8_t flags, flagset; strlcpy(label, r->label, sizeof(label)); + strlcpy(qname, r->qname, sizeof(qname)); flags = r->flags; flagset = r->flagset; @@ -2111,6 +2425,8 @@ expand_rule(struct pf_rule *r, strlcpy(r->label, label, PF_RULE_LABEL_SIZE); expand_label(r->label, r->ifname, r->af, src_host, src_port, dst_host, dst_port, proto->proto); + strlcpy(r->qname, qname, PF_QNAME_SIZE); + r->qid = qname_to_qid(qname, r->ifname); r->ifnot = interface->not; r->proto = proto->proto; r->src.addr = src_host->addr; @@ -2343,16 +2659,23 @@ lookup(char *s) static const struct keywords keywords[] = { { "all", ALL}, { "allow-opts", ALLOWOPTS}, + { "altq", ALTQ}, { "antispoof", ANTISPOOF}, { "any", ANY}, + { "bandwidth", BANDWIDTH}, { "binat", BINAT}, { "block", BLOCK}, { "block-policy", BLOCKPOLICY}, + { "borrow", BORROW}, + { "cbq", CBQ}, { "code", CODE}, + { "control", CONTROL}, { "crop", FRAGCROP}, + { "default", DEFAULT}, { "drop", DROP}, { "drop-ovl", FRAGDROP}, { "dup-to", DUPTO}, + { "ecn", ECN}, { "fastroute", FASTROUTE}, { "flags", FLAGS}, { "for", FOR}, @@ -2383,20 +2706,27 @@ lookup(char *s) { "out", OUT}, { "pass", PASS}, { "port", PORT}, + { "priority", PRIORITY}, { "proto", PROTO}, + { "qlimit", QLIMIT}, + { "queue", QUEUE}, { "quick", QUICK}, { "rdr", RDR}, { "reassemble", FRAGNORM}, + { "red", RED}, { "reply-to", REPLYTO}, { "require-order", REQUIREORDER}, { "return", RETURN}, { "return-icmp",RETURNICMP}, { "return-icmp6",RETURNICMP6}, { "return-rst", RETURNRST}, + { "rio", RIO}, { "route-to", ROUTETO}, + { "scheduler", SCHEDULER}, { "scrub", SCRUB}, { "set", SET}, { "state", STATE}, + { "tbrsize", TBRSIZE}, { "timeout", TIMEOUT}, { "to", TO}, { "tos", TOS}, diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 071b103cba1..2d4f1826279 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.85 2002/10/07 14:34:40 dhartmei Exp $ */ +/* $OpenBSD: pfctl.c,v 1.86 2002/11/18 22:49:15 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -51,6 +51,7 @@ #include "pfctl_parser.h" #include "pf_print_state.h" +#include "pfctl_altq.h" void usage(void); int pfctl_enable(int, int); @@ -58,10 +59,12 @@ int pfctl_disable(int, int); int pfctl_clear_stats(int, int); int pfctl_clear_rules(int, int); int pfctl_clear_nat(int, int); +int pfctl_clear_altq(int, int); int pfctl_clear_states(int, int); int pfctl_kill_states(int, int); int pfctl_show_rules(int, int, int); int pfctl_show_nat(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); @@ -148,7 +151,7 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-deqhnNrROvz] [-f file] ", __progname); + fprintf(stderr, "usage: %s [-AdeqhnNrROvz] [-f file] ", __progname); fprintf(stderr, "[-F modifier] [-k host]\n"); fprintf(stderr, " "); fprintf(stderr, "[-s modifier] [-x level]\n"); @@ -166,6 +169,16 @@ pfctl_enable(int dev, int opts) } if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "pf enabled\n"); + + if (ioctl(dev, DIOCSTARTALTQ)) { + if (errno == EEXIST) + errx(1, "altq already enabled"); + else + err(1, "DIOCSTARTALTQ"); + } + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "altq enabled\n"); + return (0); } @@ -180,6 +193,16 @@ pfctl_disable(int dev, int opts) } if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "pf disabled\n"); + + if (ioctl(dev, DIOCSTOPALTQ)) { + if (errno == ENOENT) + errx(1, "altq not enabled"); + else + err(1, "DIOCSTOPALTQ"); + } + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "altq disabled\n"); + return (0); } @@ -232,6 +255,20 @@ pfctl_clear_nat(int dev, int opts) } int +pfctl_clear_altq(int dev, int opts) +{ + struct pfioc_altq pa; + + if (ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) + err(1, "DIOCBEGINALTQS"); + else if (ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) + err(1, "DIOCCOMMITALTQS"); + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "altq cleared\n"); + return (0); +} + +int pfctl_clear_states(int dev, int opts) { if (ioctl(dev, DIOCCLRSTATES)) @@ -384,6 +421,33 @@ 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 (ioctl(dev, DIOCGETALTQS, &pa)) { + warnx("DIOCGETALTQS"); + return (-1); + } + mnr = pa.nr; + for (nr = 0; nr < mnr; ++nr) { + pa.nr = nr; + if (ioctl(dev, DIOCGETALTQ, &pa)) { + warnx("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) { struct pfioc_nat pn; @@ -583,6 +647,24 @@ pfctl_add_rdr(struct pfctl *pf, struct pf_rdr *r) } int +pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) +{ + if ((loadopt & (PFCTL_FLAG_ALTQ | PFCTL_FLAG_ALL)) != 0) { + memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); + if ((pf->opts & PF_OPT_NOACTION) == 0) { + if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) + err(1, "DIOCADDALTQ"); + } + pfaltq_store(&pf->paltq->altq); + if (pf->opts & PF_OPT_VERBOSE) { + print_altq(&pf->paltq->altq, 0); + printf("\n"); + } + } + return (0); +} + +int pfctl_rules(int dev, char *filename, int opts) { FILE *fin; @@ -590,6 +672,7 @@ pfctl_rules(int dev, char *filename, int opts) struct pfioc_binat pb; struct pfioc_rdr pr; struct pfioc_rule pl; + struct pfioc_altq pa; struct pfctl pf; if (strcmp(filename, "-") == 0) { @@ -612,6 +695,9 @@ pfctl_rules(int dev, char *filename, int opts) if (ioctl(dev, DIOCBEGINBINATS, &pb.ticket)) err(1, "DIOCBEGINBINATS"); } + if (((loadopt & (PFCTL_FLAG_ALTQ | PFCTL_FLAG_ALL)) != 0) && + ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) + err(1, "DIOCBEGINALTQS"); if (((loadopt & (PFCTL_FLAG_FILTER | PFCTL_FLAG_ALL)) != 0) && ioctl(dev, DIOCBEGINRULES, &pl.ticket)) err(1, "DIOCBEGINRULES"); @@ -622,10 +708,14 @@ pfctl_rules(int dev, char *filename, int opts) pf.pnat = &pn; pf.pbinat = &pb; pf.prdr = ≺ + pf.paltq = &pa; pf.prule = &pl; pf.rule_nr = 0; if (parse_rules(fin, &pf) < 0) errx(1, "Syntax error in file: pf rules not loaded"); + if ((loadopt & (PFCTL_FLAG_ALTQ | PFCTL_FLAG_ALL)) != 0) + if (check_commit_altq(dev, opts) != 0) + errx(1, "errors in altq config"); if ((opts & PF_OPT_NOACTION) == 0) { if ((loadopt & (PFCTL_FLAG_NAT | PFCTL_FLAG_ALL)) != 0) { if (ioctl(dev, DIOCCOMMITNATS, &pn.ticket)) @@ -635,6 +725,9 @@ pfctl_rules(int dev, char *filename, int opts) if (ioctl(dev, DIOCCOMMITBINATS, &pb.ticket)) err(1, "DIOCCOMMITBINATS"); } + if (((loadopt & (PFCTL_FLAG_ALTQ | PFCTL_FLAG_ALL)) != 0) && + ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) + err(1, "DIOCCOMMITALTQS"); if (((loadopt & (PFCTL_FLAG_FILTER | PFCTL_FLAG_ALL)) != 0) && ioctl(dev, DIOCCOMMITRULES, &pl.ticket)) err(1, "DIOCCOMMITRULES"); @@ -805,7 +898,7 @@ main(int argc, char *argv[]) if (argc < 2) usage(); - while ((ch = getopt(argc, argv, "deqf:F:hk:nNOrRs:Svx:z")) != -1) { + while ((ch = getopt(argc, argv, "Adeqf:F:hk:nNOrRs:Svx:z")) != -1) { switch (ch) { case 'd': opts |= PF_OPT_DISABLE; @@ -845,6 +938,10 @@ main(int argc, char *argv[]) rulesopt = optarg; mode = O_RDWR; break; + case 'A': + loadopt &= ~PFCTL_FLAG_ALL; + loadopt |= PFCTL_FLAG_ALTQ; + break; case 'R': loadopt &= ~PFCTL_FLAG_ALL; loadopt |= PFCTL_FLAG_FILTER; @@ -905,6 +1002,9 @@ main(int argc, char *argv[]) case 'n': pfctl_clear_nat(dev, opts); break; + case 'q': + pfctl_clear_altq(dev, opts); + break; case 's': pfctl_clear_states(dev, opts); break; @@ -914,6 +1014,7 @@ main(int argc, char *argv[]) case 'a': pfctl_clear_rules(dev, opts); pfctl_clear_nat(dev, opts); + pfctl_clear_altq(dev, opts); pfctl_clear_states(dev, opts); pfctl_clear_stats(dev, opts); break; @@ -940,6 +1041,9 @@ main(int argc, char *argv[]) case 'n': pfctl_show_nat(dev); break; + case 'q': + pfctl_show_altq(dev); + break; case 's': pfctl_show_states(dev, 0, opts); break; @@ -955,6 +1059,7 @@ main(int argc, char *argv[]) case 'a': pfctl_show_rules(dev, opts, 0); pfctl_show_nat(dev); + pfctl_show_altq(dev); pfctl_show_states(dev, 0, opts); pfctl_show_status(dev); pfctl_show_rules(dev, opts, 1); diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c new file mode 100644 index 00000000000..8ebcbc66443 --- /dev/null +++ b/sbin/pfctl/pfctl_altq.c @@ -0,0 +1,593 @@ +/* $OpenBSD: pfctl_altq.c,v 1.1 2002/11/18 22:49:15 henning Exp $ */ +/* + * Copyright (C) 2002 + * Sony Computer Science Laboratories Inc. All rights reserved. + * Copyright (C) 2002 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: + * 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/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <net/pfvar.h> + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <math.h> + +#include <altq/altq.h> +#include <altq/altq_cbq.h> + +#include "pfctl_parser.h" +#include "pfctl_altq.h" + +static int eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *); +static int cbq_compute_idletime(struct pfctl *, struct pf_altq *); +static int check_commit_cbq(int, int, struct pf_altq *); +static void print_cbq_opts(const struct pf_altq *); +static char *rate2str(double); + +TAILQ_HEAD(altqs, pf_altq) altqs = TAILQ_HEAD_INITIALIZER(altqs); + +void +pfaltq_store(struct pf_altq *a) +{ + struct pf_altq *altq; + + if ((altq = malloc(sizeof(*altq))) == NULL) + err(1, "malloc"); + memcpy(altq, a, sizeof(struct pf_altq)); + TAILQ_INSERT_TAIL(&altqs, altq, entries); +} + +void +pfaltq_free(struct pf_altq *a) +{ + struct pf_altq *altq; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(a->ifname, altq->ifname, IFNAMSIZ) == 0 + && strncmp(a->qname, altq->qname, PF_QNAME_SIZE) == 0) { + TAILQ_REMOVE(&altqs, altq, entries); + free(altq); + return; + } + } +} + +struct pf_altq * +pfaltq_lookup(const char *ifname) +{ + struct pf_altq *altq; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 + && altq->qname[0] == 0) + return (altq); + } + return (NULL); +} + +struct pf_altq * +qname_to_pfaltq(const char *qname, const char *ifname) +{ + struct pf_altq *altq; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && + strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) + return (altq); + } + return (NULL); +} + +u_int32_t +qname_to_qid(const char *qname, const char *ifname) +{ + struct pf_altq *altq; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && + strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0) + return (altq->qid); + } + return (0); +} + +char * +qid_to_qname(u_int32_t qid, const char *ifname) +{ + struct pf_altq *altq; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 && + altq->qid == qid) + return (altq->qname); + } + return (NULL); +} + +void +print_altq(const struct pf_altq *a, unsigned level) +{ + unsigned i; + + if (a->qname[0] != NULL) { + print_queue(a, level); + return; + } + + for (i = 0; i < level; ++i) + printf(" "); + printf("altq on %s scheduler %u bandwidth %s tbrsize %u", + a->ifname, a->scheduler, rate2str((double)a->ifbandwidth), + a->tbrsize); +} + +void +print_queue(const struct pf_altq *a, unsigned level) +{ + unsigned i; + + for (i = 0; i < level; ++i) + printf(" "); + printf("queue %s bandwidth %s priority %u", a->qname, + rate2str((double)a->bandwidth), a->priority); +/* printf("queue on %s %s parent 0x%x priority %u bandwidth %s" + " qlimit %u qid 0x%x\n", + a->ifname, a->qname, a->parent_qid, a->priority, + rate2str((double)a->bandwidth), a->qlimit, a->qid); */ + switch (a->scheduler) { + case ALTQT_CBQ: + print_cbq_opts(a); + break; + } +} + +int +eval_pfaltq(struct pfctl *pf, struct pf_altq *pa) +{ + u_int rate, size; + + /* if tbrsize is not specified, use heuristics */ + if (pa->tbrsize == 0) { + rate = pa->ifbandwidth; + if (rate <= 1 * 1024 * 1024) + size = 1; + else if (rate <= 10 * 1024 * 1024) + size = 4; + else if (rate <= 200 * 1024 * 1024) + size = 8; + else + size = 24; + size = size * 1500; /* assume the default mtu is 1500 */ + pa->tbrsize = size; + } + return (0); +} + +int +check_commit_altq(int dev, int opts) +{ + struct pf_altq *altq; + int error = 0; + + TAILQ_FOREACH(altq, &altqs, entries) { + if (altq->qname[0] == 0) { + switch (altq->scheduler) { + case ALTQT_CBQ: + error = check_commit_cbq(dev, opts, altq); + break; + default: + break; + } + } + } + return (error); +} + +int +eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, u_int32_t bw_absolute, + u_int16_t bw_percent) +{ + /* should be merged with expand_queue */ + struct pf_altq *if_pa, *parent; + int error = 0; + + /* find the corresponding interface and copy fields used by queues */ + if_pa = pfaltq_lookup(pa->ifname); + if (if_pa == NULL) + errx(1, "altq not defined on %s", pa->ifname); + pa->scheduler = if_pa->scheduler; + pa->ifbandwidth = if_pa->ifbandwidth; + + parent = NULL; + if (pa->parent[0] != 0) { + parent = qname_to_pfaltq(pa->parent, pa->ifname); + if (parent == NULL) + errx(1, "parent %s not found for %s", + pa->parent, pa->qname); + pa->parent_qid = parent->qid; + } + if (pa->qlimit == 0) + pa->qlimit = 50; + + if (bw_absolute > 0) + pa->bandwidth = bw_absolute; + else if (bw_percent > 0 && parent != NULL) + pa->bandwidth = parent->bandwidth / 100 * bw_percent; + else + errx(1, "bandwidth for %s invalid (%d / %d)", pa->qname, bw_absolute, bw_percent); + + /* + * admission control: bandwidth should be smaller than the + * interface bandwidth and the parent bandwidth + */ + if (pa->bandwidth > pa->ifbandwidth) + errx(1, "bandwidth for %s higher than interface", pa->qname); + if (parent != NULL && pa->bandwidth > parent->bandwidth) + errx(1, "bandwidth for %s higher than parent", pa->qname); + + switch (pa->scheduler) { + case ALTQT_CBQ: + error = eval_pfqueue_cbq(pf, pa); + break; + default: + break; + } + return (error); +} + +/* + * CBQ support functions + */ +#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */ +#define RM_NS_PER_SEC (1000000000) + +static int +eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa) +{ + struct cbq_opts *opts; + u_int ifmtu; + +#if 1 + ifmtu = 1500; /* should be obtained from the interface */ +#endif + opts = &pa->pq_u.cbq_opts; + + if (opts->pktsize == 0) { /* use default */ + opts->pktsize = ifmtu; + if (opts->pktsize > MCLBYTES) /* do what TCP does */ + opts->pktsize &= ~MCLBYTES; + } else if (opts->pktsize > ifmtu) + opts->pktsize = ifmtu; + if (opts->maxpktsize == 0) /* use default */ + opts->maxpktsize = ifmtu; + else if (opts->maxpktsize > ifmtu) + opts->pktsize = ifmtu; + + if (opts->pktsize > opts->maxpktsize) + opts->pktsize = opts->maxpktsize; + + if (pa->parent[0] == 0 || strcasecmp("NULL", pa->parent) == 0) + opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR); + + cbq_compute_idletime(pf, pa); + + return (0); +} + +/* + * compute ns_per_byte, maxidle, minidle, and offtime + */ +static int +cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa) +{ + struct cbq_opts *opts; + double maxidle_s, maxidle, minidle, + offtime, nsPerByte, ifnsPerByte, ptime, cptime; + double z, g, f, gton, gtom, maxrate; + u_int minburst, maxburst; + + opts = &pa->pq_u.cbq_opts; + ifnsPerByte = (1.0 / (double)pa->ifbandwidth) * RM_NS_PER_SEC * 8; + minburst = opts->minburst; + maxburst = opts->maxburst; + + if (pa->bandwidth == 0) + f = 0.0001; /* small enough? */ + else + f = ((double) pa->bandwidth / (double) pa->ifbandwidth); + + nsPerByte = ifnsPerByte / f; + ptime = (double)opts->pktsize * ifnsPerByte; + maxrate = f * ((double)pa->ifbandwidth / 8.0); + cptime = ptime * (1.0 - f) / f; + + if (nsPerByte * (double)opts->maxpktsize > (double)INT_MAX) { + /* + * this causes integer overflow in kernel! + * (bandwidth < 6Kbps when max_pkt_size=1500) + */ + if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "cbq: class %s is too slow!\n", + pa->qname); + nsPerByte = (double)(INT_MAX / opts->maxpktsize); + } + + if (maxburst == 0) { /* use default */ + if (cptime > 10.0 * 1000000) + maxburst = 4; + else + maxburst = 16; + } + if (minburst == 0) /* use default */ + minburst = 2; + if (minburst > maxburst) + minburst = maxburst; + + z = (double)(1 << RM_FILTER_GAIN); + g = (1.0 - 1.0 / z); + gton = pow(g, (double)maxburst); + gtom = pow(g, (double)(minburst-1)); + maxidle = ((1.0 / f - 1.0) * ((1.0 - gton) / gton)); + maxidle_s = (1.0 - g); + if (maxidle > maxidle_s) + maxidle = ptime * maxidle; + else + maxidle = ptime * maxidle_s; + if (minburst) + offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom); + else + offtime = cptime; + minidle = -((double)opts->maxpktsize * (double)nsPerByte); + + /* scale parameters */ + maxidle = ((maxidle * 8.0) / nsPerByte) * pow(2, RM_FILTER_GAIN); + offtime = (offtime * 8.0) / nsPerByte * pow(2, RM_FILTER_GAIN); + minidle = ((minidle * 8.0) / nsPerByte) * pow(2, RM_FILTER_GAIN); + + maxidle = maxidle / 1000.0; + offtime = offtime / 1000.0; + minidle = minidle / 1000.0; + + opts->minburst = minburst; + opts->maxburst = maxburst; + opts->ns_per_byte = (u_int) nsPerByte; + opts->maxidle = (u_int) fabs(maxidle); + opts->minidle = (int)minidle; + opts->offtime = (u_int) fabs(offtime); + + return (0); +} + +static int +check_commit_cbq(int dev, int opts, struct pf_altq *pa) +{ + struct pf_altq *altq; + int root_class, default_class; + int error = 0; + + /* + * check if cbq has one root class and one default class + * for this interface + */ + root_class = default_class = 0; + TAILQ_FOREACH(altq, &altqs, entries) { + if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) + continue; + if (altq->qname[0] == 0) /* this is for interface */ + continue; + if (altq->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS) + root_class++; + if (altq->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS) + default_class++; + } + if (root_class != 1) { + warnx("should have one root class on %s", pa->ifname); + error++; + } + if (default_class != 1) { + warnx("should have one default class on %s", pa->ifname); + error++; + } + return (error); +} + +static void +print_cbq_opts(const struct pf_altq *a) +{ + const struct cbq_opts *opts; + + opts = &a->pq_u.cbq_opts; + +/* printf(" cbq options: minburst %u maxburst %u" + " pktsize %u maxpktsize %u\n", + opts->minburst, opts->maxburst, + opts->pktsize, opts->maxpktsize); + + printf(" ns_per_byte %u maxidle %u minidle %d offtime %u\n", + opts->ns_per_byte, opts->maxidle, opts->minidle, opts->offtime); +*/ + + if (opts->flags) { + printf(" cbq("); + if (opts->flags & CBQCLF_RED) + printf(" red"); + if (opts->flags & CBQCLF_ECN) + printf(" ecn"); + if (opts->flags & CBQCLF_RIO) + printf(" rio"); + if (opts->flags & CBQCLF_CLEARDSCP) + printf(" cleardscp"); + if (opts->flags & CBQCLF_FLOWVALVE) + printf(" flowvalve"); + if (opts->flags & CBQCLF_BORROW) + printf(" borrow"); + if (opts->flags & CBQCLF_WRR) + printf(" wrr"); + if (opts->flags & CBQCLF_EFFICIENT) + printf(" efficient"); + if (opts->flags & CBQCLF_ROOTCLASS) + printf(" root"); + if (opts->flags & CBQCLF_DEFCLASS) + printf(" default"); + printf(" )"); + } +} + +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) { + errx(1, "pfctl_insert_altq_node: calloc"); + return; + } + 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); + 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) +{ + struct pf_altq_node *node, *child; + + for (node = root; node != NULL; node = node->next) { + if (!strcmp(node->altq.qname, qname)) + return (node); + if (node->children != NULL) { + child = pfctl_find_altq_node(node->children, qname); + 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; + + if (node->altq.qname[0]) + print_altq(&node->altq, level); + else + print_queue(&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+2); +} + +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 + */ +#define R2S_BUFS 8 +#define RATESTR_MAX 16 +static char * +rate2str(double rate) +{ + char *buf; + static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */ + static int idx = 0; + + buf = r2sbuf[idx++]; + if (idx == R2S_BUFS) + idx = 0; + + if (rate == 0.0) + snprintf(buf, RATESTR_MAX, "0"); + else if (rate >= 1024 * 1024) + snprintf(buf, RATESTR_MAX, "%.2fMb", rate / (1024.0 * 1024.0)); + else if (rate >= 1024) + snprintf(buf, RATESTR_MAX, "%.2fKb", rate / 1024.0); + else + snprintf(buf, RATESTR_MAX, "%db", (int)rate); + return (buf); +} diff --git a/sbin/pfctl/pfctl_altq.h b/sbin/pfctl/pfctl_altq.h new file mode 100644 index 00000000000..a4288ad0449 --- /dev/null +++ b/sbin/pfctl/pfctl_altq.h @@ -0,0 +1,104 @@ +/* $OpenBSD: pfctl_altq.h,v 1.1 2002/11/18 22:49:15 henning Exp $ */ +/* + * Copyright (C) 2002 + * Sony Computer Science Laboratories Inc. All rights reserved. + * Copyright (C) 2002 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: + * 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. + */ + +/* + * misc defines needed by pfctl(8) for altq + * (copied from altq headers until we find a better way...) + */ +#ifndef ALTQT_NONE +/* altq discipline type */ +#define ALTQT_NONE 0 /* reserved */ +#define ALTQT_CBQ 1 /* cbq */ +#define ALTQT_WFQ 2 /* wfq */ +#define ALTQT_AFMAP 3 /* afmap */ +#define ALTQT_FIFOQ 4 /* fifoq */ +#define ALTQT_RED 5 /* red */ +#define ALTQT_RIO 6 /* rio */ +#define ALTQT_LOCALQ 7 /* local use */ +#define ALTQT_HFSC 8 /* hfsc */ +#define ALTQT_CDNR 9 /* traffic conditioner */ +#define ALTQT_BLUE 10 /* blue */ +#define ALTQT_PRIQ 11 /* priority queue */ +#define ALTQT_MAX 12 /* should be max discipline type + 1 */ +#endif + +#ifndef CBQCLF_RED +/* class flags shoud be same as class flags in rm_class.h */ +#define CBQCLF_RED 0x0001 /* use RED */ +#define CBQCLF_ECN 0x0002 /* use RED/ECN */ +#define CBQCLF_RIO 0x0004 /* use RIO */ +#define CBQCLF_FLOWVALVE 0x0008 /* use flowvalve (aka penalty-box) */ +#define CBQCLF_CLEARDSCP 0x0010 /* clear diffserv codepoint */ +#define CBQCLF_BORROW 0x0020 /* borrow from parent */ + +/* class flags only for root class */ +#define CBQCLF_WRR 0x0100 /* weighted-round robin */ +#define CBQCLF_EFFICIENT 0x0200 /* work-conserving */ + +/* class flags for special classes */ +#define CBQCLF_ROOTCLASS 0x1000 /* root class */ +#define CBQCLF_DEFCLASS 0x2000 /* default class */ +#define CBQCLF_CTLCLASS 0x4000 /* control class */ +#define CBQCLF_CLASSMASK 0xf000 /* class mask */ +#endif + +#ifndef REDF_ECN4 +/* red flags */ +#define REDF_ECN4 0x01 /* use packet marking for IPv4 packets */ +#define REDF_ECN6 0x02 /* use packet marking for IPv6 packets */ +#define REDF_ECN (REDF_ECN4 | REDF_ECN6) +#define REDF_FLOWVALVE 0x04 /* use flowvalve (aka penalty-box) */ +#endif + +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 *); +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 *); +struct pf_altq *pfaltq_lookup(const char *); +struct pf_altq *qname_to_pfaltq(const char *, const char *); +u_int32_t qname_to_qid(const char *, const char *); +char *qid_to_qname(u_int32_t, const char *); + +void print_altq(const struct pf_altq *, unsigned); +void print_queue(const struct pf_altq *, unsigned); + +int eval_pfaltq(struct pfctl *, struct pf_altq *); +int eval_pfqueue(struct pfctl *, struct pf_altq *, u_int32_t, u_int16_t); diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 6181a438eec..0400f34c4ae 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.102 2002/10/25 10:40:45 camield Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.103 2002/11/18 22:49:15 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -811,6 +811,8 @@ print_rule(struct pf_rule *r) } if (r->label[0]) printf("label %s", r->label); + if (r->qname[0]) + printf("queue %s", r->qname); printf("\n"); } diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h index 774a7dee882..29c30e3685f 100644 --- a/sbin/pfctl/pfctl_parser.h +++ b/sbin/pfctl/pfctl_parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.h,v 1.26 2002/10/25 10:40:45 camield Exp $ */ +/* $OpenBSD: pfctl_parser.h,v 1.27 2002/11/18 22:49:15 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -61,12 +61,15 @@ struct pfctl { struct pfioc_nat *pnat; struct pfioc_binat *pbinat; struct pfioc_rdr *prdr; + struct pfioc_altq *paltq; + struct pfioc_queue *pqueue; }; int pfctl_add_rule(struct pfctl *, struct pf_rule *); int pfctl_add_nat(struct pfctl *, struct pf_nat *); int pfctl_add_binat(struct pfctl *, struct pf_binat *); int pfctl_add_rdr(struct pfctl *, struct pf_rdr *); +int pfctl_add_altq(struct pfctl *, struct pf_altq *); int pfctl_set_timeout(struct pfctl *, const char *, int); int pfctl_set_optimization(struct pfctl *, const char *); @@ -109,6 +112,7 @@ struct pf_timeout { #define PFCTL_FLAG_FILTER 0x02 #define PFCTL_FLAG_NAT 0x04 #define PFCTL_FLAG_OPTION 0x08 +#define PFCTL_FLAG_ALTQ 0x10 extern const struct pf_timeout pf_timeouts[]; |