From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by huchra.bufferbloat.net (Postfix, from userid 1000) id E7077201A91; Thu, 3 May 2012 10:52:31 -0700 (PDT) From: =?UTF-8?q?Dave=20T=C3=A4ht?= To: codel@lists.bufferbloat.net Date: Thu, 3 May 2012 10:52:12 -0700 Message-Id: <1336067533-16923-1-git-send-email-dave.taht@bufferbloat.net> X-Mailer: git-send-email 1.7.1 X-Mailman-Approved-At: Thu, 03 May 2012 10:53:46 -0700 Cc: =?UTF-8?q?Dave=20T=C3=A4ht?= Subject: [Codel] [PATCH] iproute2: added preliminary codel support X-BeenThere: codel@lists.bufferbloat.net X-Mailman-Version: 2.1.13 Precedence: list List-Id: CoDel AQM discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 May 2012 17:52:32 -0000 this makes certain constants in the code variables, but has seemingly good defaults. target and interval can be specified with a ms, s, or us parameter mtu is in bytes ecn, while part of the api, is not enabled in the code --- include/linux/pkt_sched.h | 28 ++++++++++ tc/Makefile | 1 + tc/q_codel.c | 135 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 tc/q_codel.c diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 410b33d..150aee9 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -654,4 +654,32 @@ struct tc_qfq_stats { __u32 lmax; }; +/* CODEL */ + +enum { + TCA_CODEL_UNSPEC, + TCA_CODEL_PARMS, + TCA_CODEL_TARGET, + TCA_CODEL_DEPTH, + TCA_CODEL_MINBYTES, + TCA_CODEL_INTERVAL, + __TCA_CODEL_MAX +}; + +#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1) +#define TC_CODEL_ECN 1 + +struct tc_codel_qopt { + __u32 flags; /* flags (e.g. ecn) */ + __u32 target; /* max delay, in us */ + __u32 depth; /* queue depth in packets */ + __u32 minbytes; /* MTU (usually) */ + __u32 interval; /* Sliding min time window width (us) */ +}; + +struct tc_codel_stats { + __u64 drops; + __u64 marks; +}; + #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..2ff51a1 --- /dev/null +++ b/tc/q_codel.c @@ -0,0 +1,135 @@ +/* + * q_codel.c Controlled Delay + * + * 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: Dave Taht + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "tc_util.h" + +static void explain(void) +{ + fprintf(stderr, + "Usage: ... codel [target MAX_DELAY] [depth PACKETS]" + " [mtu MINBYTES]\n " + "[interval INTEGRATION_TIME] [ecn]\n" ); +} + +static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n) +{ + struct tc_codel_qopt opt; + struct rtattr *tail; + + memset(&opt, 0, sizeof(opt)); + opt.target = 5000; + opt.depth = 1000; + opt.interval = 1000*100; + opt.minbytes = 1500; + opt.flags = 0; + + while (argc > 0) { + if (strcmp(*argv, "target") == 0) { + NEXT_ARG(); + if (get_time(&opt.target, *argv)) { + fprintf(stderr, "Illegal \"target\"\n"); + return -1; + } + } else if (strcmp(*argv, "depth") == 0) { + NEXT_ARG(); + if (get_u32(&opt.depth, *argv, 0)) { + fprintf(stderr, "Illegal \"depth\"\n"); + return -1; + } + } else if (strcmp(*argv, "interval") == 0) { + NEXT_ARG(); + if (get_time(&opt.interval, *argv)) { + fprintf(stderr, "Illegal \"interval\"\n"); + return -1; + } + } else if (strcmp(*argv, "mtu") == 0) { + NEXT_ARG(); + if (get_u32(&opt.minbytes, *argv, 0)) { + fprintf(stderr, "Illegal \"mtu\"\n"); + return -1; + } + } else if (strcmp(*argv, "ecn") == 0) { + opt.flags |= TC_CODEL_ECN; + } 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); + addattr_l(n, 1024, TCA_CODEL_PARMS, &opt, sizeof(opt)); + 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]; + struct tc_codel_qopt *qopt; + + if (opt == NULL) + return 0; + + parse_rtattr_nested(tb, TCA_CODEL_MAX, opt); + if (tb[TCA_CODEL_PARMS] == NULL) + return -1; + qopt = RTA_DATA(tb[TCA_CODEL_PARMS]); + if (RTA_PAYLOAD(tb[TCA_CODEL_PARMS]) < sizeof(*qopt)) + return -1; + fprintf(f," target %dus depth %d mtu %d interval %dus %s\n", + qopt->target, qopt->depth, qopt->minbytes, + qopt->interval, (qopt->flags & TC_CODEL_ECN) ? "ecn" : ""); + + return 0; +} + +static int codel_print_xstats(struct qdisc_util *qu, FILE *f, + struct rtattr *xstats) +{ + struct tc_codel_stats *st; + + if (xstats == NULL) + return 0; + + if (RTA_PAYLOAD(xstats) < sizeof(*st)) + return -1; + + st = RTA_DATA(xstats); + fprintf(f, " dropped %lu marked %lu ", + st->drops, st->marks); + + return 0; +} + +struct qdisc_util codel_qdisc_util = { + .id = "codel", + .parse_qopt = codel_parse_opt, + .print_qopt = codel_print_opt, + .print_xstats = codel_print_xstats, +}; -- 1.7.9.5