Date: Mon, 18 Apr 2016 20:17:20 +0200 From: =?UTF-8?Q?Ermal_Lu=C3=A7i?= <eri@freebsd.org> 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-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: Re: svn commit: r298091 - in stable/10: sbin/pfctl share/man/man4 sys/conf sys/contrib/altq/altq sys/netpfil/pf Message-ID: <CAPBZQG2gZ4_aFkzNOPcisiJE1k88ZV%2Bn=pywe_2j=2vehxczEg@mail.gmail.com> In-Reply-To: <201604160211.u3G2B4Mv078856@repo.freebsd.org> References: <201604160211.u3G2B4Mv078856@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Careful with things you should credit to me :) Your boss likes to play games do not get in the middle as well. On Sat, Apr 16, 2016 at 4:11 AM, Luiz Otavio O Souza <loos@freebsd.org> wrote: > Author: loos > Date: Sat Apr 16 02:11:04 2016 > New Revision: 298091 > URL: https://svnweb.freebsd.org/changeset/base/298091 > > Log: > MFC r284777, r284814, r284863 and r298088: > > ALTQ FAIRQ discipline import from DragonFLY. > > Differential Revision: https://reviews.freebsd.org/D2847 > Obtained from: pfSense > Sponsored by: Rubicon Communications (Netgate) > > Added: > stable/10/sys/contrib/altq/altq/altq_fairq.c (contents, props changed) > stable/10/sys/contrib/altq/altq/altq_fairq.h (contents, props changed) > Modified: > stable/10/sbin/pfctl/parse.y > stable/10/sbin/pfctl/pfctl_altq.c > stable/10/sbin/pfctl/pfctl_parser.h > stable/10/sbin/pfctl/pfctl_qstats.c > stable/10/share/man/man4/altq.4 > stable/10/sys/conf/NOTES > stable/10/sys/conf/files > stable/10/sys/conf/options > stable/10/sys/contrib/altq/altq/altq.h > stable/10/sys/contrib/altq/altq/altq_subr.c > stable/10/sys/contrib/altq/altq/altq_var.h > stable/10/sys/netpfil/pf/pf.c > stable/10/sys/netpfil/pf/pf_altq.h > stable/10/sys/netpfil/pf/pf_mtag.h > Directory Properties: > stable/10/ (props changed) > > Modified: stable/10/sbin/pfctl/parse.y > > ============================================================================== > --- stable/10/sbin/pfctl/parse.y Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/sbin/pfctl/parse.y Sat Apr 16 02:11:04 2016 > (r298091) > @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); > #include <altq/altq_cbq.h> > #include <altq/altq_priq.h> > #include <altq/altq_hfsc.h> > +#include <net/altq/altq_fairq.h> > > #include <stdio.h> > #include <unistd.h> > @@ -300,6 +301,7 @@ struct pool_opts { > > > struct node_hfsc_opts hfsc_opts; > +struct node_fairq_opts fairq_opts; > struct node_state_opt *keep_state_defaults = NULL; > > int disallow_table(struct node_host *, const char *); > @@ -422,6 +424,7 @@ typedef struct { > struct table_opts table_opts; > struct pool_opts pool_opts; > struct node_hfsc_opts hfsc_opts; > + struct node_fairq_opts fairq_opts; > } v; > int lineno; > } YYSTYPE; > @@ -446,8 +449,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 BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT > -%token QUEUE PRIORITY QLIMIT RTABLE > +%token ALTQ CBQ PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME > UPPERLIMIT > +%token QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE > %token LOAD RULESET_OPTIMIZATION > %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE > %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY > @@ -495,6 +498,7 @@ int parseport(char *, struct range *r, i > %type <v.number> cbqflags_list cbqflags_item > %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.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 > @@ -1659,6 +1663,15 @@ scheduler : CBQ { > $$.qtype = ALTQT_HFSC; > $$.data.hfsc_opts = $3; > } > + | FAIRQ { > + $$.qtype = ALTQT_FAIRQ; > + bzero(&$$.data.fairq_opts, > + sizeof(struct node_fairq_opts)); > + } > + | FAIRQ '(' fairq_opts ')' { > + $$.qtype = ALTQT_FAIRQ; > + $$.data.fairq_opts = $3; > + } > ; > > cbqflags_list : cbqflags_item { $$ |= $1; } > @@ -1807,6 +1820,61 @@ hfscopts_item : LINKSHARE bandwidth > { > } > ; > > +fairq_opts : { > + bzero(&fairq_opts, > + sizeof(struct node_fairq_opts)); > + } > + fairqopts_list { > + $$ = fairq_opts; > + } > + ; > + > +fairqopts_list : fairqopts_item > + | fairqopts_list comma fairqopts_item > + ; > + > +fairqopts_item : LINKSHARE bandwidth { > + if (fairq_opts.linkshare.used) { > + yyerror("linkshare already specified"); > + YYERROR; > + } > + fairq_opts.linkshare.m2 = $2; > + fairq_opts.linkshare.used = 1; > + } > + | LINKSHARE '(' bandwidth number bandwidth ')' { > + if (fairq_opts.linkshare.used) { > + yyerror("linkshare already specified"); > + YYERROR; > + } > + fairq_opts.linkshare.m1 = $3; > + fairq_opts.linkshare.d = $4; > + fairq_opts.linkshare.m2 = $5; > + fairq_opts.linkshare.used = 1; > + } > + | HOGS bandwidth { > + fairq_opts.hogs_bw = $2; > + } > + | BUCKETS number { > + fairq_opts.nbuckets = $2; > + } > + | STRING { > + if (!strcmp($1, "default")) > + fairq_opts.flags |= FARF_DEFAULTCLASS; > + else if (!strcmp($1, "red")) > + fairq_opts.flags |= FARF_RED; > + else if (!strcmp($1, "ecn")) > + fairq_opts.flags |= FARF_RED|FARF_ECN; > + else if (!strcmp($1, "rio")) > + fairq_opts.flags |= FARF_RIO; > + else { > + yyerror("unknown fairq flag \"%s\"", $1); > + free($1); > + YYERROR; > + } > + free($1); > + } > + ; > + > qassign : /* empty */ { $$ = NULL; } > | qassign_item { $$ = $1; } > | '{' optnl qassign_list '}' { $$ = $3; } > @@ -5226,6 +5294,7 @@ lookup(char *s) > { "bitmask", BITMASK}, > { "block", BLOCK}, > { "block-policy", BLOCKPOLICY}, > + { "buckets", BUCKETS}, > { "cbq", CBQ}, > { "code", CODE}, > { "crop", FRAGCROP}, > @@ -5235,6 +5304,7 @@ lookup(char *s) > { "drop", DROP}, > { "drop-ovl", FRAGDROP}, > { "dup-to", DUPTO}, > + { "fairq", FAIRQ}, > { "fastroute", FASTROUTE}, > { "file", FILENAME}, > { "fingerprints", FINGERPRINTS}, > @@ -5247,6 +5317,7 @@ lookup(char *s) > { "global", GLOBAL}, > { "group", GROUP}, > { "hfsc", HFSC}, > + { "hogs", HOGS}, > { "hostid", HOSTID}, > { "icmp-type", ICMPTYPE}, > { "icmp6-type", ICMP6TYPE}, > > Modified: stable/10/sbin/pfctl/pfctl_altq.c > > ============================================================================== > --- stable/10/sbin/pfctl/pfctl_altq.c Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/sbin/pfctl/pfctl_altq.c Sat Apr 16 02:11:04 2016 > (r298091) > @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); > #include <altq/altq_cbq.h> > #include <altq/altq_priq.h> > #include <altq/altq_hfsc.h> > +#include <net/altq/altq_fairq.h> > > #include "pfctl_parser.h" > #include "pfctl.h" > @@ -68,6 +69,11 @@ static int check_commit_hfsc(int, int, s > static int print_hfsc_opts(const struct pf_altq *, > const struct node_queue_opt *); > > +static int eval_pfqueue_fairq(struct pfctl *, struct pf_altq *); > +static int print_fairq_opts(const struct pf_altq *, > + const struct node_queue_opt *); > +static int check_commit_fairq(int, int, struct pf_altq *); > + > static void gsc_add_sc(struct gen_sc *, struct service_curve > *); > static int is_gsc_under_sc(struct gen_sc *, > struct service_curve *); > @@ -88,6 +94,8 @@ int eval_queue_opts(struct pf_altq *, > u_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t); > void print_hfsc_sc(const char *, u_int, u_int, u_int, > const struct node_hfsc_sc *); > +void print_fairq_sc(const char *, u_int, u_int, u_int, > + const struct node_fairq_sc *); > > void > pfaltq_store(struct pf_altq *a) > @@ -173,6 +181,10 @@ print_altq(const struct pf_altq *a, unsi > if (!print_hfsc_opts(a, qopts)) > printf("hfsc "); > break; > + case ALTQT_FAIRQ: > + if (!print_fairq_opts(a, qopts)) > + printf("fairq "); > + break; > } > > if (bw != NULL && bw->bw_percent > 0) { > @@ -203,7 +215,8 @@ print_queue(const struct pf_altq *a, uns > printf("%s ", a->qname); > if (print_interface) > printf("on %s ", a->ifname); > - if (a->scheduler == ALTQT_CBQ || a->scheduler == ALTQT_HFSC) { > + if (a->scheduler == ALTQT_CBQ || a->scheduler == ALTQT_HFSC || > + a->scheduler == ALTQT_FAIRQ) { > if (bw != NULL && bw->bw_percent > 0) { > if (bw->bw_percent < 100) > printf("bandwidth %u%% ", bw->bw_percent); > @@ -224,6 +237,9 @@ print_queue(const struct pf_altq *a, uns > case ALTQT_HFSC: > print_hfsc_opts(a, qopts); > break; > + case ALTQT_FAIRQ: > + print_fairq_opts(a, qopts); > + break; > } > } > > @@ -294,6 +310,9 @@ check_commit_altq(int dev, int opts) > case ALTQT_HFSC: > error = check_commit_hfsc(dev, opts, altq); > break; > + case ALTQT_FAIRQ: > + error = check_commit_fairq(dev, opts, > altq); > + break; > default: > break; > } > @@ -342,7 +361,8 @@ eval_pfqueue(struct pfctl *pf, struct pf > if (pa->qlimit == 0) > pa->qlimit = DEFAULT_QLIMIT; > > - if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) { > + if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC || > + pa->scheduler == ALTQT_FAIRQ) { > pa->bandwidth = eval_bwspec(bw, > parent == NULL ? 0 : parent->bandwidth); > > @@ -388,6 +408,9 @@ eval_pfqueue(struct pfctl *pf, struct pf > case ALTQT_HFSC: > error = eval_pfqueue_hfsc(pf, pa); > break; > + case ALTQT_FAIRQ: > + error = eval_pfqueue_fairq(pf, pa); > + break; > default: > break; > } > @@ -807,6 +830,85 @@ err_ret: > return (-1); > } > > +/* > + * FAIRQ support functions > + */ > +static int > +eval_pfqueue_fairq(struct pfctl *pf __unused, struct pf_altq *pa) > +{ > + struct pf_altq *altq, *parent; > + struct fairq_opts *opts; > + struct service_curve sc; > + > + opts = &pa->pq_u.fairq_opts; > + > + if (pa->parent[0] == 0) { > + /* root queue */ > + opts->lssc_m1 = pa->ifbandwidth; > + opts->lssc_m2 = pa->ifbandwidth; > + opts->lssc_d = 0; > + return (0); > + } > + > + LIST_INIT(&lssc); > + > + /* if link_share is not specified, use bandwidth */ > + if (opts->lssc_m2 == 0) > + opts->lssc_m2 = pa->bandwidth; > + > + /* > + * admission control: > + * for the real-time service curve, the sum of the service curves > + * should not exceed 80% of the interface bandwidth. 20% is > reserved > + * not to over-commit the actual interface bandwidth. > + * for the link-sharing service curve, the sum of the child service > + * curve should not exceed the parent service curve. > + * for the upper-limit service curve, the assigned bandwidth should > + * be smaller than the interface bandwidth, and the upper-limit > should > + * be larger than the real-time service curve when both are > defined. > + */ > + parent = qname_to_pfaltq(pa->parent, pa->ifname); > + if (parent == NULL) > + errx(1, "parent %s not found for %s", pa->parent, > pa->qname); > + > + TAILQ_FOREACH(altq, &altqs, entries) { > + if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) > + continue; > + if (altq->qname[0] == 0) /* this is for interface */ > + continue; > + > + if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0) > + continue; > + > + /* if the class has a link-sharing service curve, add it. > */ > + if (opts->lssc_m2 != 0 && altq->pq_u.fairq_opts.lssc_m2 != > 0) { > + sc.m1 = altq->pq_u.fairq_opts.lssc_m1; > + sc.d = altq->pq_u.fairq_opts.lssc_d; > + sc.m2 = altq->pq_u.fairq_opts.lssc_m2; > + gsc_add_sc(&lssc, &sc); > + } > + } > + > + /* check the link-sharing service curve. */ > + if (opts->lssc_m2 != 0) { > + sc.m1 = parent->pq_u.fairq_opts.lssc_m1; > + sc.d = parent->pq_u.fairq_opts.lssc_d; > + sc.m2 = parent->pq_u.fairq_opts.lssc_m2; > + if (!is_gsc_under_sc(&lssc, &sc)) { > + warnx("link-sharing sc exceeds parent's sc"); > + goto err_ret; > + } > + } > + > + gsc_destroy(&lssc); > + > + return (0); > + > +err_ret: > + gsc_destroy(&lssc); > + return (-1); > +} > + > static int > check_commit_hfsc(int dev, int opts, struct pf_altq *pa) > { > @@ -847,6 +949,43 @@ check_commit_hfsc(int dev, int opts, str > } > > static int > +check_commit_fairq(int dev __unused, int opts __unused, struct pf_altq > *pa) > +{ > + struct pf_altq *altq, *def = NULL; > + int default_class; > + int error = 0; > + > + /* check if fairq has one default queue for this interface */ > + default_class = 0; > + TAILQ_FOREACH(altq, &altqs, entries) { > + if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) > + continue; > + if (altq->qname[0] == 0) /* this is for interface */ > + continue; > + if (altq->pq_u.fairq_opts.flags & FARF_DEFAULTCLASS) { > + default_class++; > + def = altq; > + } > + } > + if (default_class != 1) { > + warnx("should have one default queue on %s", pa->ifname); > + return (1); > + } > + /* make sure the default queue is a leaf */ > + TAILQ_FOREACH(altq, &altqs, entries) { > + if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0) > + continue; > + if (altq->qname[0] == 0) /* this is for interface */ > + continue; > + if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) > { > + warnx("default queue is not a leaf"); > + error++; > + } > + } > + return (error); > +} > + > +static int > print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt > *qopts) > { > const struct hfsc_opts *opts; > @@ -892,6 +1031,43 @@ print_hfsc_opts(const struct pf_altq *a, > return (0); > } > > +static int > +print_fairq_opts(const struct pf_altq *a, const struct node_queue_opt > *qopts) > +{ > + const struct fairq_opts *opts; > + const struct node_fairq_sc *loc_lssc; > + > + opts = &a->pq_u.fairq_opts; > + if (qopts == NULL) > + loc_lssc = NULL; > + else > + loc_lssc = &qopts->data.fairq_opts.linkshare; > + > + if (opts->flags || > + (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || > + opts->lssc_d != 0))) { > + printf("fairq("); > + if (opts->flags & FARF_RED) > + printf(" red"); > + if (opts->flags & FARF_ECN) > + printf(" ecn"); > + if (opts->flags & FARF_RIO) > + printf(" rio"); > + if (opts->flags & FARF_CLEARDSCP) > + printf(" cleardscp"); > + if (opts->flags & FARF_DEFAULTCLASS) > + printf(" default"); > + if (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth || > + opts->lssc_d != 0)) > + print_fairq_sc("linkshare", opts->lssc_m1, > opts->lssc_d, > + opts->lssc_m2, loc_lssc); > + printf(" ) "); > + > + return (1); > + } else > + return (0); > +} > + > /* > * admission control using generalized service curve > */ > @@ -1211,6 +1387,23 @@ eval_queue_opts(struct pf_altq *pa, stru > opts->data.hfsc_opts.upperlimit.d; > } > break; > + case ALTQT_FAIRQ: > + pa->pq_u.fairq_opts.flags = opts->data.fairq_opts.flags; > + pa->pq_u.fairq_opts.nbuckets = > opts->data.fairq_opts.nbuckets; > + pa->pq_u.fairq_opts.hogs_m1 = > + eval_bwspec(&opts->data.fairq_opts.hogs_bw, > ref_bw); > + > + if (opts->data.fairq_opts.linkshare.used) { > + pa->pq_u.fairq_opts.lssc_m1 = > + > eval_bwspec(&opts->data.fairq_opts.linkshare.m1, > + ref_bw); > + pa->pq_u.fairq_opts.lssc_m2 = > + > eval_bwspec(&opts->data.fairq_opts.linkshare.m2, > + ref_bw); > + pa->pq_u.fairq_opts.lssc_d = > + opts->data.fairq_opts.linkshare.d; > + } > + break; > default: > warnx("eval_queue_opts: unknown scheduler type %u", > opts->qtype); > @@ -1256,3 +1449,27 @@ print_hfsc_sc(const char *scname, u_int > if (d != 0) > printf(")"); > } > + > +void > +print_fairq_sc(const char *scname, u_int m1, u_int d, u_int m2, > + const struct node_fairq_sc *sc) > +{ > + printf(" %s", scname); > + > + if (d != 0) { > + printf("("); > + if (sc != NULL && sc->m1.bw_percent > 0) > + printf("%u%%", sc->m1.bw_percent); > + else > + printf("%s", rate2str((double)m1)); > + printf(" %u", d); > + } > + > + if (sc != NULL && sc->m2.bw_percent > 0) > + printf(" %u%%", sc->m2.bw_percent); > + else > + printf(" %s", rate2str((double)m2)); > + > + if (d != 0) > + printf(")"); > +} > > Modified: stable/10/sbin/pfctl/pfctl_parser.h > > ============================================================================== > --- stable/10/sbin/pfctl/pfctl_parser.h Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/sbin/pfctl/pfctl_parser.h Sat Apr 16 02:11:04 2016 > (r298091) > @@ -150,12 +150,27 @@ struct node_hfsc_opts { > int flags; > }; > > +struct node_fairq_sc { > + struct node_queue_bw m1; /* slope of 1st segment; bps */ > + u_int d; /* x-projection of m1; msec */ > + struct node_queue_bw m2; /* slope of 2nd segment; bps */ > + u_int8_t used; > +}; > + > +struct node_fairq_opts { > + struct node_fairq_sc linkshare; > + struct node_queue_bw hogs_bw; > + u_int nbuckets; > + int flags; > +}; > + > struct node_queue_opt { > int qtype; > union { > struct cbq_opts cbq_opts; > struct priq_opts priq_opts; > struct node_hfsc_opts hfsc_opts; > + struct node_fairq_opts fairq_opts; > } data; > }; > > > Modified: stable/10/sbin/pfctl/pfctl_qstats.c > > ============================================================================== > --- stable/10/sbin/pfctl/pfctl_qstats.c Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/sbin/pfctl/pfctl_qstats.c Sat Apr 16 02:11:04 2016 > (r298091) > @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); > #include <altq/altq_cbq.h> > #include <altq/altq_priq.h> > #include <altq/altq_hfsc.h> > +#include <net/altq/altq_fairq.h> > > #include "pfctl.h" > #include "pfctl_parser.h" > @@ -46,6 +47,7 @@ union class_stats { > class_stats_t cbq_stats; > struct priq_classstats priq_stats; > struct hfsc_classstats hfsc_stats; > + struct fairq_classstats fairq_stats; > }; > > #define AVGN_MAX 8 > @@ -77,6 +79,7 @@ void pfctl_print_altq_node(int, const > void print_cbqstats(struct queue_stats); > void print_priqstats(struct queue_stats); > void print_hfscstats(struct queue_stats); > +void print_fairqstats(struct queue_stats); > void pfctl_free_altq_node(struct pf_altq_node *); > void pfctl_print_altq_nodestat(int, > const struct pf_altq_node *); > @@ -317,6 +320,9 @@ pfctl_print_altq_nodestat(int dev, const > case ALTQT_HFSC: > print_hfscstats(a->qstats); > break; > + case ALTQT_FAIRQ: > + print_fairqstats(a->qstats); > + break; > } > } > > @@ -382,6 +388,26 @@ print_hfscstats(struct queue_stats cur) > } > > void > +print_fairqstats(struct queue_stats cur) > +{ > + printf(" [ pkts: %10llu bytes: %10llu " > + "dropped pkts: %6llu bytes: %6llu ]\n", > + (unsigned long long)cur.data.fairq_stats.xmit_cnt.packets, > + (unsigned long long)cur.data.fairq_stats.xmit_cnt.bytes, > + (unsigned long long)cur.data.fairq_stats.drop_cnt.packets, > + (unsigned long long)cur.data.fairq_stats.drop_cnt.bytes); > + printf(" [ qlength: %3d/%3d ]\n", > + cur.data.fairq_stats.qlength, cur.data.fairq_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 > pfctl_free_altq_node(struct pf_altq_node *node) > { > while (node != NULL) { > @@ -421,6 +447,10 @@ update_avg(struct pf_altq_node *a) > b = qs->data.hfsc_stats.xmit_cnt.bytes; > p = qs->data.hfsc_stats.xmit_cnt.packets; > break; > + case ALTQT_FAIRQ: > + b = qs->data.fairq_stats.xmit_cnt.bytes; > + p = qs->data.fairq_stats.xmit_cnt.packets; > + break; > default: > b = 0; > p = 0; > > Modified: stable/10/share/man/man4/altq.4 > > ============================================================================== > --- stable/10/share/man/man4/altq.4 Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/share/man/man4/altq.4 Sat Apr 16 02:11:04 2016 > (r298091) > @@ -25,7 +25,7 @@ > .\" > .\" $FreeBSD$ > .\" > -.Dd December 9, 2011 > +.Dd June 24, 2015 > .Dt ALTQ 4 > .Os > .Sh NAME > @@ -40,6 +40,7 @@ > .Cd options ALTQ_HFSC > .Cd options ALTQ_CDNR > .Cd options ALTQ_PRIQ > +.Cd options ALTQ_FAIRQ > .Sh DESCRIPTION > The > .Nm > @@ -93,6 +94,10 @@ any of the available disciplines or cons > Build the > .Dq "Priority Queuing" > discipline. > +.It Dv ALTQ_FAIRQ > +Build the > +.Dq "Fair Queuing" > +discipline. > .It Dv ALTQ_NOPCC > Required if the TSC is unusable. > .It Dv ALTQ_DEBUG > > Modified: stable/10/sys/conf/NOTES > > ============================================================================== > --- stable/10/sys/conf/NOTES Sat Apr 16 00:01:16 2016 (r298090) > +++ stable/10/sys/conf/NOTES Sat Apr 16 02:11:04 2016 (r298091) > @@ -700,6 +700,7 @@ options ALTQ_CBQ # Class Based Queueing > options ALTQ_RED # Random Early Detection > options ALTQ_RIO # RED In/Out > options ALTQ_HFSC # Hierarchical Packet Scheduler > +options ALTQ_FAIRQ # Fair Packet Scheduler > options ALTQ_CDNR # Traffic conditioner > options ALTQ_PRIQ # Priority Queueing > options ALTQ_NOPCC # Required if the TSC is unusable > > Modified: stable/10/sys/conf/files > > ============================================================================== > --- stable/10/sys/conf/files Sat Apr 16 00:01:16 2016 (r298090) > +++ stable/10/sys/conf/files Sat Apr 16 02:11:04 2016 (r298091) > @@ -252,6 +252,7 @@ compat/freebsd32/freebsd32_syscalls.c op > compat/freebsd32/freebsd32_sysent.c optional compat_freebsd32 > contrib/altq/altq/altq_cbq.c optional altq > contrib/altq/altq/altq_cdnr.c optional altq > +contrib/altq/altq/altq_fairq.c optional altq > contrib/altq/altq/altq_hfsc.c optional altq > contrib/altq/altq/altq_priq.c optional altq > contrib/altq/altq/altq_red.c optional altq > > Modified: stable/10/sys/conf/options > > ============================================================================== > --- stable/10/sys/conf/options Sat Apr 16 00:01:16 2016 (r298090) > +++ stable/10/sys/conf/options Sat Apr 16 02:11:04 2016 (r298091) > @@ -385,6 +385,7 @@ ALTQ opt_global.h > ALTQ_CBQ opt_altq.h > ALTQ_CDNR opt_altq.h > ALTQ_DEBUG opt_altq.h > +ALTQ_FAIRQ opt_altq.h > ALTQ_HFSC opt_altq.h > ALTQ_NOPCC opt_altq.h > ALTQ_PRIQ opt_altq.h > > Modified: stable/10/sys/contrib/altq/altq/altq.h > > ============================================================================== > --- stable/10/sys/contrib/altq/altq/altq.h Sat Apr 16 00:01:16 2016 > (r298090) > +++ stable/10/sys/contrib/altq/altq/altq.h Sat Apr 16 02:11:04 2016 > (r298091) > @@ -63,7 +63,8 @@ > #define ALTQT_BLUE 10 /* blue */ > #define ALTQT_PRIQ 11 /* priority queue */ > #define ALTQT_JOBS 12 /* JoBS */ > -#define ALTQT_MAX 13 /* should be max > discipline type + 1 */ > +#define ALTQT_FAIRQ 13 /* fairq */ > +#define ALTQT_MAX 14 /* should be max > discipline type + 1 */ > > #ifdef ALTQ3_COMPAT > struct altqreq { > > Added: stable/10/sys/contrib/altq/altq/altq_fairq.c > > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ stable/10/sys/contrib/altq/altq/altq_fairq.c Sat Apr 16 > 02:11:04 2016 (r298091) > @@ -0,0 +1,874 @@ > +/* > + * Copyright (c) 2008 The DragonFly Project. All rights reserved. > + * > + * This code is derived from software contributed to The DragonFly Project > + * by Matthew Dillon <dillon@backplane.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. > + * 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. Neither the name of The DragonFly Project nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific, prior written permission. > + * > + * 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 HOLDERS 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. > + * > + * $DragonFly: src/sys/net/altq/altq_fairq.c,v 1.1 2008/04/06 18:58:15 > dillon Exp $ > + * $FreeBSD$ > + */ > +/* > + * Matt: I gutted altq_priq.c and used it as a skeleton on which to build > + * fairq. The fairq algorithm is completely different then priq, of > course, > + * but because I used priq's skeleton I believe I should include priq's > + * copyright. > + * > + * Copyright (C) 2000-2003 > + * Sony Computer Science Laboratories Inc. All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, > STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY > WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +/* > + * FAIRQ - take traffic classified by keep state (hashed into > + * mbuf->m_pkthdr.altq_state_hash) and bucketize it. Fairly extract > + * the first packet from each bucket in a round-robin fashion. > + * > + * TODO - better overall qlimit support (right now it is per-bucket). > + * - NOTE: red etc is per bucket, not overall. > + * - better service curve support. > + * > + * EXAMPLE: > + * > + * altq on em0 fairq bandwidth 650Kb queue { std, bulk } > + * queue std priority 3 bandwidth 400Kb \ > + * fairq (buckets 64, default, hogs 1Kb) qlimit 50 > + * queue bulk priority 2 bandwidth 100Kb \ > + * fairq (buckets 64, hogs 1Kb) qlimit 50 > + * > + * pass out on em0 from any to any keep state queue std > + * pass out on em0 inet proto tcp ..... port ... keep state queue bulk > + */ > +#include "opt_altq.h" > +#include "opt_inet.h" > +#include "opt_inet6.h" > + > +#ifdef ALTQ_FAIRQ /* fairq is enabled in the kernel conf */ > + > +#include <sys/param.h> > +#include <sys/malloc.h> > +#include <sys/mbuf.h> > +#include <sys/socket.h> > +#include <sys/sockio.h> > +#include <sys/systm.h> > +#include <sys/proc.h> > +#include <sys/errno.h> > +#include <sys/kernel.h> > +#include <sys/queue.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 <netpfil/pf/pf_mtag.h> > +#include <altq/altq.h> > +#include <altq/altq_fairq.h> > + > +/* > + * function prototypes > + */ > +static int fairq_clear_interface(struct fairq_if *); > +static int fairq_request(struct ifaltq *, int, void *); > +static void fairq_purge(struct fairq_if *); > +static struct fairq_class *fairq_class_create(struct fairq_if *, int, > int, u_int, struct fairq_opts *, int); > +static int fairq_class_destroy(struct fairq_class *); > +static int fairq_enqueue(struct ifaltq *, struct mbuf *, struct > altq_pktattr *); > +static struct mbuf *fairq_dequeue(struct ifaltq *, int); > + > +static int fairq_addq(struct fairq_class *, struct mbuf *, u_int32_t); > +static struct mbuf *fairq_getq(struct fairq_class *, uint64_t); > +static struct mbuf *fairq_pollq(struct fairq_class *, uint64_t, int *); > +static fairq_bucket_t *fairq_selectq(struct fairq_class *, int); > +static void fairq_purgeq(struct fairq_class *); > + > +static void get_class_stats(struct fairq_classstats *, struct > fairq_class *); > +static struct fairq_class *clh_to_clp(struct fairq_if *, uint32_t); > + > +int > +fairq_pfattach(struct pf_altq *a) > +{ > + struct ifnet *ifp; > + int error; > + > + if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL) > + return (EINVAL); > + > + error = altq_attach(&ifp->if_snd, ALTQT_FAIRQ, a->altq_disc, > + fairq_enqueue, fairq_dequeue, fairq_request, NULL, NULL); > + > + return (error); > +} > + > +int > +fairq_add_altq(struct pf_altq *a) > +{ > + struct fairq_if *pif; > + struct ifnet *ifp; > + > + if ((ifp = ifunit(a->ifname)) == NULL) > + return (EINVAL); > + if (!ALTQ_IS_READY(&ifp->if_snd)) > + return (ENODEV); > + > + > + pif = malloc(sizeof(struct fairq_if), > + M_DEVBUF, M_WAITOK | M_ZERO); > + pif->pif_bandwidth = a->ifbandwidth; > + pif->pif_maxpri = -1; > + pif->pif_ifq = &ifp->if_snd; > + > + /* keep the state in pf_altq */ > + a->altq_disc = pif; > + > + return (0); > +} > + > +int > +fairq_remove_altq(struct pf_altq *a) > +{ > + struct fairq_if *pif; > + > + if ((pif = a->altq_disc) == NULL) > + return (EINVAL); > + a->altq_disc = NULL; > + > + fairq_clear_interface(pif); > + > + free(pif, M_DEVBUF); > + return (0); > +} > + > +int > +fairq_add_queue(struct pf_altq *a) > +{ > + struct fairq_if *pif; > + struct fairq_class *cl; > + > + if ((pif = a->altq_disc) == NULL) > + return (EINVAL); > + > + /* check parameters */ > + if (a->priority >= FAIRQ_MAXPRI) > + return (EINVAL); > + if (a->qid == 0) > + return (EINVAL); > + if (pif->pif_classes[a->priority] != NULL) > + return (EBUSY); > + if (clh_to_clp(pif, a->qid) != NULL) > + return (EBUSY); > + > + cl = fairq_class_create(pif, a->priority, a->qlimit, a->bandwidth, > + &a->pq_u.fairq_opts, a->qid); > + if (cl == NULL) > + return (ENOMEM); > + > + return (0); > +} > + > +int > +fairq_remove_queue(struct pf_altq *a) > +{ > + struct fairq_if *pif; > + struct fairq_class *cl; > + > + if ((pif = a->altq_disc) == NULL) > + return (EINVAL); > + > + if ((cl = clh_to_clp(pif, a->qid)) == NULL) > + return (EINVAL); > + > + return (fairq_class_destroy(cl)); > +} > + > +int > +fairq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) > +{ > + struct fairq_if *pif; > + struct fairq_class *cl; > + struct fairq_classstats stats; > + int error = 0; > + > + if ((pif = altq_lookup(a->ifname, ALTQT_FAIRQ)) == NULL) > + return (EBADF); > + > + if ((cl = clh_to_clp(pif, a->qid)) == NULL) > + return (EINVAL); > + > + if (*nbytes < sizeof(stats)) > + return (EINVAL); > + > + get_class_stats(&stats, cl); > + > + if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0) > + return (error); > + *nbytes = sizeof(stats); > + return (0); > +} > + > +/* > + * bring the interface back to the initial state by discarding > + * all the filters and classes. > + */ > +static int > +fairq_clear_interface(struct fairq_if *pif) > +{ > + struct fairq_class *cl; > + int pri; > + > + /* clear out the classes */ > + for (pri = 0; pri <= pif->pif_maxpri; pri++) { > + if ((cl = pif->pif_classes[pri]) != NULL) > + fairq_class_destroy(cl); > + } > + > + return (0); > +} > + > +static int > +fairq_request(struct ifaltq *ifq, int req, void *arg) > +{ > + struct fairq_if *pif = (struct fairq_if *)ifq->altq_disc; > + > + IFQ_LOCK_ASSERT(ifq); > + > + switch (req) { > + case ALTRQ_PURGE: > + fairq_purge(pif); > + break; > + } > + return (0); > +} > + > +/* discard all the queued packets on the interface */ > +static void > +fairq_purge(struct fairq_if *pif) > +{ > + struct fairq_class *cl; > + int pri; > + > + for (pri = 0; pri <= pif->pif_maxpri; pri++) { > + if ((cl = pif->pif_classes[pri]) != NULL && cl->cl_head) > + fairq_purgeq(cl); > + } > + if (ALTQ_IS_ENABLED(pif->pif_ifq)) > + pif->pif_ifq->ifq_len = 0; > +} > + > +static struct fairq_class * > +fairq_class_create(struct fairq_if *pif, int pri, int qlimit, > + u_int bandwidth, struct fairq_opts *opts, int qid) > +{ > + struct fairq_class *cl; > + int flags = opts->flags; > + u_int nbuckets = opts->nbuckets; > + int i; > + > +#ifndef ALTQ_RED > + if (flags & FARF_RED) { > +#ifdef ALTQ_DEBUG > + printf("fairq_class_create: RED not configured for > FAIRQ!\n"); > +#endif > + return (NULL); > + } > +#endif > + if (nbuckets == 0) > + nbuckets = 256; > + if (nbuckets > FAIRQ_MAX_BUCKETS) > + nbuckets = FAIRQ_MAX_BUCKETS; > + /* enforce power-of-2 size */ > + while ((nbuckets ^ (nbuckets - 1)) != ((nbuckets << 1) - 1)) > + ++nbuckets; > + > + if ((cl = pif->pif_classes[pri]) != NULL) { > + /* modify the class instead of creating a new one */ > + IFQ_LOCK(cl->cl_pif->pif_ifq); > + if (cl->cl_head) > + fairq_purgeq(cl); > + IFQ_UNLOCK(cl->cl_pif->pif_ifq); > +#ifdef ALTQ_RIO > + if (cl->cl_qtype == Q_RIO) > + rio_destroy((rio_t *)cl->cl_red); > +#endif > +#ifdef ALTQ_RED > + if (cl->cl_qtype == Q_RED) > + red_destroy(cl->cl_red); > +#endif > + } else { > + cl = malloc(sizeof(struct fairq_class), > + M_DEVBUF, M_WAITOK | M_ZERO); > + cl->cl_nbuckets = nbuckets; > + cl->cl_nbucket_mask = nbuckets - 1; > + > + cl->cl_buckets = malloc( > + sizeof(struct fairq_bucket) * cl->cl_nbuckets, > + M_DEVBUF, M_WAITOK | M_ZERO); > + cl->cl_head = NULL; > + } > + > + pif->pif_classes[pri] = cl; > > *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** > > -- > Ermal >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAPBZQG2gZ4_aFkzNOPcisiJE1k88ZV%2Bn=pywe_2j=2vehxczEg>