1
|
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
|
2
|
index da1468b..591db6b 100644
|
3
|
--- a/sbin/pfctl/parse.y
|
4
|
+++ b/sbin/pfctl/parse.y
|
5
|
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
6
|
#include <altq/altq_priq.h>
|
7
|
#include <altq/altq_hfsc.h>
|
8
|
#include <altq/altq_fairq.h>
|
9
|
+#include <altq/altq_codel.h>
|
10
|
|
11
|
#include <stdio.h>
|
12
|
#include <unistd.h>
|
13
|
@@ -315,6 +316,7 @@ struct pool_opts {
|
14
|
|
15
|
struct node_hfsc_opts hfsc_opts;
|
16
|
struct node_fairq_opts fairq_opts;
|
17
|
+struct codel_opts codel_opts;
|
18
|
struct node_state_opt *keep_state_defaults = NULL;
|
19
|
|
20
|
int disallow_table(struct node_host *, const char *);
|
21
|
@@ -439,6 +441,7 @@ typedef struct {
|
22
|
struct pool_opts pool_opts;
|
23
|
struct node_hfsc_opts hfsc_opts;
|
24
|
struct node_fairq_opts fairq_opts;
|
25
|
+ struct codel_opts codel_opts;
|
26
|
} v;
|
27
|
int lineno;
|
28
|
} YYSTYPE;
|
29
|
@@ -463,8 +466,8 @@ int parseport(char *, struct range *r, int);
|
30
|
%token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
|
31
|
%token ANTISPOOF FOR INCLUDE
|
32
|
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
|
33
|
-%token ALTQ CBQ PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
|
34
|
-%token QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE
|
35
|
+%token ALTQ CBQ PRIQ HFSC FAIRQ CODEL BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
|
36
|
+%token QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE INTERVAL
|
37
|
%token DNPIPE DNQUEUE
|
38
|
%token LOAD RULESET_OPTIMIZATION
|
39
|
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
|
40
|
@@ -515,6 +518,7 @@ int parseport(char *, struct range *r, int);
|
41
|
%type <v.number> priqflags_list priqflags_item
|
42
|
%type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts
|
43
|
%type <v.fairq_opts> fairqopts_list fairqopts_item fairq_opts
|
44
|
+%type <v.codel_opts> codelopts_list codelopts_item codel_opts
|
45
|
%type <v.queue_bwspec> bandwidth
|
46
|
%type <v.filter_opts> filter_opts filter_opt filter_opts_l
|
47
|
%type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
|
48
|
@@ -1491,7 +1495,7 @@ altqif : ALTQ interface queue_opts QUEUE qassign {
|
49
|
a.scheduler = $3.scheduler.qtype;
|
50
|
a.qlimit = $3.qlimit;
|
51
|
a.tbrsize = $3.tbrsize;
|
52
|
- if ($5 == NULL) {
|
53
|
+ if ($5 == NULL && $3.scheduler.qtype != ALTQT_CODEL) {
|
54
|
yyerror("no child queues specified");
|
55
|
YYERROR;
|
56
|
}
|
57
|
@@ -1701,6 +1705,15 @@ scheduler : CBQ {
|
58
|
$$.qtype = ALTQT_FAIRQ;
|
59
|
$$.data.fairq_opts = $3;
|
60
|
}
|
61
|
+ | CODEL {
|
62
|
+ $$.qtype = ALTQT_CODEL;
|
63
|
+ bzero(&$$.data.codel_opts,
|
64
|
+ sizeof(struct codel_opts));
|
65
|
+ }
|
66
|
+ | CODEL '(' codel_opts ')' {
|
67
|
+ $$.qtype = ALTQT_CODEL;
|
68
|
+ $$.data.codel_opts = $3;
|
69
|
+ }
|
70
|
;
|
71
|
|
72
|
cbqflags_list : cbqflags_item { $$ |= $1; }
|
73
|
@@ -1718,6 +1731,8 @@ cbqflags_item : STRING {
|
74
|
$$ = CBQCLF_RED|CBQCLF_ECN;
|
75
|
else if (!strcmp($1, "rio"))
|
76
|
$$ = CBQCLF_RIO;
|
77
|
+ else if (!strcmp($1, "codel"))
|
78
|
+ $$ = CBQCLF_CODEL;
|
79
|
else {
|
80
|
yyerror("unknown cbq flag \"%s\"", $1);
|
81
|
free($1);
|
82
|
@@ -1740,6 +1755,8 @@ priqflags_item : STRING {
|
83
|
$$ = PRCF_RED|PRCF_ECN;
|
84
|
else if (!strcmp($1, "rio"))
|
85
|
$$ = PRCF_RIO;
|
86
|
+ else if (!strcmp($1, "codel"))
|
87
|
+ $$ = PRCF_CODEL;
|
88
|
else {
|
89
|
yyerror("unknown priq flag \"%s\"", $1);
|
90
|
free($1);
|
91
|
@@ -1840,6 +1857,8 @@ hfscopts_item : LINKSHARE bandwidth {
|
92
|
hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
|
93
|
else if (!strcmp($1, "rio"))
|
94
|
hfsc_opts.flags |= HFCF_RIO;
|
95
|
+ else if (!strcmp($1, "codel"))
|
96
|
+ hfsc_opts.flags |= HFCF_CODEL;
|
97
|
else {
|
98
|
yyerror("unknown hfsc flag \"%s\"", $1);
|
99
|
free($1);
|
100
|
@@ -1895,6 +1914,8 @@ fairqopts_item : LINKSHARE bandwidth {
|
101
|
fairq_opts.flags |= FARF_RED|FARF_ECN;
|
102
|
else if (!strcmp($1, "rio"))
|
103
|
fairq_opts.flags |= FARF_RIO;
|
104
|
+ else if (!strcmp($1, "codel"))
|
105
|
+ fairq_opts.flags |= FARF_CODEL;
|
106
|
else {
|
107
|
yyerror("unknown fairq flag \"%s\"", $1);
|
108
|
free($1);
|
109
|
@@ -1904,6 +1925,45 @@ fairqopts_item : LINKSHARE bandwidth {
|
110
|
}
|
111
|
;
|
112
|
|
113
|
+codel_opts : {
|
114
|
+ bzero(&codel_opts,
|
115
|
+ sizeof(struct codel_opts));
|
116
|
+ }
|
117
|
+ codelopts_list {
|
118
|
+ $$ = codel_opts;
|
119
|
+ }
|
120
|
+ ;
|
121
|
+
|
122
|
+codelopts_list : codelopts_item
|
123
|
+ | codelopts_list comma codelopts_item
|
124
|
+ ;
|
125
|
+
|
126
|
+codelopts_item : QLIMIT number {
|
127
|
+ if (codel_opts.target) {
|
128
|
+ yyerror("target already specified");
|
129
|
+ YYERROR;
|
130
|
+ }
|
131
|
+ codel_opts.target = $2;
|
132
|
+ }
|
133
|
+ | INTERVAL number {
|
134
|
+ if (codel_opts.interval) {
|
135
|
+ yyerror("interval already specified");
|
136
|
+ YYERROR;
|
137
|
+ }
|
138
|
+ codel_opts.interval = $2;
|
139
|
+ }
|
140
|
+ | STRING {
|
141
|
+ if (!strcmp($1, "ecn"))
|
142
|
+ codel_opts.ecn = 1;
|
143
|
+ else {
|
144
|
+ yyerror("unknown codel option \"%s\"", $1);
|
145
|
+ free($1);
|
146
|
+ YYERROR;
|
147
|
+ }
|
148
|
+ free($1);
|
149
|
+ }
|
150
|
+ ;
|
151
|
+
|
152
|
qassign : /* empty */ { $$ = NULL; }
|
153
|
| qassign_item { $$ = $1; }
|
154
|
| '{' optnl qassign_list '}' { $$ = $3; }
|
155
|
@@ -5051,7 +5111,8 @@ expand_altq(struct pf_altq *a, struct node_if *interfaces,
|
156
|
|
157
|
if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
|
158
|
FREE_LIST(struct node_if, interfaces);
|
159
|
- FREE_LIST(struct node_queue, nqueues);
|
160
|
+ if (nqueues)
|
161
|
+ FREE_LIST(struct node_queue, nqueues);
|
162
|
return (0);
|
163
|
}
|
164
|
|
165
|
@@ -5113,37 +5174,40 @@ expand_altq(struct pf_altq *a, struct node_if *interfaces,
|
166
|
errs++;
|
167
|
}
|
168
|
|
169
|
- LOOP_THROUGH(struct node_queue, queue, nqueues,
|
170
|
- n = calloc(1, sizeof(struct node_queue));
|
171
|
- if (n == NULL)
|
172
|
- err(1, "expand_altq: calloc");
|
173
|
- if (pa.scheduler == ALTQT_CBQ ||
|
174
|
- pa.scheduler == ALTQT_HFSC /* ||
|
175
|
- pa.scheduler == ALTQT_FAIRQ */)
|
176
|
- if (strlcpy(n->parent, qname,
|
177
|
- sizeof(n->parent)) >=
|
178
|
- sizeof(n->parent))
|
179
|
+ if (nqueues) {
|
180
|
+ LOOP_THROUGH(struct node_queue, queue, nqueues,
|
181
|
+ n = calloc(1, sizeof(struct node_queue));
|
182
|
+ if (n == NULL)
|
183
|
+ err(1, "expand_altq: calloc");
|
184
|
+ if (pa.scheduler == ALTQT_CBQ ||
|
185
|
+ pa.scheduler == ALTQT_HFSC /* ||
|
186
|
+ pa.scheduler == ALTQT_FAIRQ */)
|
187
|
+ if (strlcpy(n->parent, qname,
|
188
|
+ sizeof(n->parent)) >=
|
189
|
+ sizeof(n->parent))
|
190
|
+ errx(1, "expand_altq: strlcpy");
|
191
|
+ if (strlcpy(n->queue, queue->queue,
|
192
|
+ sizeof(n->queue)) >= sizeof(n->queue))
|
193
|
errx(1, "expand_altq: strlcpy");
|
194
|
- if (strlcpy(n->queue, queue->queue,
|
195
|
- sizeof(n->queue)) >= sizeof(n->queue))
|
196
|
- errx(1, "expand_altq: strlcpy");
|
197
|
- if (strlcpy(n->ifname, interface->ifname,
|
198
|
- sizeof(n->ifname)) >= sizeof(n->ifname))
|
199
|
- errx(1, "expand_altq: strlcpy");
|
200
|
- n->scheduler = pa.scheduler;
|
201
|
- n->next = NULL;
|
202
|
- n->tail = n;
|
203
|
- if (queues == NULL)
|
204
|
- queues = n;
|
205
|
- else {
|
206
|
- queues->tail->next = n;
|
207
|
- queues->tail = n;
|
208
|
- }
|
209
|
- );
|
210
|
+ if (strlcpy(n->ifname, interface->ifname,
|
211
|
+ sizeof(n->ifname)) >= sizeof(n->ifname))
|
212
|
+ errx(1, "expand_altq: strlcpy");
|
213
|
+ n->scheduler = pa.scheduler;
|
214
|
+ n->next = NULL;
|
215
|
+ n->tail = n;
|
216
|
+ if (queues == NULL)
|
217
|
+ queues = n;
|
218
|
+ else {
|
219
|
+ queues->tail->next = n;
|
220
|
+ queues->tail = n;
|
221
|
+ }
|
222
|
+ );
|
223
|
+ }
|
224
|
}
|
225
|
);
|
226
|
FREE_LIST(struct node_if, interfaces);
|
227
|
- FREE_LIST(struct node_queue, nqueues);
|
228
|
+ if (nqueues)
|
229
|
+ FREE_LIST(struct node_queue, nqueues);
|
230
|
|
231
|
return (errs);
|
232
|
}
|
233
|
@@ -5557,6 +5621,7 @@ lookup(char *s)
|
234
|
{ "buckets", BUCKETS},
|
235
|
{ "cbq", CBQ},
|
236
|
{ "code", CODE},
|
237
|
+ { "codelq", CODEL},
|
238
|
{ "crop", FRAGCROP},
|
239
|
{ "debug", DEBUG},
|
240
|
{ "dnpipe", DNPIPE},
|
241
|
@@ -5591,6 +5656,7 @@ lookup(char *s)
|
242
|
{ "include", INCLUDE},
|
243
|
{ "inet", INET},
|
244
|
{ "inet6", INET6},
|
245
|
+ { "interval", INTERVAL},
|
246
|
{ "keep", KEEP},
|
247
|
{ "label", LABEL},
|
248
|
{ "limit", LIMIT},
|
249
|
diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c
|
250
|
index 9a33c01..f532aeb 100644
|
251
|
--- a/sbin/pfctl/pfctl_altq.c
|
252
|
+++ b/sbin/pfctl/pfctl_altq.c
|
253
|
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
254
|
#include <altq/altq_priq.h>
|
255
|
#include <altq/altq_hfsc.h>
|
256
|
#include <altq/altq_fairq.h>
|
257
|
+#include <altq/altq_codel.h>
|
258
|
|
259
|
#include "pfctl_parser.h"
|
260
|
#include "pfctl.h"
|
261
|
@@ -75,6 +76,9 @@ static int print_fairq_opts(const struct pf_altq *,
|
262
|
const struct node_queue_opt *);
|
263
|
static int check_commit_fairq(int, int, struct pf_altq *);
|
264
|
|
265
|
+static int print_codel_opts(const struct pf_altq *,
|
266
|
+ const struct node_queue_opt *);
|
267
|
+
|
268
|
static void gsc_add_sc(struct gen_sc *, struct service_curve *);
|
269
|
static int is_gsc_under_sc(struct gen_sc *,
|
270
|
struct service_curve *);
|
271
|
@@ -186,6 +190,10 @@ print_altq(const struct pf_altq *a, unsigned int level,
|
272
|
if (!print_fairq_opts(a, qopts))
|
273
|
printf("fairq ");
|
274
|
break;
|
275
|
+ case ALTQT_CODEL:
|
276
|
+ if (!print_codel_opts(a, qopts))
|
277
|
+ printf("codel ");
|
278
|
+ break;
|
279
|
}
|
280
|
|
281
|
if (bw != NULL && bw->bw_percent > 0) {
|
282
|
@@ -588,6 +596,8 @@ print_cbq_opts(const struct pf_altq *a)
|
283
|
printf(" ecn");
|
284
|
if (opts->flags & CBQCLF_RIO)
|
285
|
printf(" rio");
|
286
|
+ if (opts->flags & CBQCLF_CODEL)
|
287
|
+ printf(" codel");
|
288
|
if (opts->flags & CBQCLF_CLEARDSCP)
|
289
|
printf(" cleardscp");
|
290
|
if (opts->flags & CBQCLF_FLOWVALVE)
|
291
|
@@ -675,6 +685,8 @@ print_priq_opts(const struct pf_altq *a)
|
292
|
printf(" ecn");
|
293
|
if (opts->flags & PRCF_RIO)
|
294
|
printf(" rio");
|
295
|
+ if (opts->flags & PRCF_CODEL)
|
296
|
+ printf(" codel");
|
297
|
if (opts->flags & PRCF_CLEARDSCP)
|
298
|
printf(" cleardscp");
|
299
|
if (opts->flags & PRCF_DEFAULTCLASS)
|
300
|
@@ -1000,6 +1012,8 @@ print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
301
|
printf(" ecn");
|
302
|
if (opts->flags & HFCF_RIO)
|
303
|
printf(" rio");
|
304
|
+ if (opts->flags & HFCF_CODEL)
|
305
|
+ printf(" codel");
|
306
|
if (opts->flags & HFCF_CLEARDSCP)
|
307
|
printf(" cleardscp");
|
308
|
if (opts->flags & HFCF_DEFAULTCLASS)
|
309
|
@@ -1022,6 +1036,28 @@ print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
310
|
}
|
311
|
|
312
|
static int
|
313
|
+print_codel_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
314
|
+{
|
315
|
+ const struct codel_opts *opts;
|
316
|
+
|
317
|
+ opts = &a->pq_u.codel_opts;
|
318
|
+ if (opts->target || opts->interval || opts->ecn) {
|
319
|
+ printf("codel(");
|
320
|
+ if (opts->target)
|
321
|
+ printf(" target %d", opts->target);
|
322
|
+ if (opts->interval)
|
323
|
+ printf(" interval %d", opts->interval);
|
324
|
+ if (opts->ecn)
|
325
|
+ printf("ecn");
|
326
|
+ printf(") ");
|
327
|
+
|
328
|
+ return (1);
|
329
|
+ }
|
330
|
+
|
331
|
+ return (0);
|
332
|
+}
|
333
|
+
|
334
|
+static int
|
335
|
print_fairq_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
336
|
{
|
337
|
const struct fairq_opts *opts;
|
338
|
@@ -1043,6 +1079,8 @@ print_fairq_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
|
339
|
printf(" ecn");
|
340
|
if (opts->flags & FARF_RIO)
|
341
|
printf(" rio");
|
342
|
+ if (opts->flags & FARF_CODEL)
|
343
|
+ printf(" codel");
|
344
|
if (opts->flags & FARF_CLEARDSCP)
|
345
|
printf(" cleardscp");
|
346
|
if (opts->flags & FARF_DEFAULTCLASS)
|
347
|
@@ -1394,6 +1432,11 @@ eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts,
|
348
|
opts->data.fairq_opts.linkshare.d;
|
349
|
}
|
350
|
break;
|
351
|
+ case ALTQT_CODEL:
|
352
|
+ pa->pq_u.codel_opts.target = opts->data.codel_opts.target;
|
353
|
+ pa->pq_u.codel_opts.interval = opts->data.codel_opts.interval;
|
354
|
+ pa->pq_u.codel_opts.ecn = opts->data.codel_opts.ecn;
|
355
|
+ break;
|
356
|
default:
|
357
|
warnx("eval_queue_opts: unknown scheduler type %u",
|
358
|
opts->qtype);
|
359
|
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
|
360
|
index f2b0a9b..b44a65a 100644
|
361
|
--- a/sbin/pfctl/pfctl_parser.h
|
362
|
+++ b/sbin/pfctl/pfctl_parser.h
|
363
|
@@ -169,6 +169,7 @@ struct node_queue_opt {
|
364
|
union {
|
365
|
struct cbq_opts cbq_opts;
|
366
|
struct priq_opts priq_opts;
|
367
|
+ struct codel_opts codel_opts;
|
368
|
struct node_hfsc_opts hfsc_opts;
|
369
|
struct node_fairq_opts fairq_opts;
|
370
|
} data;
|
371
|
diff --git a/sbin/pfctl/pfctl_qstats.c b/sbin/pfctl/pfctl_qstats.c
|
372
|
index 4087d71..5530572 100644
|
373
|
--- a/sbin/pfctl/pfctl_qstats.c
|
374
|
+++ b/sbin/pfctl/pfctl_qstats.c
|
375
|
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
376
|
#include <altq/altq_priq.h>
|
377
|
#include <altq/altq_hfsc.h>
|
378
|
#include <altq/altq_fairq.h>
|
379
|
+#include <altq/altq_codel.h>
|
380
|
|
381
|
#include "pfctl.h"
|
382
|
#include "pfctl_parser.h"
|
383
|
@@ -48,6 +49,7 @@ union class_stats {
|
384
|
struct priq_classstats priq_stats;
|
385
|
struct hfsc_classstats hfsc_stats;
|
386
|
struct fairq_classstats fairq_stats;
|
387
|
+ struct codel_ifstats codel_stats;
|
388
|
};
|
389
|
|
390
|
#define AVGN_MAX 8
|
391
|
@@ -78,6 +80,7 @@ void pfctl_print_altq_node(int, const struct pf_altq_node *,
|
392
|
unsigned, int);
|
393
|
void print_cbqstats(struct queue_stats);
|
394
|
void print_priqstats(struct queue_stats);
|
395
|
+void print_codelstats(struct queue_stats);
|
396
|
void print_hfscstats(struct queue_stats);
|
397
|
void print_fairqstats(struct queue_stats);
|
398
|
void pfctl_free_altq_node(struct pf_altq_node *);
|
399
|
@@ -165,7 +168,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
|
400
|
return (-1);
|
401
|
}
|
402
|
#ifdef __FreeBSD__
|
403
|
- if (pa.altq.qid > 0 &&
|
404
|
+ if ((pa.altq.qid > 0 || pa.altq.scheduler == ALTQT_CODEL) &&
|
405
|
!(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) {
|
406
|
#else
|
407
|
if (pa.altq.qid > 0) {
|
408
|
@@ -303,7 +306,7 @@ pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
|
409
|
void
|
410
|
pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
|
411
|
{
|
412
|
- if (a->altq.qid == 0)
|
413
|
+ if (a->altq.qid == 0 && a->altq.scheduler != ALTQT_CODEL)
|
414
|
return;
|
415
|
|
416
|
#ifdef __FreeBSD__
|
417
|
@@ -323,6 +326,9 @@ pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
|
418
|
case ALTQT_FAIRQ:
|
419
|
print_fairqstats(a->qstats);
|
420
|
break;
|
421
|
+ case ALTQT_CODEL:
|
422
|
+ print_codelstats(a->qstats);
|
423
|
+ break;
|
424
|
}
|
425
|
}
|
426
|
|
427
|
@@ -368,6 +374,26 @@ print_priqstats(struct queue_stats cur)
|
428
|
}
|
429
|
|
430
|
void
|
431
|
+print_codelstats(struct queue_stats cur)
|
432
|
+{
|
433
|
+ printf(" [ pkts: %10llu bytes: %10llu "
|
434
|
+ "dropped pkts: %6llu bytes: %6llu ]\n",
|
435
|
+ (unsigned long long)cur.data.codel_stats.cl_xmitcnt.packets,
|
436
|
+ (unsigned long long)cur.data.codel_stats.cl_xmitcnt.bytes,
|
437
|
+ (unsigned long long)cur.data.codel_stats.cl_dropcnt.packets + cur.data.codel_stats.stats.drop_cnt.packets,
|
438
|
+ (unsigned long long)cur.data.codel_stats.cl_dropcnt.bytes + cur.data.codel_stats.stats.drop_cnt.bytes);
|
439
|
+ printf(" [ qlength: %3d/%3d ]\n",
|
440
|
+ cur.data.codel_stats.qlength, cur.data.codel_stats.qlimit);
|
441
|
+
|
442
|
+ if (cur.avgn < 2)
|
443
|
+ return;
|
444
|
+
|
445
|
+ printf(" [ measured: %7.1f packets/s, %s/s ]\n",
|
446
|
+ cur.avg_packets / STAT_INTERVAL,
|
447
|
+ rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
|
448
|
+}
|
449
|
+
|
450
|
+void
|
451
|
print_hfscstats(struct queue_stats cur)
|
452
|
{
|
453
|
printf(" [ pkts: %10llu bytes: %10llu "
|
454
|
@@ -428,7 +454,7 @@ update_avg(struct pf_altq_node *a)
|
455
|
u_int64_t b, p;
|
456
|
int n;
|
457
|
|
458
|
- if (a->altq.qid == 0)
|
459
|
+ if (a->altq.qid == 0 && a->altq.scheduler != ALTQT_CODEL)
|
460
|
return;
|
461
|
|
462
|
qs = &a->qstats;
|
463
|
@@ -451,6 +477,10 @@ update_avg(struct pf_altq_node *a)
|
464
|
b = qs->data.fairq_stats.xmit_cnt.bytes;
|
465
|
p = qs->data.fairq_stats.xmit_cnt.packets;
|
466
|
break;
|
467
|
+ case ALTQT_CODEL:
|
468
|
+ b = qs->data.codel_stats.cl_xmitcnt.bytes;
|
469
|
+ p = qs->data.codel_stats.cl_xmitcnt.packets;
|
470
|
+ break;
|
471
|
default:
|
472
|
b = 0;
|
473
|
p = 0;
|
474
|
diff --git a/sys/conf/files b/sys/conf/files
|
475
|
index 434ffaf..6c2d452 100644
|
476
|
--- a/sys/conf/files
|
477
|
+++ b/sys/conf/files
|
478
|
@@ -286,6 +286,7 @@ compat/freebsd32/freebsd32_sysent.c optional compat_freebsd32
|
479
|
contrib/altq/altq/altq_cbq.c optional altq
|
480
|
contrib/altq/altq/altq_cdnr.c optional altq
|
481
|
contrib/altq/altq/altq_hfsc.c optional altq
|
482
|
+contrib/altq/altq/altq_codel.c optional altq
|
483
|
contrib/altq/altq/altq_fairq.c optional altq
|
484
|
contrib/altq/altq/altq_priq.c optional altq
|
485
|
contrib/altq/altq/altq_red.c optional altq
|
486
|
diff --git a/sys/conf/options b/sys/conf/options
|
487
|
index 55030c3..b838d17 100644
|
488
|
--- a/sys/conf/options
|
489
|
+++ b/sys/conf/options
|
490
|
@@ -384,6 +384,7 @@ ALTQ_NOPCC opt_altq.h
|
491
|
ALTQ_PRIQ opt_altq.h
|
492
|
ALTQ_RED opt_altq.h
|
493
|
ALTQ_RIO opt_altq.h
|
494
|
+ALTQ_CODEL opt_altq.h
|
495
|
BOOTP opt_bootp.h
|
496
|
BOOTP_BLOCKSIZE opt_bootp.h
|
497
|
BOOTP_COMPAT opt_bootp.h
|
498
|
diff --git a/sys/contrib/altq/altq/altq.h b/sys/contrib/altq/altq/altq.h
|
499
|
index 6200ac5..26d6cb7 100644
|
500
|
--- a/sys/contrib/altq/altq/altq.h
|
501
|
+++ b/sys/contrib/altq/altq/altq.h
|
502
|
@@ -64,7 +64,8 @@
|
503
|
#define ALTQT_PRIQ 11 /* priority queue */
|
504
|
#define ALTQT_JOBS 12 /* JoBS */
|
505
|
#define ALTQT_FAIRQ 13 /* fairq */
|
506
|
-#define ALTQT_MAX 14 /* should be max discipline type + 1 */
|
507
|
+#define ALTQT_CODEL 14 /* fairq */
|
508
|
+#define ALTQT_MAX 15 /* should be max discipline type + 1 */
|
509
|
|
510
|
#ifdef ALTQ3_COMPAT
|
511
|
struct altqreq {
|
512
|
diff --git a/sys/contrib/altq/altq/altq_cbq.c b/sys/contrib/altq/altq/altq_cbq.c
|
513
|
index 3991d1d..13f9721 100644
|
514
|
--- a/sys/contrib/altq/altq/altq_cbq.c
|
515
|
+++ b/sys/contrib/altq/altq/altq_cbq.c
|
516
|
@@ -241,6 +241,10 @@ get_class_stats(class_stats_t *statsp, struct rm_class *cl)
|
517
|
if (q_is_rio(cl->q_))
|
518
|
rio_getstats((rio_t *)cl->red_, &statsp->red[0]);
|
519
|
#endif
|
520
|
+#ifdef ALTQ_CODEL
|
521
|
+ if (q_is_codel(cl->q_))
|
522
|
+ codel_getstats(cl->codel_, &statsp->codel);
|
523
|
+#endif
|
524
|
}
|
525
|
|
526
|
int
|
527
|
diff --git a/sys/contrib/altq/altq/altq_cbq.h b/sys/contrib/altq/altq/altq_cbq.h
|
528
|
index 76096af..45509f0 100644
|
529
|
--- a/sys/contrib/altq/altq/altq_cbq.h
|
530
|
+++ b/sys/contrib/altq/altq/altq_cbq.h
|
531
|
@@ -37,6 +37,7 @@
|
532
|
#include <altq/altq_rmclass.h>
|
533
|
#include <altq/altq_red.h>
|
534
|
#include <altq/altq_rio.h>
|
535
|
+#include <altq/altq_codel.h>
|
536
|
|
537
|
#ifdef __cplusplus
|
538
|
extern "C" {
|
539
|
@@ -51,6 +52,7 @@ extern "C" {
|
540
|
#define CBQCLF_FLOWVALVE 0x0008 /* use flowvalve (aka penalty-box) */
|
541
|
#define CBQCLF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
|
542
|
#define CBQCLF_BORROW 0x0020 /* borrow from parent */
|
543
|
+#define CBQCLF_CODEL 0x0040 /* use CODEL */
|
544
|
|
545
|
/* class flags only for root class */
|
546
|
#define CBQCLF_WRR 0x0100 /* weighted-round robin */
|
547
|
@@ -93,6 +95,7 @@ typedef struct _cbq_class_stats_ {
|
548
|
/* red and rio related info */
|
549
|
int qtype;
|
550
|
struct redstats red[3];
|
551
|
+ struct codel_stats codel;
|
552
|
} class_stats_t;
|
553
|
|
554
|
#ifdef ALTQ3_COMPAT
|
555
|
diff --git a/sys/contrib/altq/altq/altq_classq.h b/sys/contrib/altq/altq/altq_classq.h
|
556
|
index dc5c646..8e4d1db 100644
|
557
|
--- a/sys/contrib/altq/altq/altq_classq.h
|
558
|
+++ b/sys/contrib/altq/altq/altq_classq.h
|
559
|
@@ -49,6 +49,7 @@ extern "C" {
|
560
|
#define Q_RED 0x01
|
561
|
#define Q_RIO 0x02
|
562
|
#define Q_DROPTAIL 0x03
|
563
|
+#define Q_CODEL 0x04
|
564
|
|
565
|
#ifdef _KERNEL
|
566
|
|
567
|
@@ -58,6 +59,7 @@ extern "C" {
|
568
|
struct _class_queue_ {
|
569
|
struct mbuf *tail_; /* Tail of packet queue */
|
570
|
int qlen_; /* Queue length (in number of packets) */
|
571
|
+ int qsize_; /* Queue size (in number of bytes*) */
|
572
|
int qlim_; /* Queue limit (in number of packets*) */
|
573
|
int qtype_; /* Queue type */
|
574
|
};
|
575
|
@@ -67,11 +69,13 @@ typedef struct _class_queue_ class_queue_t;
|
576
|
#define qtype(q) (q)->qtype_ /* Get queue type */
|
577
|
#define qlimit(q) (q)->qlim_ /* Max packets to be queued */
|
578
|
#define qlen(q) (q)->qlen_ /* Current queue length. */
|
579
|
+#define qsize(q) (q)->qsize_ /* Current queue size. */
|
580
|
#define qtail(q) (q)->tail_ /* Tail of the queue */
|
581
|
#define qhead(q) ((q)->tail_ ? (q)->tail_->m_nextpkt : NULL)
|
582
|
|
583
|
#define qempty(q) ((q)->qlen_ == 0) /* Is the queue empty?? */
|
584
|
#define q_is_red(q) ((q)->qtype_ == Q_RED) /* Is the queue a red queue */
|
585
|
+#define q_is_codel(q) ((q)->qtype_ == Q_CODEL) /* Is the queue a codel queue */
|
586
|
#define q_is_rio(q) ((q)->qtype_ == Q_RIO) /* Is the queue a rio queue */
|
587
|
#define q_is_red_or_rio(q) ((q)->qtype_ == Q_RED || (q)->qtype_ == Q_RIO)
|
588
|
|
589
|
@@ -100,6 +104,7 @@ _addq(class_queue_t *q, struct mbuf *m)
|
590
|
m0->m_nextpkt = m;
|
591
|
qtail(q) = m;
|
592
|
qlen(q)++;
|
593
|
+ qsize(q) += m_pktlen(m);
|
594
|
}
|
595
|
|
596
|
static __inline struct mbuf *
|
597
|
@@ -114,6 +119,7 @@ _getq(class_queue_t *q)
|
598
|
else
|
599
|
qtail(q) = NULL;
|
600
|
qlen(q)--;
|
601
|
+ qsize(q) -= m_pktlen(m0);
|
602
|
m0->m_nextpkt = NULL;
|
603
|
return (m0);
|
604
|
}
|
605
|
diff --git a/sys/contrib/altq/altq/altq_codel.c b/sys/contrib/altq/altq/altq_codel.c
|
606
|
new file mode 100644
|
607
|
index 0000000..81628c5
|
608
|
--- /dev/null
|
609
|
+++ b/sys/contrib/altq/altq/altq_codel.c
|
610
|
@@ -0,0 +1,434 @@
|
611
|
+/*
|
612
|
+ * Codel - The Controlled-Delay Active Queue Management algorithm
|
613
|
+ *
|
614
|
+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
|
615
|
+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
|
616
|
+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
|
617
|
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
|
618
|
+ *
|
619
|
+ * Redistribution and use in source and binary forms, with or without
|
620
|
+ * modification, are permitted provided that the following conditions
|
621
|
+ * are met:
|
622
|
+ * 1. Redistributions of source code must retain the above copyright
|
623
|
+ * notice, this list of conditions, and the following disclaimer,
|
624
|
+ * without modification.
|
625
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
626
|
+ * notice, this list of conditions and the following disclaimer in the
|
627
|
+ * documentation and/or other materials provided with the distribution.
|
628
|
+ * 3. The names of the authors may not be used to endorse or promote products
|
629
|
+ * derived from this software without specific prior written permission.
|
630
|
+ *
|
631
|
+ * Alternatively, provided that this notice is retained in full, this
|
632
|
+ * software may be distributed under the terms of the GNU General
|
633
|
+ * Public License ("GPL") version 2, in which case the provisions of the
|
634
|
+ * GPL apply INSTEAD OF those given above.
|
635
|
+ *
|
636
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
637
|
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
638
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
639
|
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
640
|
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
641
|
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
642
|
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
643
|
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
644
|
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
645
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
646
|
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
647
|
+ * DAMAGE.
|
648
|
+ *
|
649
|
+ */
|
650
|
+
|
651
|
+#include <sys/param.h>
|
652
|
+#include <sys/malloc.h>
|
653
|
+#include <sys/mbuf.h>
|
654
|
+#include <sys/socket.h>
|
655
|
+#include <sys/systm.h>
|
656
|
+
|
657
|
+#include <net/if.h>
|
658
|
+#include <netinet/in.h>
|
659
|
+
|
660
|
+#include <net/pfvar.h>
|
661
|
+
|
662
|
+#include <altq/altq.h>
|
663
|
+#include <altq/altq_codel.h>
|
664
|
+
|
665
|
+static int codel_should_drop(struct codel *, class_queue_t *,
|
666
|
+ struct mbuf *, u_int64_t);
|
667
|
+static void codel_Newton_step(struct codel_vars *);
|
668
|
+static u_int64_t codel_control_law(u_int64_t t, u_int64_t, u_int32_t);
|
669
|
+
|
670
|
+#define codel_time_after(a, b) ((int64_t)(a) - (int64_t)(b) > 0)
|
671
|
+#define codel_time_after_eq(a, b) ((int64_t)(a) - (int64_t)(b) >= 0)
|
672
|
+#define codel_time_before(a, b) ((int64_t)(a) - (int64_t)(b) < 0)
|
673
|
+#define codel_time_before_eq(a, b) ((int64_t)(a) - (int64_t)(b) <= 0)
|
674
|
+
|
675
|
+static int codel_request(struct ifaltq *, int, void *);
|
676
|
+
|
677
|
+static int codel_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
|
678
|
+static struct mbuf *codel_dequeue(struct ifaltq *, int);
|
679
|
+
|
680
|
+int
|
681
|
+codel_pfattach(struct pf_altq *a)
|
682
|
+{
|
683
|
+ struct ifnet *ifp;
|
684
|
+ int s, error;
|
685
|
+
|
686
|
+ if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL)
|
687
|
+ return (EINVAL);
|
688
|
+#ifdef __NetBSD__
|
689
|
+ s = splnet();
|
690
|
+#else
|
691
|
+ s = splimp();
|
692
|
+#endif
|
693
|
+ error = altq_attach(&ifp->if_snd, ALTQT_CODEL, a->altq_disc,
|
694
|
+ codel_enqueue, codel_dequeue, codel_request, NULL, NULL);
|
695
|
+ splx(s);
|
696
|
+ return (error);
|
697
|
+}
|
698
|
+
|
699
|
+int
|
700
|
+codel_add_altq(struct pf_altq *a)
|
701
|
+{
|
702
|
+ struct codel_if *cif;
|
703
|
+ struct ifnet *ifp;
|
704
|
+ struct codel_opts *opts;
|
705
|
+
|
706
|
+ if ((ifp = ifunit(a->ifname)) == NULL)
|
707
|
+ return (EINVAL);
|
708
|
+ if (!ALTQ_IS_READY(&ifp->if_snd))
|
709
|
+ return (ENODEV);
|
710
|
+
|
711
|
+ opts = &a->pq_u.codel_opts;
|
712
|
+
|
713
|
+ cif = malloc(sizeof(struct codel_if), M_DEVBUF, M_NOWAIT | M_ZERO);
|
714
|
+ if (cif == NULL)
|
715
|
+ return (ENOMEM);
|
716
|
+ cif->cif_bandwidth = a->ifbandwidth;
|
717
|
+ cif->cif_ifq = &ifp->if_snd;
|
718
|
+
|
719
|
+ cif->cl_q = malloc(sizeof(class_queue_t), M_DEVBUF, M_NOWAIT | M_ZERO);
|
720
|
+ if (cif->cl_q == NULL) {
|
721
|
+ free(cif, M_DEVBUF);
|
722
|
+ return (ENOMEM);
|
723
|
+ }
|
724
|
+
|
725
|
+ if (a->qlimit == 0)
|
726
|
+ a->qlimit = 100;
|
727
|
+ qlimit(cif->cl_q) = a->qlimit;
|
728
|
+ qtype(cif->cl_q) = Q_CODEL;
|
729
|
+ qlen(cif->cl_q) = 0;
|
730
|
+ qsize(cif->cl_q) = 0;
|
731
|
+
|
732
|
+ if (!opts->target)
|
733
|
+ opts->target = a->qlimit;
|
734
|
+ if (!opts->interval)
|
735
|
+ opts->interval = 5;
|
736
|
+ cif->codel.params.target = machclk_freq * opts->target / 1000;
|
737
|
+ cif->codel.params.interval = machclk_freq * opts->interval / 1000;
|
738
|
+ cif->codel.params.ecn = opts->ecn;
|
739
|
+ cif->codel.stats.maxpacket = 256;
|
740
|
+
|
741
|
+ cif->cl_stats.qlength = qlen(cif->cl_q);
|
742
|
+ cif->cl_stats.qlimit = qlimit(cif->cl_q);
|
743
|
+
|
744
|
+ /* keep the state in pf_altq */
|
745
|
+ a->altq_disc = cif;
|
746
|
+
|
747
|
+ return (0);
|
748
|
+}
|
749
|
+
|
750
|
+int
|
751
|
+codel_remove_altq(struct pf_altq *a)
|
752
|
+{
|
753
|
+ struct codel_if *cif;
|
754
|
+
|
755
|
+ if ((cif = a->altq_disc) == NULL)
|
756
|
+ return (EINVAL);
|
757
|
+ a->altq_disc = NULL;
|
758
|
+
|
759
|
+ if (cif->cl_q)
|
760
|
+ free(cif->cl_q, M_DEVBUF);
|
761
|
+ free(cif, M_DEVBUF);
|
762
|
+ return (0);
|
763
|
+}
|
764
|
+
|
765
|
+int
|
766
|
+codel_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
|
767
|
+{
|
768
|
+ struct codel_if *cif;
|
769
|
+ struct codel_ifstats stats;
|
770
|
+ int error = 0;
|
771
|
+
|
772
|
+ if ((cif = altq_lookup(a->ifname, ALTQT_CODEL)) == NULL)
|
773
|
+ return (EBADF);
|
774
|
+
|
775
|
+ if (*nbytes < sizeof(stats))
|
776
|
+ return (EINVAL);
|
777
|
+
|
778
|
+ stats = cif->cl_stats;
|
779
|
+ stats.stats = cif->codel.stats;
|
780
|
+
|
781
|
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
|
782
|
+ return (error);
|
783
|
+ *nbytes = sizeof(stats);
|
784
|
+ return (0);
|
785
|
+}
|
786
|
+
|
787
|
+static int
|
788
|
+codel_request(struct ifaltq *ifq, int req, void *arg)
|
789
|
+{
|
790
|
+ struct codel_if *cif = (struct codel_if *)ifq->altq_disc;
|
791
|
+ struct mbuf *m;
|
792
|
+
|
793
|
+ IFQ_LOCK_ASSERT(ifq);
|
794
|
+
|
795
|
+ switch (req) {
|
796
|
+ case ALTRQ_PURGE:
|
797
|
+ if (!ALTQ_IS_ENABLED(cif->cif_ifq))
|
798
|
+ break;
|
799
|
+
|
800
|
+ if (qempty(cif->cl_q))
|
801
|
+ break;
|
802
|
+
|
803
|
+ while ((m = _getq(cif->cl_q)) != NULL) {
|
804
|
+ PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, m_pktlen(m));
|
805
|
+ m_freem(m);
|
806
|
+ IFQ_DEC_LEN(cif->cif_ifq);
|
807
|
+ }
|
808
|
+ cif->cif_ifq->ifq_len = 0;
|
809
|
+ break;
|
810
|
+ }
|
811
|
+ return (0);
|
812
|
+}
|
813
|
+
|
814
|
+static int
|
815
|
+codel_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pktattr)
|
816
|
+{
|
817
|
+
|
818
|
+ struct codel_if *cif = (struct codel_if *) ifq->altq_disc;
|
819
|
+
|
820
|
+ IFQ_LOCK_ASSERT(ifq);
|
821
|
+
|
822
|
+ /* grab class set by classifier */
|
823
|
+ if ((m->m_flags & M_PKTHDR) == 0) {
|
824
|
+ /* should not happen */
|
825
|
+ printf("altq: packet for %s does not have pkthdr\n",
|
826
|
+ ifq->altq_ifp->if_xname);
|
827
|
+ m_freem(m);
|
828
|
+ PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, m_pktlen(m));
|
829
|
+ return (ENOBUFS);
|
830
|
+ }
|
831
|
+
|
832
|
+ if (codel_addq(&cif->codel, cif->cl_q, m)) {
|
833
|
+ PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, m_pktlen(m));
|
834
|
+ return (ENOBUFS);
|
835
|
+ }
|
836
|
+ IFQ_INC_LEN(ifq);
|
837
|
+
|
838
|
+ return (0);
|
839
|
+}
|
840
|
+
|
841
|
+static struct mbuf *
|
842
|
+codel_dequeue(struct ifaltq *ifq, int op)
|
843
|
+{
|
844
|
+ struct codel_if *cif = (struct codel_if *)ifq->altq_disc;
|
845
|
+ struct mbuf *m;
|
846
|
+
|
847
|
+ IFQ_LOCK_ASSERT(ifq);
|
848
|
+
|
849
|
+ if (IFQ_IS_EMPTY(ifq))
|
850
|
+ return (NULL);
|
851
|
+
|
852
|
+ if (op == ALTDQ_POLL)
|
853
|
+ return (qhead(cif->cl_q));
|
854
|
+
|
855
|
+
|
856
|
+ m = codel_getq(&cif->codel, cif->cl_q);
|
857
|
+ if (m != NULL) {
|
858
|
+ IFQ_DEC_LEN(ifq);
|
859
|
+ PKTCNTR_ADD(&cif->cl_stats.cl_xmitcnt, m_pktlen(m));
|
860
|
+ return (m);
|
861
|
+ }
|
862
|
+
|
863
|
+ return (NULL);
|
864
|
+}
|
865
|
+
|
866
|
+struct codel *
|
867
|
+codel_alloc(int target, int interval, int ecn)
|
868
|
+{
|
869
|
+ struct codel *c;
|
870
|
+
|
871
|
+ c = malloc(sizeof(*c), M_DEVBUF, M_NOWAIT|M_ZERO);
|
872
|
+
|
873
|
+ c->params.target = machclk_freq * target / 1000;
|
874
|
+ c->params.interval = machclk_freq * interval / 1000;
|
875
|
+ c->params.ecn = ecn;
|
876
|
+ c->stats.maxpacket = 256;
|
877
|
+
|
878
|
+ return (c);
|
879
|
+}
|
880
|
+
|
881
|
+void
|
882
|
+codel_destroy(struct codel *c)
|
883
|
+{
|
884
|
+ free(c, M_DEVBUF);
|
885
|
+}
|
886
|
+
|
887
|
+int
|
888
|
+codel_addq(struct codel *c, class_queue_t *q, struct mbuf *m)
|
889
|
+{
|
890
|
+ if (qlen(q) < qlimit(q)) {
|
891
|
+ m->m_pkthdr.enqueue_time = read_machclk();
|
892
|
+ _addq(q, m);
|
893
|
+ return (0);
|
894
|
+ }
|
895
|
+ c->drop_overlimit++;
|
896
|
+ m_freem(m);
|
897
|
+ return (-1);
|
898
|
+}
|
899
|
+
|
900
|
+static int
|
901
|
+codel_should_drop(struct codel *c, class_queue_t *q, struct mbuf *m,
|
902
|
+ u_int64_t now)
|
903
|
+{
|
904
|
+ if (m == NULL) {
|
905
|
+ c->vars.first_above_time = 0;
|
906
|
+ return (0);
|
907
|
+ }
|
908
|
+
|
909
|
+ c->vars.ldelay = now - m->m_pkthdr.enqueue_time;
|
910
|
+ c->stats.maxpacket = MAX(c->stats.maxpacket, m_pktlen(m));
|
911
|
+
|
912
|
+ if (codel_time_before(c->vars.ldelay, c->params.target) ||
|
913
|
+ qsize(q) <= c->stats.maxpacket) {
|
914
|
+ /* went below - stay below for at least interval */
|
915
|
+ c->vars.first_above_time = 0;
|
916
|
+ return (0);
|
917
|
+ }
|
918
|
+ if (c->vars.first_above_time == 0) {
|
919
|
+ /* just went above from below. If we stay above
|
920
|
+ * for at least interval we'll say it's ok to drop
|
921
|
+ */
|
922
|
+ c->vars.first_above_time = now + c->params.interval;
|
923
|
+ return (0);
|
924
|
+ }
|
925
|
+ if (codel_time_after(now, c->vars.first_above_time))
|
926
|
+ return (1);
|
927
|
+ return (0);
|
928
|
+}
|
929
|
+
|
930
|
+/*
|
931
|
+ * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
932
|
+ * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
|
933
|
+ *
|
934
|
+ * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
|
935
|
+ */
|
936
|
+static void codel_Newton_step(struct codel_vars *vars)
|
937
|
+{
|
938
|
+#define REC_INV_SQRT_BITS (8 * sizeof(u_int16_t)) /* or sizeof_in_bits(rec_inv_sqrt) */
|
939
|
+/* needed shift to get a Q0.32 number from rec_inv_sqrt */
|
940
|
+#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
|
941
|
+
|
942
|
+ u_int32_t invsqrt = ((u_int32_t)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
|
943
|
+ u_int32_t invsqrt2 = ((u_int64_t)invsqrt * invsqrt) >> 32;
|
944
|
+ u_int64_t val = (3LL << 32) - ((u_int64_t)vars->count * invsqrt2);
|
945
|
+
|
946
|
+ val >>= 2; /* avoid overflow in following multiply */
|
947
|
+ val = (val * invsqrt) >> (32 - 2 + 1);
|
948
|
+
|
949
|
+ vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
|
950
|
+}
|
951
|
+
|
952
|
+static u_int64_t
|
953
|
+codel_control_law(u_int64_t t, u_int64_t interval, u_int32_t rec_inv_sqrt)
|
954
|
+{
|
955
|
+ return (t + (u_int32_t)(((u_int64_t)interval *
|
956
|
+ (rec_inv_sqrt << REC_INV_SQRT_SHIFT)) >> 32));
|
957
|
+}
|
958
|
+
|
959
|
+struct mbuf *
|
960
|
+codel_getq(struct codel *c, class_queue_t *q)
|
961
|
+{
|
962
|
+ struct mbuf *m;
|
963
|
+ u_int64_t now;
|
964
|
+ int drop;
|
965
|
+
|
966
|
+ if ((m = _getq(q)) == NULL) {
|
967
|
+ c->vars.dropping = 0;
|
968
|
+ return (m);
|
969
|
+ }
|
970
|
+
|
971
|
+ now = read_machclk();
|
972
|
+ drop = codel_should_drop(c, q, m, now);
|
973
|
+ if (c->vars.dropping) {
|
974
|
+ if (!drop) {
|
975
|
+ /* sojourn time below target - leave dropping state */
|
976
|
+ c->vars.dropping = 0;
|
977
|
+ } else if (codel_time_after_eq(now, c->vars.drop_next)) {
|
978
|
+ /* It's time for the next drop. Drop the current
|
979
|
+ * packet and dequeue the next. The dequeue might
|
980
|
+ * take us out of dropping state.
|
981
|
+ * If not, schedule the next drop.
|
982
|
+ * A large backlog might result in drop rates so high
|
983
|
+ * that the next drop should happen now,
|
984
|
+ * hence the while loop.
|
985
|
+ */
|
986
|
+ while (c->vars.dropping &&
|
987
|
+ codel_time_after_eq(now, c->vars.drop_next)) {
|
988
|
+ c->vars.count++; /* don't care of possible wrap
|
989
|
+ * since there is no more
|
990
|
+ * divide */
|
991
|
+ codel_Newton_step(&c->vars);
|
992
|
+ /* TODO ECN */
|
993
|
+ PKTCNTR_ADD(&c->stats.drop_cnt, m_pktlen(m));
|
994
|
+ m_freem(m);
|
995
|
+ m = _getq(q);
|
996
|
+ if (!codel_should_drop(c, q, m, now))
|
997
|
+ /* leave dropping state */
|
998
|
+ c->vars.dropping = 0;
|
999
|
+ else
|
1000
|
+ /* and schedule the next drop */
|
1001
|
+ c->vars.drop_next =
|
1002
|
+ codel_control_law(c->vars.drop_next,
|
1003
|
+ c->params.interval,
|
1004
|
+ c->vars.rec_inv_sqrt);
|
1005
|
+ }
|
1006
|
+ }
|
1007
|
+ } else if (drop) {
|
1008
|
+ /* TODO ECN */
|
1009
|
+ PKTCNTR_ADD(&c->stats.drop_cnt, m_pktlen(m));
|
1010
|
+ m_freem(m);
|
1011
|
+
|
1012
|
+ m = _getq(q);
|
1013
|
+ drop = codel_should_drop(c, q, m, now);
|
1014
|
+
|
1015
|
+ c->vars.dropping = 1;
|
1016
|
+ /* if min went above target close to when we last went below it
|
1017
|
+ * assume that the drop rate that controlled the queue on the
|
1018
|
+ * last cycle is a good starting point to control it now.
|
1019
|
+ */
|
1020
|
+ if (codel_time_before(now - c->vars.drop_next,
|
1021
|
+ 16 * c->params.interval)) {
|
1022
|
+ c->vars.count = (c->vars.count - c->vars.lastcount) | 1;
|
1023
|
+ /* we dont care if rec_inv_sqrt approximation
|
1024
|
+ * is not very precise :
|
1025
|
+ * Next Newton steps will correct it quadratically.
|
1026
|
+ */
|
1027
|
+ codel_Newton_step(&c->vars);
|
1028
|
+ } else {
|
1029
|
+ c->vars.count = 1;
|
1030
|
+ c->vars.rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
|
1031
|
+ }
|
1032
|
+ c->vars.lastcount = c->vars.count;
|
1033
|
+ c->vars.drop_next = codel_control_law(now, c->params.interval,
|
1034
|
+ c->vars.rec_inv_sqrt);
|
1035
|
+ }
|
1036
|
+
|
1037
|
+ return m;
|
1038
|
+}
|
1039
|
+
|
1040
|
+void
|
1041
|
+codel_getstats(struct codel *c, struct codel_stats *s)
|
1042
|
+{
|
1043
|
+ *s = c->stats;
|
1044
|
+}
|
1045
|
diff --git a/sys/contrib/altq/altq/altq_codel.h b/sys/contrib/altq/altq/altq_codel.h
|
1046
|
new file mode 100644
|
1047
|
index 0000000..9413ae1
|
1048
|
--- /dev/null
|
1049
|
+++ b/sys/contrib/altq/altq/altq_codel.h
|
1050
|
@@ -0,0 +1,87 @@
|
1051
|
+#ifndef _ALTQ_ALTQ_CODEL_H_
|
1052
|
+#define _ALTQ_ALTQ_CODEL_H_
|
1053
|
+
|
1054
|
+struct codel_stats {
|
1055
|
+ u_int32_t maxpacket;
|
1056
|
+ struct pktcntr drop_cnt;
|
1057
|
+ u_int marked_packets;
|
1058
|
+};
|
1059
|
+
|
1060
|
+struct codel_ifstats {
|
1061
|
+ u_int qlength;
|
1062
|
+ u_int qlimit;
|
1063
|
+ struct codel_stats stats;
|
1064
|
+ struct pktcntr cl_xmitcnt; /* transmitted packet counter */
|
1065
|
+ struct pktcntr cl_dropcnt; /* dropped packet counter */
|
1066
|
+};
|
1067
|
+
|
1068
|
+#ifdef _KERNEL
|
1069
|
+#include <altq/altq_classq.h>
|
1070
|
+
|
1071
|
+/**
|
1072
|
+ * struct codel_params - contains codel parameters
|
1073
|
+ * <at> target: target queue size (in time units)
|
1074
|
+ * <at> interval: width of moving time window
|
1075
|
+ * <at> ecn: is Explicit Congestion Notification enabled
|
1076
|
+ */
|
1077
|
+struct codel_params {
|
1078
|
+ u_int64_t target;
|
1079
|
+ u_int64_t interval;
|
1080
|
+ int ecn;
|
1081
|
+};
|
1082
|
+
|
1083
|
+/**
|
1084
|
+ * struct codel_vars - contains codel variables
|
1085
|
+ * <at> count: how many drops we've done since the last time we
|
1086
|
+ * entered dropping state
|
1087
|
+ * <at> lastcount: count at entry to dropping state
|
1088
|
+ * <at> dropping: set to true if in dropping state
|
1089
|
+ * <at> rec_inv_sqrt: reciprocal value of sqrt(count) >> 1
|
1090
|
+ * <at> first_above_time: when we went (or will go) continuously above target
|
1091
|
+ * for interval
|
1092
|
+ * <at> drop_next: time to drop next packet, or when we dropped last
|
1093
|
+ * <at> ldelay: sojourn time of last dequeued packet
|
1094
|
+ */
|
1095
|
+struct codel_vars {
|
1096
|
+ u_int32_t count;
|
1097
|
+ u_int32_t lastcount;
|
1098
|
+ int dropping;
|
1099
|
+ u_int16_t rec_inv_sqrt;
|
1100
|
+ u_int64_t first_above_time;
|
1101
|
+ u_int64_t drop_next;
|
1102
|
+ u_int64_t ldelay;
|
1103
|
+};
|
1104
|
+
|
1105
|
+struct codel {
|
1106
|
+ struct codel_params params;
|
1107
|
+ struct codel_vars vars;
|
1108
|
+ struct codel_stats stats;
|
1109
|
+ u_int32_t drop_overlimit;
|
1110
|
+};
|
1111
|
+
|
1112
|
+/*
|
1113
|
+ * codel interface state
|
1114
|
+ */
|
1115
|
+struct codel_if {
|
1116
|
+ struct codel_if *cif_next; /* interface state list */
|
1117
|
+ struct ifaltq *cif_ifq; /* backpointer to ifaltq */
|
1118
|
+ u_int cif_bandwidth; /* link bandwidth in bps */
|
1119
|
+
|
1120
|
+ class_queue_t *cl_q; /* class queue structure */
|
1121
|
+ struct codel codel;
|
1122
|
+
|
1123
|
+ /* statistics */
|
1124
|
+ struct codel_ifstats cl_stats;
|
1125
|
+};
|
1126
|
+
|
1127
|
+struct codel;
|
1128
|
+
|
1129
|
+struct codel *codel_alloc(int, int, int);
|
1130
|
+void codel_destroy(struct codel *);
|
1131
|
+int codel_addq(struct codel *, class_queue_t *, struct mbuf *);
|
1132
|
+struct mbuf *codel_getq(struct codel *, class_queue_t *);
|
1133
|
+void codel_getstats(struct codel *, struct codel_stats *);
|
1134
|
+
|
1135
|
+#endif
|
1136
|
+
|
1137
|
+#endif /* _ALTQ_ALTQ_CODEL_H_ */
|
1138
|
diff --git a/sys/contrib/altq/altq/altq_fairq.c b/sys/contrib/altq/altq/altq_fairq.c
|
1139
|
index 2267bfd..2277aa8 100644
|
1140
|
--- a/sys/contrib/altq/altq/altq_fairq.c
|
1141
|
+++ b/sys/contrib/altq/altq/altq_fairq.c
|
1142
|
@@ -156,10 +156,7 @@ fairq_add_altq(struct pf_altq *a)
|
1143
|
|
1144
|
|
1145
|
MALLOC(pif, struct fairq_if *, sizeof(struct fairq_if),
|
1146
|
- M_DEVBUF, M_WAITOK);
|
1147
|
- if (pif == NULL)
|
1148
|
- return (ENOMEM);
|
1149
|
- bzero(pif, sizeof(struct fairq_if));
|
1150
|
+ M_DEVBUF, M_WAITOK|M_ZERO);
|
1151
|
pif->pif_bandwidth = a->ifbandwidth;
|
1152
|
pif->pif_maxpri = -1;
|
1153
|
pif->pif_ifq = &ifp->if_snd;
|
1154
|
@@ -318,6 +315,14 @@ fairq_class_create(struct fairq_if *pif, int pri, int qlimit,
|
1155
|
return (NULL);
|
1156
|
}
|
1157
|
#endif
|
1158
|
+#ifndef ALTQ_CODEL
|
1159
|
+ if (flags & FARF_CODEL) {
|
1160
|
+#ifdef ALTQ_DEBUG
|
1161
|
+ printf("fairq_class_create: CODEL not configured for FAIRQ!\n");
|
1162
|
+#endif
|
1163
|
+ return (NULL);
|
1164
|
+ }
|
1165
|
+#endif
|
1166
|
if (nbuckets == 0)
|
1167
|
nbuckets = 256;
|
1168
|
if (nbuckets > FAIRQ_MAX_BUCKETS)
|
1169
|
@@ -342,6 +347,10 @@ fairq_class_create(struct fairq_if *pif, int pri, int qlimit,
|
1170
|
if (cl->cl_qtype == Q_RED)
|
1171
|
red_destroy(cl->cl_red);
|
1172
|
#endif
|
1173
|
+#ifdef ALTQ_CODEL
|
1174
|
+ if (cl->cl_qtype == Q_CODEL)
|
1175
|
+ codel_destroy(cl->cl_codel);
|
1176
|
+#endif
|
1177
|
} else {
|
1178
|
MALLOC(cl, struct fairq_class *, sizeof(struct fairq_class),
|
1179
|
M_DEVBUF, M_WAITOK);
|
1180
|
@@ -415,6 +424,12 @@ fairq_class_create(struct fairq_if *pif, int pri, int qlimit,
|
1181
|
}
|
1182
|
}
|
1183
|
#endif /* ALTQ_RED */
|
1184
|
+#ifdef ALTQ_CODEL
|
1185
|
+ if (flags & FARF_CODEL) {
|
1186
|
+ cl->cl_codel = codel_alloc(100, 5, 0);
|
1187
|
+ cl->cl_qtype = Q_CODEL;
|
1188
|
+ }
|
1189
|
+#endif
|
1190
|
|
1191
|
return (cl);
|
1192
|
|
1193
|
@@ -431,6 +446,10 @@ err_ret:
|
1194
|
if (cl->cl_qtype == Q_RED)
|
1195
|
red_destroy(cl->cl_red);
|
1196
|
#endif
|
1197
|
+#ifdef ALTQ_CODEL
|
1198
|
+ if (cl->cl_qtype == Q_CODEL)
|
1199
|
+ codel_destroy(cl->cl_codel);
|
1200
|
+#endif
|
1201
|
}
|
1202
|
if (cl != NULL)
|
1203
|
FREE(cl, M_DEVBUF);
|
1204
|
@@ -474,6 +493,10 @@ fairq_class_destroy(struct fairq_class *cl)
|
1205
|
if (cl->cl_qtype == Q_RED)
|
1206
|
red_destroy(cl->cl_red);
|
1207
|
#endif
|
1208
|
+#ifdef ALTQ_CODEL
|
1209
|
+ if (cl->cl_qtype == Q_CODEL)
|
1210
|
+ codel_destroy(cl->cl_codel);
|
1211
|
+#endif
|
1212
|
}
|
1213
|
FREE(cl->cl_buckets, M_DEVBUF);
|
1214
|
cl->cl_head = NULL; /* sanity */
|
1215
|
@@ -671,6 +694,10 @@ fairq_addq(struct fairq_class *cl, struct mbuf *m, u_int32_t bucketid)
|
1216
|
if (cl->cl_qtype == Q_RED)
|
1217
|
return red_addq(cl->cl_red, &b->queue, m, cl->cl_pktattr);
|
1218
|
#endif
|
1219
|
+#ifdef ALTQ_CODEL
|
1220
|
+ if (cl->cl_qtype == Q_CODEL)
|
1221
|
+ return codel_addq(cl->cl_codel, &b->queue, m);
|
1222
|
+#endif
|
1223
|
if (qlen(&b->queue) >= qlimit(&b->queue)) {
|
1224
|
m_freem(m);
|
1225
|
return (-1);
|
1226
|
@@ -701,6 +728,10 @@ fairq_getq(struct fairq_class *cl, uint64_t cur_time)
|
1227
|
else if (cl->cl_qtype == Q_RED)
|
1228
|
m = red_getq(cl->cl_red, &b->queue);
|
1229
|
#endif
|
1230
|
+#ifdef ALTQ_CODEL
|
1231
|
+ else if (cl->cl_qtype == Q_CODEL)
|
1232
|
+ m = codel_getq(cl->cl_codel, &b->queue);
|
1233
|
+#endif
|
1234
|
else
|
1235
|
m = _getq(&b->queue);
|
1236
|
|
1237
|
@@ -882,6 +913,10 @@ get_class_stats(struct fairq_classstats *sp, struct fairq_class *cl)
|
1238
|
if (cl->cl_qtype == Q_RIO)
|
1239
|
rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
|
1240
|
#endif
|
1241
|
+#ifdef ALTQ_CODEL
|
1242
|
+ if (cl->cl_qtype == Q_CODEL)
|
1243
|
+ codel_getstats(cl->cl_codel, &sp->codel);
|
1244
|
+#endif
|
1245
|
}
|
1246
|
|
1247
|
/* convert a class handle to the corresponding class pointer */
|
1248
|
diff --git a/sys/contrib/altq/altq/altq_fairq.h b/sys/contrib/altq/altq/altq_fairq.h
|
1249
|
index e4675e0..f13513b 100644
|
1250
|
--- a/sys/contrib/altq/altq/altq_fairq.h
|
1251
|
+++ b/sys/contrib/altq/altq/altq_fairq.h
|
1252
|
@@ -42,6 +42,7 @@
|
1253
|
#include <altq/altq_red.h>
|
1254
|
#include <altq/altq_rio.h>
|
1255
|
#include <altq/altq_rmclass.h>
|
1256
|
+#include <altq/altq_codel.h>
|
1257
|
|
1258
|
#define FAIRQ_MAX_BUCKETS 2048 /* maximum number of sorting buckets */
|
1259
|
#define FAIRQ_MAXPRI RM_MAXPRIO
|
1260
|
@@ -52,6 +53,7 @@
|
1261
|
#define FARF_RED 0x0001 /* use RED */
|
1262
|
#define FARF_ECN 0x0002 /* use RED/ECN */
|
1263
|
#define FARF_RIO 0x0004 /* use RIO */
|
1264
|
+#define FARF_CODEL 0x0008 /* use CODEL */
|
1265
|
#define FARF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
|
1266
|
#define FARF_DEFAULTCLASS 0x1000 /* default class */
|
1267
|
|
1268
|
@@ -76,6 +78,7 @@ struct fairq_classstats {
|
1269
|
/* red and rio related info */
|
1270
|
int qtype;
|
1271
|
struct redstats red[3]; /* rio has 3 red stats */
|
1272
|
+ struct codel_stats codel;
|
1273
|
};
|
1274
|
|
1275
|
#ifdef _KERNEL
|
1276
|
@@ -97,7 +100,10 @@ struct fairq_class {
|
1277
|
fairq_bucket_t *cl_buckets;
|
1278
|
fairq_bucket_t *cl_head; /* head of circular bucket list */
|
1279
|
fairq_bucket_t *cl_polled;
|
1280
|
- struct red *cl_red; /* RED state */
|
1281
|
+ union {
|
1282
|
+ struct red *cl_red; /* RED state */
|
1283
|
+ struct codel *cl_codel;
|
1284
|
+ } cl_aqm;
|
1285
|
u_int cl_hogs_m1;
|
1286
|
u_int cl_lssc_m1;
|
1287
|
u_int cl_bandwidth;
|
1288
|
@@ -117,6 +123,8 @@ struct fairq_class {
|
1289
|
struct pktcntr cl_xmitcnt; /* transmitted packet counter */
|
1290
|
struct pktcntr cl_dropcnt; /* dropped packet counter */
|
1291
|
};
|
1292
|
+#define cl_red cl_aqm.cl_red
|
1293
|
+#define cl_codel cl_aqm.cl_codel
|
1294
|
|
1295
|
/*
|
1296
|
* fairq interface state
|
1297
|
diff --git a/sys/contrib/altq/altq/altq_hfsc.c b/sys/contrib/altq/altq/altq_hfsc.c
|
1298
|
index 0363016..b87ac3a 100644
|
1299
|
--- a/sys/contrib/altq/altq/altq_hfsc.c
|
1300
|
+++ b/sys/contrib/altq/altq/altq_hfsc.c
|
1301
|
@@ -391,6 +391,14 @@ hfsc_class_create(struct hfsc_if *hif, struct service_curve *rsc,
|
1302
|
return (NULL);
|
1303
|
}
|
1304
|
#endif
|
1305
|
+#ifndef ALTQ_CODEL
|
1306
|
+ if (flags & HFCF_CODEL) {
|
1307
|
+#ifdef ALTQ_DEBUG
|
1308
|
+ printf("hfsc_class_create: CODEL not configured for HFSC!\n");
|
1309
|
+#endif
|
1310
|
+ return (NULL);
|
1311
|
+ }
|
1312
|
+#endif
|
1313
|
|
1314
|
cl = malloc(sizeof(struct hfsc_class), M_DEVBUF, M_NOWAIT | M_ZERO);
|
1315
|
if (cl == NULL)
|
1316
|
@@ -407,6 +415,7 @@ hfsc_class_create(struct hfsc_if *hif, struct service_curve *rsc,
|
1317
|
qlimit(cl->cl_q) = qlimit;
|
1318
|
qtype(cl->cl_q) = Q_DROPTAIL;
|
1319
|
qlen(cl->cl_q) = 0;
|
1320
|
+ qsize(cl->cl_q) = 0;
|
1321
|
cl->cl_flags = flags;
|
1322
|
#ifdef ALTQ_RED
|
1323
|
if (flags & (HFCF_RED|HFCF_RIO)) {
|
1324
|
@@ -451,6 +460,12 @@ hfsc_class_create(struct hfsc_if *hif, struct service_curve *rsc,
|
1325
|
#endif
|
1326
|
}
|
1327
|
#endif /* ALTQ_RED */
|
1328
|
+#ifdef ALTQ_CODEL
|
1329
|
+ if (flags & HFCF_CODEL) {
|
1330
|
+ cl->cl_codel = codel_alloc(100, 5, 0);
|
1331
|
+ qtype(cl->cl_q) = Q_CODEL;
|
1332
|
+ }
|
1333
|
+#endif
|
1334
|
|
1335
|
if (rsc != NULL && (rsc->m1 != 0 || rsc->m2 != 0)) {
|
1336
|
cl->cl_rsc = malloc(sizeof(struct internal_sc),
|
1337
|
@@ -543,6 +558,10 @@ hfsc_class_create(struct hfsc_if *hif, struct service_curve *rsc,
|
1338
|
if (q_is_red(cl->cl_q))
|
1339
|
red_destroy(cl->cl_red);
|
1340
|
#endif
|
1341
|
+#ifdef ALTQ_CODEL
|
1342
|
+ if (q_is_codel(cl->cl_q))
|
1343
|
+ codel_destroy(cl->cl_codel);
|
1344
|
+#endif
|
1345
|
}
|
1346
|
if (cl->cl_fsc != NULL)
|
1347
|
free(cl->cl_fsc, M_DEVBUF);
|
1348
|
@@ -617,6 +636,10 @@ hfsc_class_destroy(struct hfsc_class *cl)
|
1349
|
if (q_is_red(cl->cl_q))
|
1350
|
red_destroy(cl->cl_red);
|
1351
|
#endif
|
1352
|
+#ifdef ALTQ_CODEL
|
1353
|
+ if (q_is_codel(cl->cl_q))
|
1354
|
+ codel_destroy(cl->cl_codel);
|
1355
|
+#endif
|
1356
|
}
|
1357
|
|
1358
|
IFQ_LOCK(cl->cl_hif->hif_ifq);
|
1359
|
@@ -844,6 +867,10 @@ hfsc_addq(struct hfsc_class *cl, struct mbuf *m)
|
1360
|
if (q_is_red(cl->cl_q))
|
1361
|
return red_addq(cl->cl_red, cl->cl_q, m, cl->cl_pktattr);
|
1362
|
#endif
|
1363
|
+#ifdef ALTQ_CODEL
|
1364
|
+ if (q_is_codel(cl->cl_q))
|
1365
|
+ return codel_addq(cl->cl_codel, cl->cl_q, m);
|
1366
|
+#endif
|
1367
|
if (qlen(cl->cl_q) >= qlimit(cl->cl_q)) {
|
1368
|
m_freem(m);
|
1369
|
return (-1);
|
1370
|
@@ -868,6 +895,10 @@ hfsc_getq(struct hfsc_class *cl)
|
1371
|
if (q_is_red(cl->cl_q))
|
1372
|
return red_getq(cl->cl_red, cl->cl_q);
|
1373
|
#endif
|
1374
|
+#ifdef ALTQ_CODEL
|
1375
|
+ if (q_is_codel(cl->cl_q))
|
1376
|
+ return codel_getq(cl->cl_codel, cl->cl_q);
|
1377
|
+#endif
|
1378
|
return _getq(cl->cl_q);
|
1379
|
}
|
1380
|
|
1381
|
@@ -1652,6 +1683,10 @@ get_class_stats(struct hfsc_classstats *sp, struct hfsc_class *cl)
|
1382
|
if (q_is_rio(cl->cl_q))
|
1383
|
rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
|
1384
|
#endif
|
1385
|
+#ifdef ALTQ_CODEL
|
1386
|
+ if (q_is_codel(cl->cl_q))
|
1387
|
+ codel_getstats(cl->cl_codel, &sp->codel);
|
1388
|
+#endif
|
1389
|
}
|
1390
|
|
1391
|
/* convert a class handle to the corresponding class pointer */
|
1392
|
diff --git a/sys/contrib/altq/altq/altq_hfsc.h b/sys/contrib/altq/altq/altq_hfsc.h
|
1393
|
index e5595cb..c8e9b13 100644
|
1394
|
--- a/sys/contrib/altq/altq/altq_hfsc.h
|
1395
|
+++ b/sys/contrib/altq/altq/altq_hfsc.h
|
1396
|
@@ -36,6 +36,7 @@
|
1397
|
#include <altq/altq_classq.h>
|
1398
|
#include <altq/altq_red.h>
|
1399
|
#include <altq/altq_rio.h>
|
1400
|
+#include <altq/altq_codel.h>
|
1401
|
|
1402
|
#ifdef __cplusplus
|
1403
|
extern "C" {
|
1404
|
@@ -55,6 +56,7 @@ struct service_curve {
|
1405
|
#define HFCF_RED 0x0001 /* use RED */
|
1406
|
#define HFCF_ECN 0x0002 /* use RED/ECN */
|
1407
|
#define HFCF_RIO 0x0004 /* use RIO */
|
1408
|
+#define HFCF_CODEL 0x0008 /* use CODEL */
|
1409
|
#define HFCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
|
1410
|
#define HFCF_DEFAULTCLASS 0x1000 /* default class */
|
1411
|
|
1412
|
@@ -104,6 +106,7 @@ struct hfsc_classstats {
|
1413
|
/* red and rio related info */
|
1414
|
int qtype;
|
1415
|
struct redstats red[3];
|
1416
|
+ struct codel_stats codel;
|
1417
|
};
|
1418
|
|
1419
|
#ifdef ALTQ3_COMPAT
|
1420
|
@@ -229,7 +232,10 @@ struct hfsc_class {
|
1421
|
struct hfsc_class *cl_children; /* child classes */
|
1422
|
|
1423
|
class_queue_t *cl_q; /* class queue structure */
|
1424
|
- struct red *cl_red; /* RED state */
|
1425
|
+ union {
|
1426
|
+ struct red *cl_red; /* RED state */
|
1427
|
+ struct codel *cl_codel; /* CoDel state */
|
1428
|
+ } cl_aqm;
|
1429
|
struct altq_pktattr *cl_pktattr; /* saved header used by ECN */
|
1430
|
|
1431
|
u_int64_t cl_total; /* total work in bytes */
|
1432
|
@@ -278,6 +284,8 @@ struct hfsc_class {
|
1433
|
u_int period;
|
1434
|
} cl_stats;
|
1435
|
};
|
1436
|
+#define cl_red cl_aqm.cl_red
|
1437
|
+#define cl_codel cl_aqm.cl_codel
|
1438
|
|
1439
|
/*
|
1440
|
* hfsc interface state
|
1441
|
diff --git a/sys/contrib/altq/altq/altq_priq.c b/sys/contrib/altq/altq/altq_priq.c
|
1442
|
index 3ce65dc..cea88be 100644
|
1443
|
--- a/sys/contrib/altq/altq/altq_priq.c
|
1444
|
+++ b/sys/contrib/altq/altq/altq_priq.c
|
1445
|
@@ -297,6 +297,15 @@ priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
|
1446
|
return (NULL);
|
1447
|
}
|
1448
|
#endif
|
1449
|
+#ifndef ALTQ_CODEL
|
1450
|
+ if (flags & PRCF_CODEL) {
|
1451
|
+#ifdef ALTQ_DEBUG
|
1452
|
+ printf("priq_class_create: CODEL not configured for PRIQ!\n");
|
1453
|
+#endif
|
1454
|
+ return (NULL);
|
1455
|
+ }
|
1456
|
+#endif
|
1457
|
+
|
1458
|
|
1459
|
if ((cl = pif->pif_classes[pri]) != NULL) {
|
1460
|
/* modify the class instead of creating a new one */
|
1461
|
@@ -318,6 +327,10 @@ priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
|
1462
|
if (q_is_red(cl->cl_q))
|
1463
|
red_destroy(cl->cl_red);
|
1464
|
#endif
|
1465
|
+#ifdef ALTQ_CODEL
|
1466
|
+ if (q_is_codel(cl->cl_q))
|
1467
|
+ codel_destroy(cl->cl_codel);
|
1468
|
+#endif
|
1469
|
} else {
|
1470
|
cl = malloc(sizeof(struct priq_class), M_DEVBUF,
|
1471
|
M_NOWAIT | M_ZERO);
|
1472
|
@@ -338,6 +351,7 @@ priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
|
1473
|
qlimit(cl->cl_q) = qlimit;
|
1474
|
qtype(cl->cl_q) = Q_DROPTAIL;
|
1475
|
qlen(cl->cl_q) = 0;
|
1476
|
+ qsize(cl->cl_q) = 0;
|
1477
|
cl->cl_flags = flags;
|
1478
|
cl->cl_pri = pri;
|
1479
|
if (pri > pif->pif_maxpri)
|
1480
|
@@ -381,6 +395,12 @@ priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
|
1481
|
}
|
1482
|
}
|
1483
|
#endif /* ALTQ_RED */
|
1484
|
+#ifdef ALTQ_CODEL
|
1485
|
+ if (flags & PRCF_CODEL) {
|
1486
|
+ cl->cl_codel = codel_alloc(100, 5, 0);
|
1487
|
+ qtype(cl->cl_q) = Q_CODEL;
|
1488
|
+ }
|
1489
|
+#endif
|
1490
|
|
1491
|
return (cl);
|
1492
|
|
1493
|
@@ -394,6 +414,10 @@ priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
|
1494
|
if (q_is_red(cl->cl_q))
|
1495
|
red_destroy(cl->cl_red);
|
1496
|
#endif
|
1497
|
+#ifdef ALTQ_CODEL
|
1498
|
+ if (q_is_codel(cl->cl_q))
|
1499
|
+ codel_destroy(cl->cl_codel);
|
1500
|
+#endif
|
1501
|
}
|
1502
|
if (cl->cl_q != NULL)
|
1503
|
free(cl->cl_q, M_DEVBUF);
|
1504
|
@@ -445,6 +469,10 @@ priq_class_destroy(struct priq_class *cl)
|
1505
|
if (q_is_red(cl->cl_q))
|
1506
|
red_destroy(cl->cl_red);
|
1507
|
#endif
|
1508
|
+#ifdef ALTQ_CODEL
|
1509
|
+ if (q_is_codel(cl->cl_q))
|
1510
|
+ codel_destroy(cl->cl_codel);
|
1511
|
+#endif
|
1512
|
}
|
1513
|
free(cl->cl_q, M_DEVBUF);
|
1514
|
free(cl, M_DEVBUF);
|
1515
|
@@ -560,6 +588,10 @@ priq_addq(struct priq_class *cl, struct mbuf *m)
|
1516
|
if (q_is_red(cl->cl_q))
|
1517
|
return red_addq(cl->cl_red, cl->cl_q, m, cl->cl_pktattr);
|
1518
|
#endif
|
1519
|
+#ifdef ALTQ_CODEL
|
1520
|
+ if (q_is_codel(cl->cl_q))
|
1521
|
+ return codel_addq(cl->cl_codel, cl->cl_q, m);
|
1522
|
+#endif
|
1523
|
if (qlen(cl->cl_q) >= qlimit(cl->cl_q)) {
|
1524
|
m_freem(m);
|
1525
|
return (-1);
|
1526
|
@@ -584,6 +616,10 @@ priq_getq(struct priq_class *cl)
|
1527
|
if (q_is_red(cl->cl_q))
|
1528
|
return red_getq(cl->cl_red, cl->cl_q);
|
1529
|
#endif
|
1530
|
+#ifdef ALTQ_CODEL
|
1531
|
+ if (q_is_codel(cl->cl_q))
|
1532
|
+ return codel_getq(cl->cl_codel, cl->cl_q);
|
1533
|
+#endif
|
1534
|
return _getq(cl->cl_q);
|
1535
|
}
|
1536
|
|
1537
|
@@ -628,6 +664,10 @@ get_class_stats(struct priq_classstats *sp, struct priq_class *cl)
|
1538
|
if (q_is_rio(cl->cl_q))
|
1539
|
rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
|
1540
|
#endif
|
1541
|
+#ifdef ALTQ_CODEL
|
1542
|
+ if (q_is_codel(cl->cl_q))
|
1543
|
+ codel_getstats(cl->cl_codel, &sp->codel);
|
1544
|
+#endif
|
1545
|
|
1546
|
}
|
1547
|
|
1548
|
diff --git a/sys/contrib/altq/altq/altq_priq.h b/sys/contrib/altq/altq/altq_priq.h
|
1549
|
index 481d31b..b5b062f 100644
|
1550
|
--- a/sys/contrib/altq/altq/altq_priq.h
|
1551
|
+++ b/sys/contrib/altq/altq/altq_priq.h
|
1552
|
@@ -32,6 +32,7 @@
|
1553
|
#include <altq/altq_classq.h>
|
1554
|
#include <altq/altq_red.h>
|
1555
|
#include <altq/altq_rio.h>
|
1556
|
+#include <altq/altq_codel.h>
|
1557
|
|
1558
|
#ifdef __cplusplus
|
1559
|
extern "C" {
|
1560
|
@@ -59,6 +60,7 @@ struct priq_add_class {
|
1561
|
#define PRCF_RED 0x0001 /* use RED */
|
1562
|
#define PRCF_ECN 0x0002 /* use RED/ECN */
|
1563
|
#define PRCF_RIO 0x0004 /* use RIO */
|
1564
|
+#define PRCF_CODEL 0x0008 /* use CODEL */
|
1565
|
#define PRCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
|
1566
|
#define PRCF_DEFAULTCLASS 0x1000 /* default class */
|
1567
|
|
1568
|
@@ -105,6 +107,7 @@ struct priq_classstats {
|
1569
|
/* red and rio related info */
|
1570
|
int qtype;
|
1571
|
struct redstats red[3]; /* rio has 3 red stats */
|
1572
|
+ struct codel_stats codel;
|
1573
|
};
|
1574
|
|
1575
|
#ifdef ALTQ3_COMPAT
|
1576
|
@@ -134,7 +137,10 @@ struct priq_class_stats {
|
1577
|
struct priq_class {
|
1578
|
u_int32_t cl_handle; /* class handle */
|
1579
|
class_queue_t *cl_q; /* class queue structure */
|
1580
|
- struct red *cl_red; /* RED state */
|
1581
|
+ union {
|
1582
|
+ struct red *cl_red; /* RED state */
|
1583
|
+ struct codel *cl_codel; /* CoDel state */
|
1584
|
+ } cl_aqm;
|
1585
|
int cl_pri; /* priority */
|
1586
|
int cl_flags; /* class flags */
|
1587
|
struct priq_if *cl_pif; /* back pointer to pif */
|
1588
|
@@ -145,7 +151,8 @@ struct priq_class {
|
1589
|
struct pktcntr cl_xmitcnt; /* transmitted packet counter */
|
1590
|
struct pktcntr cl_dropcnt; /* dropped packet counter */
|
1591
|
};
|
1592
|
-
|
1593
|
+#define cl_red cl_aqm.cl_red
|
1594
|
+#define cl_codel cl_aqm.cl_codel
|
1595
|
/*
|
1596
|
* priq interface state
|
1597
|
*/
|
1598
|
diff --git a/sys/contrib/altq/altq/altq_rmclass.c b/sys/contrib/altq/altq/altq_rmclass.c
|
1599
|
index c433024..7208c60 100644
|
1600
|
--- a/sys/contrib/altq/altq/altq_rmclass.c
|
1601
|
+++ b/sys/contrib/altq/altq/altq_rmclass.c
|
1602
|
@@ -72,6 +72,7 @@
|
1603
|
#include <altq/altq_rmclass_debug.h>
|
1604
|
#include <altq/altq_red.h>
|
1605
|
#include <altq/altq_rio.h>
|
1606
|
+#include <altq/altq_codel.h>
|
1607
|
|
1608
|
/*
|
1609
|
* Local Macros
|
1610
|
@@ -218,6 +219,14 @@ rmc_newclass(int pri, struct rm_ifdat *ifd, u_int nsecPerByte,
|
1611
|
return (NULL);
|
1612
|
}
|
1613
|
#endif
|
1614
|
+#ifndef ALTQ_CODEL
|
1615
|
+ if (flags & RMCF_CODEL) {
|
1616
|
+#ifdef ALTQ_DEBUG
|
1617
|
+ printf("rmc_newclass: CODEL not configured for CBQ!\n");
|
1618
|
+#endif
|
1619
|
+ return (NULL);
|
1620
|
+ }
|
1621
|
+#endif
|
1622
|
|
1623
|
cl = malloc(sizeof(struct rm_class), M_DEVBUF, M_NOWAIT | M_ZERO);
|
1624
|
if (cl == NULL)
|
1625
|
@@ -302,6 +311,12 @@ rmc_newclass(int pri, struct rm_ifdat *ifd, u_int nsecPerByte,
|
1626
|
#endif
|
1627
|
}
|
1628
|
#endif /* ALTQ_RED */
|
1629
|
+#ifdef ALTQ_CODEL
|
1630
|
+ if (flags & RMCF_CODEL) {
|
1631
|
+ cl->codel_ = codel_alloc(100, 5, 0);
|
1632
|
+ qtype(cl->q_) = Q_CODEL;
|
1633
|
+ }
|
1634
|
+#endif
|
1635
|
|
1636
|
/*
|
1637
|
* put the class into the class tree
|
1638
|
@@ -652,6 +667,10 @@ rmc_delete_class(struct rm_ifdat *ifd, struct rm_class *cl)
|
1639
|
if (q_is_red(cl->q_))
|
1640
|
red_destroy(cl->red_);
|
1641
|
#endif
|
1642
|
+#ifdef ALTQ_CODEL
|
1643
|
+ if (q_is_codel(cl->q_))
|
1644
|
+ codel_destroy(cl->codel_);
|
1645
|
+#endif
|
1646
|
}
|
1647
|
free(cl->q_, M_DEVBUF);
|
1648
|
free(cl, M_DEVBUF);
|
1649
|
@@ -1618,6 +1637,10 @@ _rmc_addq(rm_class_t *cl, mbuf_t *m)
|
1650
|
if (q_is_red(cl->q_))
|
1651
|
return red_addq(cl->red_, cl->q_, m, cl->pktattr_);
|
1652
|
#endif /* ALTQ_RED */
|
1653
|
+#ifdef ALTQ_CODEL
|
1654
|
+ if (q_is_codel(cl->q_))
|
1655
|
+ return codel_addq(cl->codel_, cl->q_, m);
|
1656
|
+#endif /* ALTQ_RED */
|
1657
|
|
1658
|
if (cl->flags_ & RMCF_CLEARDSCP)
|
1659
|
write_dsfield(m, cl->pktattr_, 0);
|
1660
|
@@ -1647,6 +1670,10 @@ _rmc_getq(rm_class_t *cl)
|
1661
|
if (q_is_red(cl->q_))
|
1662
|
return red_getq(cl->red_, cl->q_);
|
1663
|
#endif
|
1664
|
+#ifdef ALTQ_CODEL
|
1665
|
+ if (q_is_codel(cl->q_))
|
1666
|
+ return codel_getq(cl->codel_, cl->q_);
|
1667
|
+#endif
|
1668
|
return _getq(cl->q_);
|
1669
|
}
|
1670
|
|
1671
|
@@ -1717,7 +1744,7 @@ void cbqtrace_dump(int counter)
|
1672
|
#endif /* CBQ_TRACE */
|
1673
|
#endif /* ALTQ_CBQ */
|
1674
|
|
1675
|
-#if defined(ALTQ_CBQ) || defined(ALTQ_RED) || defined(ALTQ_RIO) || defined(ALTQ_HFSC) || defined(ALTQ_PRIQ)
|
1676
|
+#if defined(ALTQ_CBQ) || defined(ALTQ_RED) || defined(ALTQ_RIO) || defined(ALTQ_HFSC) || defined(ALTQ_PRIQ) || defined(ALTQ_CODEL)
|
1677
|
#if !defined(__GNUC__) || defined(ALTQ_DEBUG)
|
1678
|
|
1679
|
void
|
1680
|
diff --git a/sys/contrib/altq/altq/altq_rmclass.h b/sys/contrib/altq/altq/altq_rmclass.h
|
1681
|
index cf0ddf4..bd87591 100644
|
1682
|
--- a/sys/contrib/altq/altq/altq_rmclass.h
|
1683
|
+++ b/sys/contrib/altq/altq/altq_rmclass.h
|
1684
|
@@ -53,6 +53,7 @@ typedef struct rm_ifdat rm_ifdat_t;
|
1685
|
typedef struct rm_class rm_class_t;
|
1686
|
|
1687
|
struct red;
|
1688
|
+struct codel;
|
1689
|
|
1690
|
/*
|
1691
|
* Macros for dealing with time values. We assume all times are
|
1692
|
@@ -164,7 +165,10 @@ struct rm_class {
|
1693
|
void (*overlimit)(struct rm_class *, struct rm_class *);
|
1694
|
void (*drop)(struct rm_class *); /* Class drop action. */
|
1695
|
|
1696
|
- struct red *red_; /* RED state pointer */
|
1697
|
+ union {
|
1698
|
+ struct red *red_; /* RED state pointer */
|
1699
|
+ struct codel *codel;
|
1700
|
+ } cl_aqm;
|
1701
|
struct altq_pktattr *pktattr_; /* saved hdr used by RED/ECN */
|
1702
|
int flags_;
|
1703
|
|
1704
|
@@ -176,6 +180,8 @@ struct rm_class {
|
1705
|
|
1706
|
rm_class_stats_t stats_; /* Class Statistics */
|
1707
|
};
|
1708
|
+#define red_ cl_aqm.red_
|
1709
|
+#define codel_ cl_aqm.codel
|
1710
|
|
1711
|
/*
|
1712
|
* CBQ Interface state
|
1713
|
@@ -233,6 +239,7 @@ struct rm_ifdat {
|
1714
|
#define RMCF_RIO 0x0004
|
1715
|
#define RMCF_FLOWVALVE 0x0008 /* use flowvalve (aka penalty-box) */
|
1716
|
#define RMCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
|
1717
|
+#define RMCF_CODEL 0x0040
|
1718
|
|
1719
|
/* flags for rmc_init */
|
1720
|
#define RMCF_WRR 0x0100
|
1721
|
diff --git a/sys/contrib/altq/altq/altq_subr.c b/sys/contrib/altq/altq/altq_subr.c
|
1722
|
index d59751a..fff1b49 100644
|
1723
|
--- a/sys/contrib/altq/altq/altq_subr.c
|
1724
|
+++ b/sys/contrib/altq/altq/altq_subr.c
|
1725
|
@@ -542,6 +542,11 @@ altq_pfattach(struct pf_altq *a)
|
1726
|
error = fairq_pfattach(a);
|
1727
|
break;
|
1728
|
#endif
|
1729
|
+#ifdef ALTQ_CODEL
|
1730
|
+ case ALTQT_CODEL:
|
1731
|
+ error = codel_pfattach(a);
|
1732
|
+ break;
|
1733
|
+#endif
|
1734
|
default:
|
1735
|
error = ENXIO;
|
1736
|
}
|
1737
|
@@ -622,6 +627,11 @@ altq_add(struct pf_altq *a)
|
1738
|
error = fairq_add_altq(a);
|
1739
|
break;
|
1740
|
#endif
|
1741
|
+#ifdef ALTQ_CODEL
|
1742
|
+ case ALTQT_CODEL:
|
1743
|
+ error = codel_add_altq(a);
|
1744
|
+ break;
|
1745
|
+#endif
|
1746
|
default:
|
1747
|
error = ENXIO;
|
1748
|
}
|
1749
|
@@ -663,6 +673,11 @@ altq_remove(struct pf_altq *a)
|
1750
|
error = fairq_remove_altq(a);
|
1751
|
break;
|
1752
|
#endif
|
1753
|
+#ifdef ALTQ_CODEL
|
1754
|
+ case ALTQT_CODEL:
|
1755
|
+ error = codel_remove_altq(a);
|
1756
|
+ break;
|
1757
|
+#endif
|
1758
|
default:
|
1759
|
error = ENXIO;
|
1760
|
}
|
1761
|
@@ -777,6 +792,11 @@ altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
|
1762
|
error = fairq_getqstats(a, ubuf, nbytes);
|
1763
|
break;
|
1764
|
#endif
|
1765
|
+#ifdef ALTQ_CODEL
|
1766
|
+ case ALTQT_CODEL:
|
1767
|
+ error = codel_getqstats(a, ubuf, nbytes);
|
1768
|
+ break;
|
1769
|
+#endif
|
1770
|
default:
|
1771
|
error = ENXIO;
|
1772
|
}
|
1773
|
diff --git a/sys/contrib/altq/altq/altq_var.h b/sys/contrib/altq/altq/altq_var.h
|
1774
|
index eb603ea..6ea7b7c 100644
|
1775
|
--- a/sys/contrib/altq/altq/altq_var.h
|
1776
|
+++ b/sys/contrib/altq/altq/altq_var.h
|
1777
|
@@ -250,6 +250,11 @@ int priq_add_queue(struct pf_altq *);
|
1778
|
int priq_remove_queue(struct pf_altq *);
|
1779
|
int priq_getqstats(struct pf_altq *, void *, int *);
|
1780
|
|
1781
|
+int codel_pfattach(struct pf_altq *);
|
1782
|
+int codel_add_altq(struct pf_altq *);
|
1783
|
+int codel_remove_altq(struct pf_altq *);
|
1784
|
+int codel_getqstats(struct pf_altq *, void *, int *);
|
1785
|
+
|
1786
|
int hfsc_pfattach(struct pf_altq *);
|
1787
|
int hfsc_add_altq(struct pf_altq *);
|
1788
|
int hfsc_remove_altq(struct pf_altq *);
|
1789
|
diff --git a/sys/netpfil/pf/pf_altq.h b/sys/netpfil/pf/pf_altq.h
|
1790
|
index db681fb..e578ae1 100644
|
1791
|
--- a/sys/netpfil/pf/pf_altq.h
|
1792
|
+++ b/sys/netpfil/pf/pf_altq.h
|
1793
|
@@ -79,6 +79,12 @@ struct fairq_opts {
|
1794
|
u_int lssc_m2;
|
1795
|
};
|
1796
|
|
1797
|
+struct codel_opts {
|
1798
|
+ u_int target;
|
1799
|
+ u_int interval;
|
1800
|
+ int ecn;
|
1801
|
+};
|
1802
|
+
|
1803
|
struct pf_altq {
|
1804
|
char ifname[IFNAMSIZ];
|
1805
|
|
1806
|
@@ -106,6 +112,7 @@ struct pf_altq {
|
1807
|
struct priq_opts priq_opts;
|
1808
|
struct hfsc_opts hfsc_opts;
|
1809
|
struct fairq_opts fairq_opts;
|
1810
|
+ struct codel_opts codel_opts;
|
1811
|
} pq_u;
|
1812
|
|
1813
|
uint32_t qid; /* return value */
|
1814
|
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
|
1815
|
index bc2924a..8b52f19 100644
|
1816
|
--- a/sys/sys/mbuf.h
|
1817
|
+++ b/sys/sys/mbuf.h
|
1818
|
@@ -128,6 +128,7 @@ struct pkthdr {
|
1819
|
uint32_t flowid; /* packet's 4-tuple system */
|
1820
|
uint64_t csum_flags; /* checksum and offload features */
|
1821
|
uint16_t fibnum; /* this packet should use this fib */
|
1822
|
+ uint64_t enqueue_time;
|
1823
|
uint8_t cosqos; /* class/quality of service */
|
1824
|
uint8_t rsstype; /* hash type */
|
1825
|
uint8_t l2hlen; /* layer 2 header length */
|