Date: Sat, 22 Aug 2015 11:18:37 +0200 From: =?UTF-8?Q?Ermal_Lu=C3=A7i?= <ermal.luci@gmail.com> To: Luiz Otavio O Souza <loos@freebsd.org> Cc: src-committers <src-committers@freebsd.org>, svn-src-all <svn-src-all@freebsd.org>, svn-src-head <svn-src-head@freebsd.org> Subject: Re: svn commit: r287009 - in head: sbin/pfctl share/man/man4 sys/conf sys/net/altq sys/netpfil/pf Message-ID: <CAPBZQG3MJVgJ%2BaZvpxrFeDdvdc-Mf%2BxGmVJ_3pcTs2Oy23Ou9A@mail.gmail.com> In-Reply-To: <201508212202.t7LM2MhF015522@repo.freebsd.org> References: <201508212202.t7LM2MhF015522@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, Aug 22, 2015 at 12:02 AM, Luiz Otavio O Souza <loos@freebsd.org> wrote: > Author: loos > Date: Fri Aug 21 22:02:22 2015 > New Revision: 287009 > URL: https://svnweb.freebsd.org/changeset/base/287009 > > Log: > Add ALTQ(9) support for the CoDel algorithm. > > CoDel is a parameterless queue discipline that handles variable bandwidth > and RTT. > > It can be used as the single queue discipline on an interface or as a sub > discipline of existing queue disciplines such as PRIQ, CBQ, HFSC, FAIRQ. > > Differential Revision: https://reviews.freebsd.org/D3272 > Reviewd by: rpaulo, gnn (previous version) > I thought part of this commit message was taken from me as a reviewer, no? > Obtained from: pfSense > Sponsored by: Rubicon Communications (Netgate) > > Added: > head/sys/net/altq/altq_codel.c (contents, props changed) > head/sys/net/altq/altq_codel.h (contents, props changed) > Modified: > head/sbin/pfctl/parse.y > head/sbin/pfctl/pfctl_altq.c > head/sbin/pfctl/pfctl_parser.h > head/sbin/pfctl/pfctl_qstats.c > head/share/man/man4/altq.4 > head/sys/conf/files > head/sys/conf/options > head/sys/net/altq/altq.h > head/sys/net/altq/altq_cbq.c > head/sys/net/altq/altq_cbq.h > head/sys/net/altq/altq_classq.h > head/sys/net/altq/altq_fairq.c > head/sys/net/altq/altq_fairq.h > head/sys/net/altq/altq_hfsc.c > head/sys/net/altq/altq_hfsc.h > head/sys/net/altq/altq_priq.c > head/sys/net/altq/altq_priq.h > head/sys/net/altq/altq_rmclass.c > head/sys/net/altq/altq_rmclass.h > head/sys/net/altq/altq_subr.c > head/sys/net/altq/altq_var.h > head/sys/netpfil/pf/pf_altq.h > > Modified: head/sbin/pfctl/parse.y > > ============================================================================== > --- head/sbin/pfctl/parse.y Fri Aug 21 21:47:29 2015 (r287008) > +++ head/sbin/pfctl/parse.y Fri Aug 21 22:02:22 2015 (r287009) > @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); > #include <arpa/inet.h> > #include <net/altq/altq.h> > #include <net/altq/altq_cbq.h> > +#include <net/altq/altq_codel.h> > #include <net/altq/altq_priq.h> > #include <net/altq/altq_hfsc.h> > #include <net/altq/altq_fairq.h> > @@ -299,7 +300,7 @@ struct pool_opts { > > } pool_opts; > > - > +struct codel_opts codel_opts; > struct node_hfsc_opts hfsc_opts; > struct node_fairq_opts fairq_opts; > struct node_state_opt *keep_state_defaults = NULL; > @@ -425,6 +426,7 @@ typedef struct { > struct pool_opts pool_opts; > struct node_hfsc_opts hfsc_opts; > struct node_fairq_opts fairq_opts; > + struct codel_opts codel_opts; > } v; > int lineno; > } YYSTYPE; > @@ -449,8 +451,8 @@ int parseport(char *, struct range *r, i > %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID > %token ANTISPOOF FOR INCLUDE > %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY > -%token ALTQ CBQ PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME > UPPERLIMIT > -%token QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE > +%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME > +%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET > INTERVAL > %token LOAD RULESET_OPTIMIZATION > %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE > %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY > @@ -499,6 +501,7 @@ int parseport(char *, struct range *r, i > %type <v.number> priqflags_list priqflags_item > %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts > %type <v.fairq_opts> fairqopts_list fairqopts_item fairq_opts > +%type <v.codel_opts> codelopts_list codelopts_item codel_opts > %type <v.queue_bwspec> bandwidth > %type <v.filter_opts> filter_opts filter_opt filter_opts_l > %type <v.antispoof_opts> antispoof_opts antispoof_opt > antispoof_opts_l > @@ -1470,7 +1473,7 @@ altqif : ALTQ interface queue_opts QUEU > a.scheduler = $3.scheduler.qtype; > a.qlimit = $3.qlimit; > a.tbrsize = $3.tbrsize; > - if ($5 == NULL) { > + if ($5 == NULL && $3.scheduler.qtype != > ALTQT_CODEL) { > yyerror("no child queues specified"); > YYERROR; > } > @@ -1672,6 +1675,15 @@ scheduler : CBQ { > $$.qtype = ALTQT_FAIRQ; > $$.data.fairq_opts = $3; > } > + | CODEL { > + $$.qtype = ALTQT_CODEL; > + bzero(&$$.data.codel_opts, > + sizeof(struct codel_opts)); > + } > + | CODEL '(' codel_opts ')' { > + $$.qtype = ALTQT_CODEL; > + $$.data.codel_opts = $3; > + } > ; > > cbqflags_list : cbqflags_item { $$ |= $1; } > @@ -1689,6 +1701,8 @@ cbqflags_item : STRING { > $$ = CBQCLF_RED|CBQCLF_ECN; > else if (!strcmp($1, "rio")) > $$ = CBQCLF_RIO; > + else if (!strcmp($1, "codel")) > + $$ = CBQCLF_CODEL; > else { > yyerror("unknown cbq flag \"%s\"", $1); > free($1); > @@ -1711,6 +1725,8 @@ priqflags_item : STRING { > $$ = PRCF_RED|PRCF_ECN; > else if (!strcmp($1, "rio")) > $$ = PRCF_RIO; > + else if (!strcmp($1, "codel")) > + $$ = PRCF_CODEL; > else { > yyerror("unknown priq flag \"%s\"", $1); > free($1); > @@ -1811,6 +1827,8 @@ hfscopts_item : LINKSHARE bandwidth > { > hfsc_opts.flags |= HFCF_RED|HFCF_ECN; > else if (!strcmp($1, "rio")) > hfsc_opts.flags |= HFCF_RIO; > + else if (!strcmp($1, "codel")) > + hfsc_opts.flags |= HFCF_CODEL; > else { > yyerror("unknown hfsc flag \"%s\"", $1); > free($1); > @@ -1866,6 +1884,8 @@ fairqopts_item : LINKSHARE bandwidth > fairq_opts.flags |= FARF_RED|FARF_ECN; > else if (!strcmp($1, "rio")) > fairq_opts.flags |= FARF_RIO; > + else if (!strcmp($1, "codel")) > + fairq_opts.flags |= FARF_CODEL; > else { > yyerror("unknown fairq flag \"%s\"", $1); > free($1); > @@ -1875,6 +1895,45 @@ fairqopts_item : LINKSHARE bandwidth > } > ; > > +codel_opts : { > + bzero(&codel_opts, > + sizeof(struct codel_opts)); > + } > + codelopts_list { > + $$ = codel_opts; > + } > + ; > + > +codelopts_list : codelopts_item > + | codelopts_list comma codelopts_item > + ; > + > +codelopts_item : INTERVAL number { > + if (codel_opts.interval) { > + yyerror("interval already specified"); > + YYERROR; > + } > + codel_opts.interval = $2; > + } > + | TARGET number { > + if (codel_opts.target) { > + yyerror("target already specified"); > + YYERROR; > + } > + codel_opts.target = $2; > + } > + | STRING { > + if (!strcmp($1, "ecn")) > + codel_opts.ecn = 1; > + else { > + yyerror("unknown codel option \"%s\"", $1); > + free($1); > + YYERROR; > + } > + free($1); > + } > + ; > + > qassign : /* empty */ { $$ = NULL; } > | qassign_item { $$ = $1; } > | '{' optnl qassign_list '}' { $$ = $3; } > @@ -4800,7 +4859,8 @@ expand_altq(struct pf_altq *a, struct no > > if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { > FREE_LIST(struct node_if, interfaces); > - FREE_LIST(struct node_queue, nqueues); > + if (nqueues) > + FREE_LIST(struct node_queue, nqueues); > return (0); > } > > @@ -4891,7 +4951,8 @@ expand_altq(struct pf_altq *a, struct no > } > ); > FREE_LIST(struct node_if, interfaces); > - FREE_LIST(struct node_queue, nqueues); > + if (nqueues) > + FREE_LIST(struct node_queue, nqueues); > > return (errs); > } > @@ -5297,6 +5358,7 @@ lookup(char *s) > { "buckets", BUCKETS}, > { "cbq", CBQ}, > { "code", CODE}, > + { "codelq", CODEL}, > { "crop", FRAGCROP}, > { "debug", DEBUG}, > { "divert-reply", DIVERTREPLY}, > @@ -5326,6 +5388,7 @@ lookup(char *s) > { "include", INCLUDE}, > { "inet", INET}, > { "inet6", INET6}, > + { "interval", INTERVAL}, > { "keep", KEEP}, > { "label", LABEL}, > { "limit", LIMIT}, > @@ -5395,6 +5458,7 @@ lookup(char *s) > { "table", TABLE}, > { "tag", TAG}, > { "tagged", TAGGED}, > + { "target", TARGET}, > { "tbrsize", TBRSIZE}, > { "timeout", TIMEOUT}, > { "to", TO}, > > Modified: head/sbin/pfctl/pfctl_altq.c > > ============================================================================== > --- head/sbin/pfctl/pfctl_altq.c Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sbin/pfctl/pfctl_altq.c Fri Aug 21 22:02:22 2015 > (r287009) > @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); > > #include <net/altq/altq.h> > #include <net/altq/altq_cbq.h> > +#include <net/altq/altq_codel.h> > #include <net/altq/altq_priq.h> > #include <net/altq/altq_hfsc.h> > #include <net/altq/altq_fairq.h> > @@ -60,6 +61,9 @@ static int cbq_compute_idletime(struct p > static int check_commit_cbq(int, int, struct pf_altq *); > static int print_cbq_opts(const struct pf_altq *); > > +static int print_codel_opts(const struct pf_altq *, > + const struct node_queue_opt *); > + > static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *); > static int check_commit_priq(int, int, struct pf_altq *); > static int print_priq_opts(const struct pf_altq *); > @@ -185,6 +189,10 @@ print_altq(const struct pf_altq *a, unsi > if (!print_fairq_opts(a, qopts)) > printf("fairq "); > break; > + case ALTQT_CODEL: > + if (!print_codel_opts(a, qopts)) > + printf("codel "); > + break; > } > > if (bw != NULL && bw->bw_percent > 0) { > @@ -591,6 +599,8 @@ print_cbq_opts(const struct pf_altq *a) > printf(" ecn"); > if (opts->flags & CBQCLF_RIO) > printf(" rio"); > + if (opts->flags & CBQCLF_CODEL) > + printf(" codel"); > if (opts->flags & CBQCLF_CLEARDSCP) > printf(" cleardscp"); > if (opts->flags & CBQCLF_FLOWVALVE) > @@ -678,6 +688,8 @@ print_priq_opts(const struct pf_altq *a) > printf(" ecn"); > if (opts->flags & PRCF_RIO) > printf(" rio"); > + if (opts->flags & PRCF_CODEL) > + printf(" codel"); > if (opts->flags & PRCF_CLEARDSCP) > printf(" cleardscp"); > if (opts->flags & PRCF_DEFAULTCLASS) > @@ -1010,6 +1022,8 @@ print_hfsc_opts(const struct pf_altq *a, > printf(" ecn"); > if (opts->flags & HFCF_RIO) > printf(" rio"); > + if (opts->flags & HFCF_CODEL) > + printf(" codel"); > if (opts->flags & HFCF_CLEARDSCP) > printf(" cleardscp"); > if (opts->flags & HFCF_DEFAULTCLASS) > @@ -1032,6 +1046,28 @@ print_hfsc_opts(const struct pf_altq *a, > } > > static int > +print_codel_opts(const struct pf_altq *a, const struct node_queue_opt > *qopts) > +{ > + const struct codel_opts *opts; > + > + opts = &a->pq_u.codel_opts; > + if (opts->target || opts->interval || opts->ecn) { > + printf("codel("); > + if (opts->target) > + printf(" target %d", opts->target); > + if (opts->interval) > + printf(" interval %d", opts->interval); > + if (opts->ecn) > + printf("ecn"); > + printf(" ) "); > + > + return (1); > + } > + > + return (0); > +} > + > +static int > print_fairq_opts(const struct pf_altq *a, const struct node_queue_opt > *qopts) > { > const struct fairq_opts *opts; > @@ -1053,6 +1089,8 @@ print_fairq_opts(const struct pf_altq *a > printf(" ecn"); > if (opts->flags & FARF_RIO) > printf(" rio"); > + if (opts->flags & FARF_CODEL) > + printf(" codel"); > if (opts->flags & FARF_CLEARDSCP) > printf(" cleardscp"); > if (opts->flags & FARF_DEFAULTCLASS) > @@ -1404,6 +1442,11 @@ eval_queue_opts(struct pf_altq *pa, stru > opts->data.fairq_opts.linkshare.d; > } > break; > + case ALTQT_CODEL: > + pa->pq_u.codel_opts.target = opts->data.codel_opts.target; > + pa->pq_u.codel_opts.interval = > opts->data.codel_opts.interval; > + pa->pq_u.codel_opts.ecn = opts->data.codel_opts.ecn; > + break; > default: > warnx("eval_queue_opts: unknown scheduler type %u", > opts->qtype); > > Modified: head/sbin/pfctl/pfctl_parser.h > > ============================================================================== > --- head/sbin/pfctl/pfctl_parser.h Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sbin/pfctl/pfctl_parser.h Fri Aug 21 22:02:22 2015 > (r287009) > @@ -168,6 +168,7 @@ struct node_queue_opt { > int qtype; > union { > struct cbq_opts cbq_opts; > + struct codel_opts codel_opts; > struct priq_opts priq_opts; > struct node_hfsc_opts hfsc_opts; > struct node_fairq_opts fairq_opts; > > Modified: head/sbin/pfctl/pfctl_qstats.c > > ============================================================================== > --- head/sbin/pfctl/pfctl_qstats.c Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sbin/pfctl/pfctl_qstats.c Fri Aug 21 22:02:22 2015 > (r287009) > @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); > > #include <net/altq/altq.h> > #include <net/altq/altq_cbq.h> > +#include <net/altq/altq_codel.h> > #include <net/altq/altq_priq.h> > #include <net/altq/altq_hfsc.h> > #include <net/altq/altq_fairq.h> > @@ -48,6 +49,7 @@ union class_stats { > struct priq_classstats priq_stats; > struct hfsc_classstats hfsc_stats; > struct fairq_classstats fairq_stats; > + struct codel_ifstats codel_stats; > }; > > #define AVGN_MAX 8 > @@ -77,6 +79,7 @@ struct pf_altq_node *pfctl_find_altq_nod > void pfctl_print_altq_node(int, const struct > pf_altq_node *, > unsigned, int); > void print_cbqstats(struct queue_stats); > +void print_codelstats(struct queue_stats); > void print_priqstats(struct queue_stats); > void print_hfscstats(struct queue_stats); > void print_fairqstats(struct queue_stats); > @@ -165,7 +168,7 @@ pfctl_update_qstats(int dev, struct pf_a > return (-1); > } > #ifdef __FreeBSD__ > - if (pa.altq.qid > 0 && > + if ((pa.altq.qid > 0 || pa.altq.scheduler == ALTQT_CODEL) > && > !(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) { > #else > if (pa.altq.qid > 0) { > @@ -303,7 +306,7 @@ pfctl_print_altq_node(int dev, const str > void > pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a) > { > - if (a->altq.qid == 0) > + if (a->altq.qid == 0 && a->altq.scheduler != ALTQT_CODEL) > return; > > #ifdef __FreeBSD__ > @@ -323,6 +326,9 @@ pfctl_print_altq_nodestat(int dev, const > case ALTQT_FAIRQ: > print_fairqstats(a->qstats); > break; > + case ALTQT_CODEL: > + print_codelstats(a->qstats); > + break; > } > } > > @@ -348,6 +354,28 @@ print_cbqstats(struct queue_stats cur) > } > > void > +print_codelstats(struct queue_stats cur) > +{ > + printf(" [ pkts: %10llu bytes: %10llu " > + "dropped pkts: %6llu bytes: %6llu ]\n", > + (unsigned long long)cur.data.codel_stats.cl_xmitcnt.packets, > + (unsigned long long)cur.data.codel_stats.cl_xmitcnt.bytes, > + (unsigned long long)cur.data.codel_stats.cl_dropcnt.packets + > + cur.data.codel_stats.stats.drop_cnt.packets, > + (unsigned long long)cur.data.codel_stats.cl_dropcnt.bytes + > + cur.data.codel_stats.stats.drop_cnt.bytes); > + printf(" [ qlength: %3d/%3d ]\n", > + cur.data.codel_stats.qlength, cur.data.codel_stats.qlimit); > + > + if (cur.avgn < 2) > + return; > + > + printf(" [ measured: %7.1f packets/s, %s/s ]\n", > + cur.avg_packets / STAT_INTERVAL, > + rate2str((8 * cur.avg_bytes) / STAT_INTERVAL)); > +} > + > +void > print_priqstats(struct queue_stats cur) > { > printf(" [ pkts: %10llu bytes: %10llu " > @@ -428,7 +456,7 @@ update_avg(struct pf_altq_node *a) > u_int64_t b, p; > int n; > > - if (a->altq.qid == 0) > + if (a->altq.qid == 0 && a->altq.scheduler != ALTQT_CODEL) > return; > > qs = &a->qstats; > @@ -451,6 +479,10 @@ update_avg(struct pf_altq_node *a) > b = qs->data.fairq_stats.xmit_cnt.bytes; > p = qs->data.fairq_stats.xmit_cnt.packets; > break; > + case ALTQT_CODEL: > + b = qs->data.codel_stats.cl_xmitcnt.bytes; > + p = qs->data.codel_stats.cl_xmitcnt.packets; > + break; > default: > b = 0; > p = 0; > > Modified: head/share/man/man4/altq.4 > > ============================================================================== > --- head/share/man/man4/altq.4 Fri Aug 21 21:47:29 2015 (r287008) > +++ head/share/man/man4/altq.4 Fri Aug 21 22:02:22 2015 (r287009) > @@ -25,7 +25,7 @@ > .\" > .\" $FreeBSD$ > .\" > -.Dd June 24, 2015 > +.Dd July 24, 2015 > .Dt ALTQ 4 > .Os > .Sh NAME > @@ -35,6 +35,7 @@ > .Cd options ALTQ > .Pp > .Cd options ALTQ_CBQ > +.Cd options ALTQ_CODEL > .Cd options ALTQ_RED > .Cd options ALTQ_RIO > .Cd options ALTQ_HFSC > @@ -74,6 +75,10 @@ Enable > Build the > .Dq "Class Based Queuing" > discipline. > +.It Dv ALTQ_CODEL > +Build the > +.Dq "Controlled Delay" > +discipline. > .It Dv ALTQ_RED > Build the > .Dq "Random Early Detection" > > Modified: head/sys/conf/files > > ============================================================================== > --- head/sys/conf/files Fri Aug 21 21:47:29 2015 (r287008) > +++ head/sys/conf/files Fri Aug 21 22:02:22 2015 (r287009) > @@ -3429,6 +3429,7 @@ libkern/zlib.c optional crypto | > geom_ > ddb_ctf | gzio | geom_uncompress > net/altq/altq_cbq.c optional altq > net/altq/altq_cdnr.c optional altq > +net/altq/altq_codel.c optional altq > net/altq/altq_hfsc.c optional altq > net/altq/altq_fairq.c optional altq > net/altq/altq_priq.c optional altq > > Modified: head/sys/conf/options > > ============================================================================== > --- head/sys/conf/options Fri Aug 21 21:47:29 2015 (r287008) > +++ head/sys/conf/options Fri Aug 21 22:02:22 2015 (r287009) > @@ -388,6 +388,7 @@ ACCEPT_FILTER_HTTP > ALTQ opt_global.h > ALTQ_CBQ opt_altq.h > ALTQ_CDNR opt_altq.h > +ALTQ_CODEL opt_altq.h > ALTQ_DEBUG opt_altq.h > ALTQ_HFSC opt_altq.h > ALTQ_FAIRQ opt_altq.h > > Modified: head/sys/net/altq/altq.h > > ============================================================================== > --- head/sys/net/altq/altq.h Fri Aug 21 21:47:29 2015 (r287008) > +++ head/sys/net/altq/altq.h Fri Aug 21 22:02:22 2015 (r287009) > @@ -64,7 +64,8 @@ > #define ALTQT_PRIQ 11 /* priority queue */ > #define ALTQT_JOBS 12 /* JoBS */ > #define ALTQT_FAIRQ 13 /* fairq */ > -#define ALTQT_MAX 14 /* should be max > discipline type + 1 */ > +#define ALTQT_CODEL 14 /* CoDel */ > +#define ALTQT_MAX 15 /* should be max > discipline type + 1 */ > > #ifdef ALTQ3_COMPAT > struct altqreq { > > Modified: head/sys/net/altq/altq_cbq.c > > ============================================================================== > --- head/sys/net/altq/altq_cbq.c Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sys/net/altq/altq_cbq.c Fri Aug 21 22:02:22 2015 > (r287009) > @@ -237,6 +237,10 @@ get_class_stats(class_stats_t *statsp, s > if (q_is_rio(cl->q_)) > rio_getstats((rio_t *)cl->red_, &statsp->red[0]); > #endif > +#ifdef ALTQ_CODEL > + if (q_is_codel(cl->q_)) > + codel_getstats(cl->codel_, &statsp->codel); > +#endif > } > > int > > Modified: head/sys/net/altq/altq_cbq.h > > ============================================================================== > --- head/sys/net/altq/altq_cbq.h Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sys/net/altq/altq_cbq.h Fri Aug 21 22:02:22 2015 > (r287009) > @@ -36,6 +36,7 @@ > > #include <net/altq/altq.h> > #include <net/altq/altq_rmclass.h> > +#include <net/altq/altq_codel.h> > #include <net/altq/altq_red.h> > #include <net/altq/altq_rio.h> > > @@ -52,6 +53,7 @@ extern "C" { > #define CBQCLF_FLOWVALVE 0x0008 /* use flowvalve (aka > penalty-box) */ > #define CBQCLF_CLEARDSCP 0x0010 /* clear diffserv > codepoint */ > #define CBQCLF_BORROW 0x0020 /* borrow from parent */ > +#define CBQCLF_CODEL 0x0040 /* use CoDel */ > > /* class flags only for root class */ > #define CBQCLF_WRR 0x0100 /* weighted-round robin */ > @@ -91,9 +93,10 @@ typedef struct _cbq_class_stats_ { > int qcnt; /* # packets in queue */ > int avgidle; > > - /* red and rio related info */ > + /* codel, red and rio related info */ > int qtype; > struct redstats red[3]; > + struct codel_stats codel; > } class_stats_t; > > #ifdef ALTQ3_COMPAT > > Modified: head/sys/net/altq/altq_classq.h > > ============================================================================== > --- head/sys/net/altq/altq_classq.h Fri Aug 21 21:47:29 2015 > (r287008) > +++ head/sys/net/altq/altq_classq.h Fri Aug 21 22:02:22 2015 > (r287009) > @@ -50,6 +50,7 @@ extern "C" { > #define Q_RED 0x01 > #define Q_RIO 0x02 > #define Q_DROPTAIL 0x03 > +#define Q_CODEL 0x04 > > #ifdef _KERNEL > > @@ -60,6 +61,7 @@ struct _class_queue_ { > struct mbuf *tail_; /* Tail of packet queue */ > int qlen_; /* Queue length (in number of packets) */ > int qlim_; /* Queue limit (in number of packets*) */ > + int qsize_; /* Queue size (in number of bytes*) */ > int qtype_; /* Queue type */ > }; > > @@ -68,10 +70,12 @@ typedef struct _class_queue_ class_queue > #define qtype(q) (q)->qtype_ /* Get queue type > */ > #define qlimit(q) (q)->qlim_ /* Max packets to > be queued */ > #define qlen(q) (q)->qlen_ /* Current queue > length. */ > +#define qsize(q) (q)->qsize_ /* Current queue > size. */ > #define qtail(q) (q)->tail_ /* Tail of the > queue */ > #define qhead(q) ((q)->tail_ ? (q)->tail_->m_nextpkt : NULL) > > #define qempty(q) ((q)->qlen_ == 0) /* Is the queue > empty?? */ > +#define q_is_codel(q) ((q)->qtype_ == Q_CODEL) /* Is the queue a > codel queue */ > #define q_is_red(q) ((q)->qtype_ == Q_RED) /* Is the queue a > red queue */ > #define q_is_rio(q) ((q)->qtype_ == Q_RIO) /* Is the queue a > rio queue */ > #define q_is_red_or_rio(q) ((q)->qtype_ == Q_RED || > (q)->qtype_ == Q_RIO) > @@ -101,6 +105,7 @@ _addq(class_queue_t *q, struct mbuf *m) > m0->m_nextpkt = m; > qtail(q) = m; > qlen(q)++; > + qsize(q) += m_pktlen(m); > } > > static __inline struct mbuf * > @@ -115,6 +120,7 @@ _getq(class_queue_t *q) > else > qtail(q) = NULL; > qlen(q)--; > + qsize(q) -= m_pktlen(m0); > m0->m_nextpkt = NULL; > return (m0); > } > > Added: head/sys/net/altq/altq_codel.c > > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/sys/net/altq/altq_codel.c Fri Aug 21 22:02:22 2015 > (r287009) > @@ -0,0 +1,477 @@ > +/* > + * CoDel - The Controlled-Delay Active Queue Management algorithm > + * > + * Copyright (C) 2013 Ermal Luci <eri@FreeBSD.org> > Can you correct my name? > + * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com> > + * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net> > + * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net> > + * Copyright (C) 2012 Eric Dumazet <edumazet@google.com> > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions, and the following disclaimer, > + * without modification. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. The names of the authors may not be used to endorse or promote > products > + * derived from this software without specific prior written > permission. > + * > + * Alternatively, provided that this notice is retained in full, this > + * software may be distributed under the terms of the GNU General > + * Public License ("GPL") version 2, in which case the provisions of the > + * GPL apply INSTEAD OF those given above. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > + * DAMAGE. > + * > + * $FreeBSD$ > + */ > +#include "opt_altq.h" > +#include "opt_inet.h" > +#include "opt_inet6.h" > + > +#ifdef ALTQ_CODEL /* CoDel is enabled by ALTQ_CODEL option in opt_altq.h > */ > + > +#include <sys/param.h> > +#include <sys/malloc.h> > +#include <sys/mbuf.h> > +#include <sys/socket.h> > +#include <sys/systm.h> > + > +#include <net/if.h> > +#include <net/if_var.h> > +#include <netinet/in.h> > + > +#include <netpfil/pf/pf.h> > +#include <netpfil/pf/pf_altq.h> > +#include <net/altq/if_altq.h> > +#include <net/altq/altq.h> > +#include <net/altq/altq_codel.h> > + > +static int codel_should_drop(struct codel *, class_queue_t *, > + struct mbuf *, u_int64_t); > +static void codel_Newton_step(struct codel_vars *); > +static u_int64_t codel_control_law(u_int64_t t, u_int64_t, > u_int32_t); > + > +#define codel_time_after(a, b) ((int64_t)(a) - > (int64_t)(b) > 0) > +#define codel_time_after_eq(a, b) ((int64_t)(a) - > (int64_t)(b) >= 0) > +#define codel_time_before(a, b) ((int64_t)(a) - > (int64_t)(b) < 0) > +#define codel_time_before_eq(a, b) ((int64_t)(a) - > (int64_t)(b) <= 0) > + > +static int codel_request(struct ifaltq *, int, void *); > + > +static int codel_enqueue(struct ifaltq *, struct mbuf *, struct > altq_pktattr *); > +static struct mbuf *codel_dequeue(struct ifaltq *, int); > + > +int > +codel_pfattach(struct pf_altq *a) > +{ > + struct ifnet *ifp; > + > + if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL) > + return (EINVAL); > + > + return (altq_attach(&ifp->if_snd, ALTQT_CODEL, a->altq_disc, > + codel_enqueue, codel_dequeue, codel_request, NULL, NULL)); > +} > + > +int > +codel_add_altq(struct pf_altq *a) > +{ > + struct codel_if *cif; > + struct ifnet *ifp; > + struct codel_opts *opts; > + > + if ((ifp = ifunit(a->ifname)) == NULL) > + return (EINVAL); > + if (!ALTQ_IS_READY(&ifp->if_snd)) > + return (ENODEV); > + > + opts = &a->pq_u.codel_opts; > + > + cif = malloc(sizeof(struct codel_if), M_DEVBUF, M_NOWAIT | M_ZERO); > + if (cif == NULL) > + return (ENOMEM); > + cif->cif_bandwidth = a->ifbandwidth; > + cif->cif_ifq = &ifp->if_snd; > + > + cif->cl_q = malloc(sizeof(class_queue_t), M_DEVBUF, M_NOWAIT | > M_ZERO); > + if (cif->cl_q == NULL) { > + free(cif, M_DEVBUF); > + return (ENOMEM); > + } > + > + if (a->qlimit == 0) > + a->qlimit = 50; /* use default. */ > + qlimit(cif->cl_q) = a->qlimit; > + qtype(cif->cl_q) = Q_CODEL; > + qlen(cif->cl_q) = 0; > + qsize(cif->cl_q) = 0; > + > + if (opts->target == 0) > + opts->target = 5; > + if (opts->interval == 0) > + opts->interval = 100; > + cif->codel.params.target = machclk_freq * opts->target / 1000; > + cif->codel.params.interval = machclk_freq * opts->interval / 1000; > + cif->codel.params.ecn = opts->ecn; > + cif->codel.stats.maxpacket = 256; > + > + cif->cl_stats.qlength = qlen(cif->cl_q); > + cif->cl_stats.qlimit = qlimit(cif->cl_q); > + > + /* keep the state in pf_altq */ > + a->altq_disc = cif; > + > + return (0); > +} > + > +int > +codel_remove_altq(struct pf_altq *a) > +{ > + struct codel_if *cif; > + > + if ((cif = a->altq_disc) == NULL) > + return (EINVAL); > + a->altq_disc = NULL; > + > + if (cif->cl_q) > + free(cif->cl_q, M_DEVBUF); > + free(cif, M_DEVBUF); > + > + return (0); > +} > + > +int > +codel_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) > +{ > + struct codel_if *cif; > + struct codel_ifstats stats; > + int error = 0; > + > + if ((cif = altq_lookup(a->ifname, ALTQT_CODEL)) == NULL) > + return (EBADF); > + > + if (*nbytes < sizeof(stats)) > + return (EINVAL); > + > + stats = cif->cl_stats; > + stats.stats = cif->codel.stats; > + > + if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0) > + return (error); > + *nbytes = sizeof(stats); > + > + return (0); > +} > + > +static int > +codel_request(struct ifaltq *ifq, int req, void *arg) > +{ > + struct codel_if *cif = (struct codel_if *)ifq->altq_disc; > + struct mbuf *m; > + > + IFQ_LOCK_ASSERT(ifq); > + > + switch (req) { > + case ALTRQ_PURGE: > + if (!ALTQ_IS_ENABLED(cif->cif_ifq)) > + break; > + > + if (qempty(cif->cl_q)) > + break; > + > + while ((m = _getq(cif->cl_q)) != NULL) { > + PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, > m_pktlen(m)); > + m_freem(m); > + IFQ_DEC_LEN(cif->cif_ifq); > + } > + cif->cif_ifq->ifq_len = 0; > + break; > + } > + > + return (0); > +} > + > +static int > +codel_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr > *pktattr) > +{ > + > + struct codel_if *cif = (struct codel_if *) ifq->altq_disc; > + > + IFQ_LOCK_ASSERT(ifq); > + > + /* grab class set by classifier */ > + if ((m->m_flags & M_PKTHDR) == 0) { > + /* should not happen */ > + printf("altq: packet for %s does not have pkthdr\n", > + ifq->altq_ifp->if_xname); > + m_freem(m); > + PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, m_pktlen(m)); > + return (ENOBUFS); > + } > + > + if (codel_addq(&cif->codel, cif->cl_q, m)) { > + PKTCNTR_ADD(&cif->cl_stats.cl_dropcnt, m_pktlen(m)); > + return (ENOBUFS); > + } > + IFQ_INC_LEN(ifq); > + > + return (0); > +} > + > +static struct mbuf * > +codel_dequeue(struct ifaltq *ifq, int op) > +{ > + struct codel_if *cif = (struct codel_if *)ifq->altq_disc; > + struct mbuf *m; > + > + IFQ_LOCK_ASSERT(ifq); > + > + if (IFQ_IS_EMPTY(ifq)) > + return (NULL); > + > + if (op == ALTDQ_POLL) > + return (qhead(cif->cl_q)); > + > + > + m = codel_getq(&cif->codel, cif->cl_q); > + if (m != NULL) { > + IFQ_DEC_LEN(ifq); > + PKTCNTR_ADD(&cif->cl_stats.cl_xmitcnt, m_pktlen(m)); > + return (m); > + } > + > + return (NULL); > +} > + > +struct codel * > +codel_alloc(int target, int interval, int ecn) > +{ > + struct codel *c; > + > + c = malloc(sizeof(*c), M_DEVBUF, M_NOWAIT | M_ZERO); > + if (c != NULL) { > + c->params.target = machclk_freq * target / 1000; > + c->params.interval = machclk_freq * interval / 1000; > + c->params.ecn = ecn; > + c->stats.maxpacket = 256; > + } > + > + return (c); > +} > + > +void > +codel_destroy(struct codel *c) > +{ > + > + free(c, M_DEVBUF); > +} > + > +#define MTAG_CODEL 1438031249 > +int > +codel_addq(struct codel *c, class_queue_t *q, struct mbuf *m) > +{ > + struct m_tag *mtag; > + uint64_t *enqueue_time; > + > + if (qlen(q) < qlimit(q)) { > + mtag = m_tag_locate(m, MTAG_CODEL, 0, NULL); > + if (mtag == NULL) > + mtag = m_tag_alloc(MTAG_CODEL, 0, sizeof(uint64_t), > + M_NOWAIT); > + if (mtag == NULL) { > + m_freem(m); > + return (-1); > + } > + enqueue_time = (uint64_t *)(mtag + 1); > + *enqueue_time = read_machclk(); > + m_tag_prepend(m, mtag); > + _addq(q, m); > + return (0); > + } > + c->drop_overlimit++; > + m_freem(m); > + > + return (-1); > +} > + > +static int > +codel_should_drop(struct codel *c, class_queue_t *q, struct mbuf *m, > + u_int64_t now) > +{ > + struct m_tag *mtag; > + uint64_t *enqueue_time; > + > + if (m == NULL) { > + c->vars.first_above_time = 0; > + return (0); > + } > + > + mtag = m_tag_locate(m, MTAG_CODEL, 0, NULL); > + if (mtag == NULL) { > + /* Only one warning per second. */ > + if (ppsratecheck(&c->last_log, &c->last_pps, 1)) > + printf("%s: could not found the packet mtag!\n", > + __func__); > + c->vars.first_above_time = 0; > + return (0); > + } > + enqueue_time = (uint64_t *)(mtag + 1); > + c->vars.ldelay = now - *enqueue_time; > + c->stats.maxpacket = MAX(c->stats.maxpacket, m_pktlen(m)); > + > + if (codel_time_before(c->vars.ldelay, c->params.target) || > + qsize(q) <= c->stats.maxpacket) { > + /* went below - stay below for at least interval */ > + c->vars.first_above_time = 0; > + return (0); > + } > + if (c->vars.first_above_time == 0) { > + /* just went above from below. If we stay above > + * for at least interval we'll say it's ok to drop > + */ > + c->vars.first_above_time = now + c->params.interval; > + return (0); > + } > + if (codel_time_after(now, c->vars.first_above_time)) > + return (1); > + > + return (0); > +} > + > +/* > + * Run a Newton method step: > + * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) > + * > + * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka > Q0.32 > + */ > +static void > +codel_Newton_step(struct codel_vars *vars) > +{ > + uint32_t invsqrt, invsqrt2; > + uint64_t val; > + > +/* sizeof_in_bits(rec_inv_sqrt) */ > +#define REC_INV_SQRT_BITS (8 * sizeof(u_int16_t)) > +/* needed shift to get a Q0.32 number from rec_inv_sqrt */ > +#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS) > + > + invsqrt = ((u_int32_t)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; > + invsqrt2 = ((u_int64_t)invsqrt * invsqrt) >> 32; > + val = (3LL << 32) - ((u_int64_t)vars->count * invsqrt2); > + val >>= 2; /* avoid overflow in following multiply */ > + val = (val * invsqrt) >> (32 - 2 + 1); > + > + vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; > +} > + > +static u_int64_t > +codel_control_law(u_int64_t t, u_int64_t interval, u_int32_t rec_inv_sqrt) > +{ > + > + return (t + (u_int32_t)(((u_int64_t)interval * > + (rec_inv_sqrt << REC_INV_SQRT_SHIFT)) >> 32)); > +} > + > +struct mbuf * > +codel_getq(struct codel *c, class_queue_t *q) > +{ > + struct mbuf *m; > + u_int64_t now; > + int drop; > + > + if ((m = _getq(q)) == NULL) { > + c->vars.dropping = 0; > + return (m); > + } > + > + now = read_machclk(); > + drop = codel_should_drop(c, q, m, now); > + if (c->vars.dropping) { > + if (!drop) { > + /* sojourn time below target - leave dropping > state */ > + c->vars.dropping = 0; > + } else if (codel_time_after_eq(now, c->vars.drop_next)) { > + /* It's time for the next drop. Drop the current > + * packet and dequeue the next. The dequeue might > + * take us out of dropping state. > + * If not, schedule the next drop. > + * A large backlog might result in drop rates so > high > + * that the next drop should happen now, > + * hence the while loop. > + */ > + while (c->vars.dropping && > + codel_time_after_eq(now, c->vars.drop_next)) { > + c->vars.count++; /* don't care of possible > wrap > + * since there is no more > + * divide */ > + codel_Newton_step(&c->vars); > + /* TODO ECN */ > + PKTCNTR_ADD(&c->stats.drop_cnt, > m_pktlen(m)); > + m_freem(m); > + m = _getq(q); > + if (!codel_should_drop(c, q, m, now)) > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** > > -- Ermal
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPBZQG3MJVgJ%2BaZvpxrFeDdvdc-Mf%2BxGmVJ_3pcTs2Oy23Ou9A>