diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-05-15 11:23:26 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2017-05-15 11:23:26 +0000 |
commit | dba2baa894a931585fbea74a7e61648b13794a0d (patch) | |
tree | 81f56886b604b67cd49c0268a72491a4e6263116 | |
parent | 2c1d16f261d10af4f37335ceab78f3f5f3def8af (diff) |
Hook up FQ-CoDel to the tree and enable configuration in the pfctl(8)
OK sthen, visa
-rw-r--r-- | sbin/pfctl/parse.y | 66 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 8 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 28 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_queue.c | 55 | ||||
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/net/pf_ioctl.c | 19 | ||||
-rw-r--r-- | sys/net/pfvar.h | 13 |
7 files changed, 153 insertions, 39 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index 4f49b102609..63aaafeeea5 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.658 2017/04/28 14:15:45 mikeb Exp $ */ +/* $OpenBSD: parse.y,v 1.659 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -36,7 +36,6 @@ #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> #include <net/pfvar.h> -#include <net/hfsc.h> #include <arpa/inet.h> #include <stdio.h> @@ -306,15 +305,25 @@ struct node_sc { struct node_queue_bw m2; }; +struct node_fq { + u_int flows; + u_int quantum; + u_int target; + u_int interval; +}; + struct queue_opts { int marker; #define QOM_BWSPEC 0x01 #define QOM_PARENT 0x02 #define QOM_DEFAULT 0x04 #define QOM_QLIMIT 0x08 +#define QOM_FLOWS 0x10 +#define QOM_QUANTUM 0x20 struct node_sc realtime; struct node_sc linkshare; struct node_sc upperlimit; + struct node_fq flowqueue; char *parent; int flags; u_int qlimit; @@ -459,7 +468,7 @@ int parseport(char *, struct range *r, int); %token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID %token ANTISPOOF FOR INCLUDE MATCHES %token BITMASK RANDOM SOURCEHASH ROUNDROBIN LEASTSTATES STATICPORT PROBABILITY -%token WEIGHT BANDWIDTH +%token WEIGHT BANDWIDTH FLOWS QUANTUM %token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN MINIMUM BURST PARENT %token LOAD RULESET_OPTIMIZATION RTABLE RDOMAIN PRIO ONCE DEFAULT %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE @@ -1319,6 +1328,11 @@ queue_opt : BANDWIDTH scspec optscs { yyerror("bandwidth cannot be respecified"); YYERROR; } + if (queue_opts.marker & QOM_FLOWS) { + yyerror("bandwidth cannot be specified for " + "a flow queue"); + YYERROR; + } queue_opts.marker |= QOM_BWSPEC; queue_opts.linkshare = $2; queue_opts.realtime= $3.realtime; @@ -1338,9 +1352,9 @@ queue_opt : BANDWIDTH scspec optscs { YYERROR; } queue_opts.marker |= QOM_DEFAULT; - queue_opts.flags |= HFSC_DEFAULTCLASS; + queue_opts.flags |= PFQS_DEFAULT; } - | QLIMIT NUMBER { + | QLIMIT NUMBER { if (queue_opts.marker & QOM_QLIMIT) { yyerror("qlimit cannot be respecified"); YYERROR; @@ -1352,6 +1366,37 @@ queue_opt : BANDWIDTH scspec optscs { queue_opts.marker |= QOM_QLIMIT; queue_opts.qlimit = $2; } + | FLOWS NUMBER { + if (queue_opts.marker & QOM_FLOWS) { + yyerror("number of flows cannot be respecified"); + YYERROR; + } + if (queue_opts.marker & QOM_BWSPEC) { + yyerror("bandwidth cannot be specified for " + "a flow queue"); + YYERROR; + } + if ($2 < 1 || $2 > 32767) { + yyerror("number of flows out of range: " + "max 32767"); + YYERROR; + } + queue_opts.marker |= QOM_FLOWS; + queue_opts.flags |= PFQS_FLOWQUEUE; + queue_opts.flowqueue.flows = $2; + } + | QUANTUM NUMBER { + if (queue_opts.marker & QOM_QUANTUM) { + yyerror("quantum cannot be respecified"); + YYERROR; + } + if ($2 < 1 || $2 > 65535) { + yyerror("quantum out of range: max 65535"); + YYERROR; + } + queue_opts.marker |= QOM_QUANTUM; + queue_opts.flowqueue.quantum = $2; + } ; optscs : /* nada */ { @@ -4298,6 +4343,10 @@ expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts) LOOP_THROUGH(struct node_if, interface, interfaces, bzero(&qspec, sizeof(qspec)); + if ((opts->flags & PFQS_FLOWQUEUE) && opts->parent) { + yyerror("discipline doesn't support hierarchy"); + return (1); + } if (strlcpy(qspec.qname, qname, sizeof(qspec.qname)) >= sizeof(qspec.qname)) { yyerror("queuename too long"); @@ -4331,6 +4380,11 @@ expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts) qspec.upperlimit.m2.percent = opts->upperlimit.m2.bw_percent; qspec.upperlimit.d = opts->upperlimit.d; + qspec.flowqueue.flows = opts->flowqueue.flows; + qspec.flowqueue.quantum = opts->flowqueue.quantum; + qspec.flowqueue.interval = opts->flowqueue.interval; + qspec.flowqueue.target = opts->flowqueue.target; + qspec.flags = opts->flags; qspec.qlimit = opts->qlimit; @@ -4985,6 +5039,7 @@ lookup(char *s) { "fingerprints", FINGERPRINTS}, { "flags", FLAGS}, { "floating", FLOATING}, + { "flows", FLOWS}, { "flush", FLUSH}, { "for", FOR}, { "fragment", FRAGMENT}, @@ -5036,6 +5091,7 @@ lookup(char *s) { "probability", PROBABILITY}, { "proto", PROTO}, { "qlimit", QLIMIT}, + { "quantum", QUANTUM}, { "queue", QUEUE}, { "quick", QUICK}, { "random", RANDOM}, diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 9c39f37bb14..47bb55f0a95 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.342 2017/04/26 15:50:59 mikeb Exp $ */ +/* $OpenBSD: pfctl.c,v 1.343 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -40,7 +40,6 @@ #include <netinet/in.h> #include <net/pfvar.h> #include <arpa/inet.h> -#include <net/hfsc.h> #include <sys/sysctl.h> #include <err.h> @@ -1313,7 +1312,7 @@ pfctl_find_childqs(struct pfctl_qsitem *qi) TAILQ_FOREACH(p, &qi->children, entries) flags |= pfctl_find_childqs(p); - if (qi->qs.flags & HFSC_DEFAULTCLASS && !TAILQ_EMPTY(&qi->children)) + if (qi->qs.flags & PFQS_DEFAULT && !TAILQ_EMPTY(&qi->children)) errx(1, "default queue %s is not a leaf queue", qi->qs.qname); return (flags); @@ -1420,7 +1419,8 @@ pfctl_check_qassignments(struct pf_ruleset *rs) if (rs->anchor->path[0] == 0) { TAILQ_FOREACH(qi, &rootqs, entries) { flags = pfctl_find_childqs(qi); - if (!(flags & HFSC_DEFAULTCLASS)) + if (!(qi->qs.flags & PFQS_FLOWQUEUE) && + !(flags & PFQS_DEFAULT)) errx(1, "no default queue specified"); } } diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index e241b11f6fc..b33edf2d446 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_parser.c,v 1.309 2016/10/26 14:15:59 bluhm Exp $ */ +/* $OpenBSD: pfctl_parser.c,v 1.310 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -41,7 +41,6 @@ #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> #include <net/pfvar.h> -#include <net/hfsc.h> #include <arpa/inet.h> #include <ctype.h> @@ -1197,18 +1196,27 @@ print_scspec(const char *prefix, struct pf_queue_scspec *sc) void print_queuespec(struct pf_queuespec *q) { - /* hide the _root_ifname queues */ - if (q->qname[0] == '_') - return; printf("queue %s", q->qname); - if (q->parent[0] && q->parent[0] != '_') + if (q->parent[0]) printf(" parent %s", q->parent); else if (q->ifname[0]) printf(" on %s", q->ifname); - print_scspec(" bandwidth ", &q->linkshare); - print_scspec(", min ", &q->realtime); - print_scspec(", max ", &q->upperlimit); - if (q->flags & HFSC_DEFAULTCLASS) + if (q->flags & PFQS_FLOWQUEUE) { + printf(" flows %u", q->flowqueue.flows); + if (q->flowqueue.quantum > 0) + printf(" quantum %u", q->flowqueue.quantum); + if (q->flowqueue.interval > 0) + printf(" interval %ums", + q->flowqueue.interval / 1000000); + if (q->flowqueue.target > 0) + printf(" target %ums", + q->flowqueue.target / 1000000); + } else { + print_scspec(" bandwidth ", &q->linkshare); + print_scspec(", min ", &q->realtime); + print_scspec(", max ", &q->upperlimit); + } + if (q->flags & PFQS_DEFAULT) printf(" default"); if (q->qlimit) printf(" qlimit %u", q->qlimit); diff --git a/sbin/pfctl/pfctl_queue.c b/sbin/pfctl/pfctl_queue.c index 6e59fff7d22..21e8d3e3dbc 100644 --- a/sbin/pfctl/pfctl_queue.c +++ b/sbin/pfctl/pfctl_queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_queue.c,v 1.3 2017/04/26 15:50:59 mikeb Exp $ */ +/* $OpenBSD: pfctl_queue.c,v 1.4 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org> @@ -26,12 +26,14 @@ #include <arpa/inet.h> #include <err.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <net/hfsc.h> +#include <net/fq_codel.h> #include "pfctl.h" #include "pfctl_parser.h" @@ -40,7 +42,10 @@ #define STAT_INTERVAL 5 struct queue_stats { - struct hfsc_class_stats data; + union { + struct hfsc_class_stats hfsc; + struct fqcodel_stats fqc; + } data; int avgn; double avg_bytes; double avg_packets; @@ -196,14 +201,33 @@ pfctl_print_queue_node(int dev, struct pfctl_queue_node *node, int opts) void pfctl_print_queue_nodestat(int dev, const struct pfctl_queue_node *node) { + struct hfsc_class_stats *stats = + (struct hfsc_class_stats *)&node->qstats.data.hfsc; + struct fqcodel_stats *fqstats = + (struct fqcodel_stats *)&node->qstats.data.fqc; + printf(" [ pkts: %10llu bytes: %10llu " "dropped pkts: %6llu bytes: %6llu ]\n", - (unsigned long long)node->qstats.data.xmit_cnt.packets, - (unsigned long long)node->qstats.data.xmit_cnt.bytes, - (unsigned long long)node->qstats.data.drop_cnt.packets, - (unsigned long long)node->qstats.data.drop_cnt.bytes); - printf(" [ qlength: %3d/%3d ]\n", node->qstats.data.qlength, - node->qstats.data.qlimit); + (unsigned long long)stats->xmit_cnt.packets, + (unsigned long long)stats->xmit_cnt.bytes, + (unsigned long long)stats->drop_cnt.packets, + (unsigned long long)stats->drop_cnt.bytes); + if (node->qs.flags & PFQS_FLOWQUEUE) { + double avg = 0, dev = 0; + + if (fqstats->flows > 0) { + avg = (double)fqstats->delaysum / + (double)fqstats->flows; + dev = sqrt(fmax(0, (double)fqstats->delaysumsq / + (double)fqstats->flows) - avg * avg); + } + + printf(" [ qlength: %3d/%3d avg delay: %.3fms std-dev: %.3fms" + " flows: %3d ]\n", stats->qlength, stats->qlimit, + avg / 1000, dev / 1000, fqstats->flows); + } else + printf(" [ qlength: %3d/%3d ]\n", stats->qlength, + stats->qlimit); if (node->qstats.avgn < 2) return; @@ -216,19 +240,22 @@ pfctl_print_queue_nodestat(int dev, const struct pfctl_queue_node *node) void update_avg(struct queue_stats *s) { + struct hfsc_class_stats *stats = + (struct hfsc_class_stats *)&s->data; + if (s->avgn > 0) { - if (s->data.xmit_cnt.bytes >= s->prev_bytes) + if (stats->xmit_cnt.bytes >= s->prev_bytes) s->avg_bytes = ((s->avg_bytes * (s->avgn - 1)) + - (s->data.xmit_cnt.bytes - s->prev_bytes)) / + (stats->xmit_cnt.bytes - s->prev_bytes)) / s->avgn; - if (s->data.xmit_cnt.packets >= s->prev_packets) + if (stats->xmit_cnt.packets >= s->prev_packets) s->avg_packets = ((s->avg_packets * (s->avgn - 1)) + - (s->data.xmit_cnt.packets - s->prev_packets)) / + (stats->xmit_cnt.packets - s->prev_packets)) / s->avgn; } - s->prev_bytes = s->data.xmit_cnt.bytes; - s->prev_packets = s->data.xmit_cnt.packets; + s->prev_bytes = stats->xmit_cnt.bytes; + s->prev_packets = stats->xmit_cnt.packets; if (s->avgn < AVGN_MAX) s->avgn++; } diff --git a/sys/conf/files b/sys/conf/files index 66f5c23e285..af7b8ba7912 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.644 2017/04/30 21:33:02 mikeb Exp $ +# $OpenBSD: files,v 1.645 2017/05/15 11:23:25 mikeb Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -763,6 +763,7 @@ file tmpfs/tmpfs_fifoops.c tmpfs & fifo file net/art.c art file net/bpf.c bpfilter needs-count file net/bpf_filter.c bpfilter +file net/fq_codel.c pf file net/if.c file net/ifq.c file net/if_ethersubr.c ether needs-flag diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c index a880590dffb..fac156bae3f 100644 --- a/sys/net/pf_ioctl.c +++ b/sys/net/pf_ioctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.310 2017/05/02 12:27:37 mikeb Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.311 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -61,6 +61,7 @@ #include <net/if_var.h> #include <net/route.h> #include <net/hfsc.h> +#include <net/fq_codel.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -598,8 +599,13 @@ pf_create_queues(void) qif = malloc(sizeof(*qif), M_TEMP, M_WAITOK); qif->ifp = ifp; - qif->ifqops = ifq_hfsc_ops; - qif->pfqops = pfq_hfsc_ops; + if (q->flags & PFQS_FLOWQUEUE) { + qif->ifqops = ifq_fqcodel_ops; + qif->pfqops = pfq_fqcodel_ops; + } else { + qif->ifqops = ifq_hfsc_ops; + qif->pfqops = pfq_hfsc_ops; + } qif->disc = qif->pfqops->pfq_alloc(ifp); @@ -1088,7 +1094,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } bcopy(qs, &pq->queue, sizeof(pq->queue)); - error = pfq_hfsc_ops->pfq_qstats(qs, pq->buf, &nbytes); + if (qs->flags & PFQS_FLOWQUEUE) + error = pfq_fqcodel_ops->pfq_qstats(qs, pq->buf, + &nbytes); + else + error = pfq_hfsc_ops->pfq_qstats(qs, pq->buf, + &nbytes); if (error == 0) pq->nbytes = nbytes; break; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 981d778e37a..48d74247965 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.451 2017/05/02 12:27:37 mikeb Exp $ */ +/* $OpenBSD: pfvar.h,v 1.452 2017/05/15 11:23:25 mikeb Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1310,6 +1310,13 @@ struct pf_queue_scspec { u_int d; }; +struct pf_queue_fqspec { + u_int flows; + u_int quantum; + u_int target; + u_int interval; +}; + struct pf_queuespec { TAILQ_ENTRY(pf_queuespec) entries; char qname[PF_QNAME_SIZE]; @@ -1318,6 +1325,7 @@ struct pf_queuespec { struct pf_queue_scspec realtime; struct pf_queue_scspec linkshare; struct pf_queue_scspec upperlimit; + struct pf_queue_fqspec flowqueue; struct pfi_kif *kif; u_int flags; u_int qlimit; @@ -1325,6 +1333,9 @@ struct pf_queuespec { u_int32_t parent_qid; }; +#define PFQS_FLOWQUEUE 0x0001 +#define PFQS_DEFAULT 0x1000 /* maps to HFSC_DEFAULTCLASS */ + struct priq_opts { int flags; }; |