[Codel] [PATCH 1/2] codel: Controlled Delay AQM

Dave Taht dave.taht at gmail.com
Sat May 5 15:47:40 EDT 2012


On Sat, May 5, 2012 at 12:32 PM, Dave Taht <dave.taht at bufferbloat.net> wrote:
> From: Dave Täht <dave.taht at bufferbloat.net>
>
> tc qdisc ... codel [ limit PACKETS ] [ target TIME]
>                   [ interval TIME ] [ minbytes BYTES ]
>
> Signed-off-by: Eric Dumazet <edumazet at google.com>
> Signed-off-by: Dave Täht <dave.taht at bufferbloat.net>
> ---
>  include/linux/pkt_sched.h |   14 +++++
>  tc/Makefile               |    1 +
>  tc/q_codel.c              |  136 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 151 insertions(+)
>  create mode 100644 tc/q_codel.c
>
> diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
> index 410b33d..62a73bf 100644
> --- a/include/linux/pkt_sched.h
> +++ b/include/linux/pkt_sched.h
> @@ -509,6 +509,7 @@ enum {
>        TCA_NETEM_CORRUPT,
>        TCA_NETEM_LOSS,
>        TCA_NETEM_RATE,
> +       TCA_NETEM_ECN,
>        __TCA_NETEM_MAX,
>  };
>
> @@ -654,4 +655,17 @@ struct tc_qfq_stats {
>        __u32 lmax;
>  };
>
> +/* CODEL */
> +
> +enum {
> +       TCA_CODEL_UNSPEC,
> +       TCA_CODEL_TARGET,
> +       TCA_CODEL_LIMIT,
> +       TCA_CODEL_MINBYTES,
> +       TCA_CODEL_INTERVAL,
> +       __TCA_CODEL_MAX
> +};
> +
> +#define TCA_CODEL_MAX  (__TCA_CODEL_MAX - 1)
> +
>  #endif
> diff --git a/tc/Makefile b/tc/Makefile
> index be8cd5a..8a7cc8d 100644
> --- a/tc/Makefile
> +++ b/tc/Makefile
> @@ -47,6 +47,7 @@ TCMODULES += em_cmp.o
>  TCMODULES += em_u32.o
>  TCMODULES += em_meta.o
>  TCMODULES += q_mqprio.o
> +TCMODULES += q_codel.o
>
>  TCSO :=
>  ifeq ($(TC_CONFIG_ATM),y)
> diff --git a/tc/q_codel.c b/tc/q_codel.c
> new file mode 100644
> index 0000000..0a7cf9f
> --- /dev/null
> +++ b/tc/q_codel.c
> @@ -0,0 +1,136 @@
> +/*
> + * q_codel.c           Codel.
> + *
> + *             This program is free software; you can redistribute it and/or
> + *             modify it under the terms of the GNU General Public License
> + *             as published by the Free Software Foundation; either version
> + *             2 of the License, or (at your option) any later version.
> + *
> + * Authors:    Eric Dumazet <edumazet at google.com>
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <syslog.h>
> +#include <fcntl.h>
> +#include <sys/socket.h>
> +#include <netinet/in.h>
> +#include <arpa/inet.h>
> +#include <string.h>
> +#include <math.h>
> +
> +#include "utils.h"
> +#include "tc_util.h"
> +
> +static void explain(void)
> +{
> +       fprintf(stderr, "Usage: ... codel [ limit PACKETS ] [ target TIME]\n");
> +       fprintf(stderr, "                 [ interval TIME ] [ minbytes BYTES ]\n");
> +}
> +
> +static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
> +                          struct nlmsghdr *n)
> +{
> +       struct tc_red_qopt opt;
> +       unsigned limit = 0;
> +       unsigned target = 0;
> +       unsigned interval = 0;
> +       unsigned minbytes = 0;
> +       struct rtattr *tail;
> +
> +       while (argc > 0) {
> +               if (strcmp(*argv, "limit") == 0) {
> +                       NEXT_ARG();
> +                       if (get_unsigned(&limit, *argv, 0)) {
> +                               fprintf(stderr, "Illegal \"limit\"\n");
> +                               return -1;
> +                       }
> +               } else if (strcmp(*argv, "minbytes") == 0) {
> +                       NEXT_ARG();
> +                       if (get_unsigned(&minbytes, *argv, 0)) {
> +                               fprintf(stderr, "Illegal \"minbytes\"\n");
> +                               return -1;
> +                       }
> +               } else if (strcmp(*argv, "target") == 0) {
> +                       NEXT_ARG();
> +                       if (get_time(&target, *argv)) {
> +                               fprintf(stderr, "Illegal \"target\"\n");
> +                               return -1;
> +                       }
> +               } else if (strcmp(*argv, "interval") == 0) {
> +                       NEXT_ARG();
> +                       if (get_time(&interval, *argv)) {
> +                               fprintf(stderr, "Illegal \"interval\"\n");
> +                               return -1;
> +                       }
> +               } else if (strcmp(*argv, "help") == 0) {
> +                       explain();
> +                       return -1;
> +               } else {
> +                       fprintf(stderr, "What is \"%s\"?\n", *argv);
> +                       explain();
> +                       return -1;
> +               }
> +               argc--; argv++;
> +       }
> +
> +       tail = NLMSG_TAIL(n);
> +       addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
> +
> +       if (limit)
> +               addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
> +       if (minbytes)
> +               addattr_l(n, 1024, TCA_CODEL_MINBYTES, &minbytes, sizeof(minbytes));
> +       if (interval)
> +               addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
> +       if (target)
> +               addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
> +       tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
> +       return 0;
> +}
> +
> +static int codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
> +{
> +       struct rtattr *tb[TCA_CODEL_MAX + 1];
> +       unsigned limit;
> +       unsigned interval;
> +       unsigned target;
> +       unsigned minbytes;
> +       SPRINT_BUF(b1);
> +
> +       if (opt == NULL)
> +               return 0;
> +
> +       parse_rtattr_nested(tb, TCA_CODEL_MAX, opt);
> +
> +       if (tb[TCA_CODEL_LIMIT] &&
> +           RTA_PAYLOAD(tb[TCA_CODEL_LIMIT]) >= sizeof(__u32)) {
> +               limit = rta_getattr_u32(tb[TCA_CODEL_LIMIT]);
> +               fprintf(f, "limit %up ", limit);
> +       }
> +       if (tb[TCA_CODEL_MINBYTES] &&
> +           RTA_PAYLOAD(tb[TCA_CODEL_MINBYTES]) >= sizeof(__u32)) {
> +               minbytes = rta_getattr_u32(tb[TCA_CODEL_MINBYTES]);
> +               fprintf(f, "minbytes %u ", minbytes);
> +       }
> +       if (tb[TCA_CODEL_TARGET] &&
> +           RTA_PAYLOAD(tb[TCA_CODEL_TARGET]) >= sizeof(__u32)) {
> +               target = rta_getattr_u32(tb[TCA_CODEL_TARGET]);
> +               fprintf(f, "target %s ", sprint_time(target, b1));
> +       }
> +       if (tb[TCA_CODEL_INTERVAL] &&
> +           RTA_PAYLOAD(tb[TCA_CODEL_INTERVAL]) >= sizeof(__u32)) {
> +               interval = rta_getattr_u32(tb[TCA_CODEL_INTERVAL]);
> +               fprintf(f, "interval %s ", sprint_time(interval, b1));
> +       }
> +
> +       return 0;
> +}
> +
> +
> +struct qdisc_util codel_qdisc_util = {
> +       .id             = "codel",
> +       .parse_qopt     = codel_parse_opt,
> +       .print_qopt     = codel_print_opt,
> +};
> --
> 1.7.9.5

I note that your recent work on ECN for netem crept in, and it should
probably stay in whatever patches exist out of tree for it.
Please feel free to rework these two patches into one, add my
signed-off-by, and resubmit.

-- 
Dave Täht
SKYPE: davetaht
US Tel: 1-239-829-5608
http://www.bufferbloat.net



More information about the Codel mailing list