summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2017-05-15 11:23:26 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2017-05-15 11:23:26 +0000
commitdba2baa894a931585fbea74a7e61648b13794a0d (patch)
tree81f56886b604b67cd49c0268a72491a4e6263116
parent2c1d16f261d10af4f37335ceab78f3f5f3def8af (diff)
Hook up FQ-CoDel to the tree and enable configuration in the pfctl(8)
OK sthen, visa
-rw-r--r--sbin/pfctl/parse.y66
-rw-r--r--sbin/pfctl/pfctl.c8
-rw-r--r--sbin/pfctl/pfctl_parser.c28
-rw-r--r--sbin/pfctl/pfctl_queue.c55
-rw-r--r--sys/conf/files3
-rw-r--r--sys/net/pf_ioctl.c19
-rw-r--r--sys/net/pfvar.h13
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;
};