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