svn commit: r298091 - in stable/10: sbin/pfctl share/man/man4 sys/conf sys/contrib/altq/altq sys/netpfil/pf
Ermal Luçi
eri at freebsd.org
Mon Apr 18 18:17:21 UTC 2016
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 at 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 at 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
>
More information about the svn-src-all
mailing list