From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wi0-f175.google.com (mail-wi0-f175.google.com [209.85.212.175]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (verified OK)) by huchra.bufferbloat.net (Postfix) with ESMTPS id 7C7D4200B1B for ; Thu, 3 May 2012 11:01:45 -0700 (PDT) Received: by wibhn6 with SMTP id hn6so564477wib.10 for ; Thu, 03 May 2012 11:01:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=M31+MJBQE0OAkE0IJeIR9nbwSN13oGPyQhe86I+FyOE=; b=vg4TyW5uuPWG+5vibA7YSNsCvkoPi6KSMle00udZFsjRVZdLTCT3mi2yfO6hu7hmRO y+8WWolImUeCa8MVwhoWQXlsCpFkSgGF5HAdCUrrQTuPteU4QcWKJpasM9ebSXYH0XWm SJW/V9wiztH0vgr+t5wtdj+Dbau5ZyDvWaovREV7PBrgKYMvh3/+YDL9+q5yUMLTEvt9 uYPiw3UYD0HwnQp8HEaP41D/VgIsxCfBusgj/15fY0YTKjuGY9l8ghBOnAvVeM6X5VPA HO2AdqbYyHx1d6t6S2Yx6Fxtfk7j/gjfNreFlhvaWbjWKM6wOJ+oibpwm3kh5XWjVhMc dUlg== MIME-Version: 1.0 Received: by 10.180.105.69 with SMTP id gk5mr6374025wib.3.1336068103426; Thu, 03 May 2012 11:01:43 -0700 (PDT) Received: by 10.223.112.66 with HTTP; Thu, 3 May 2012 11:01:43 -0700 (PDT) In-Reply-To: <1336067533-16923-2-git-send-email-dave.taht@bufferbloat.net> References: <1336067533-16923-1-git-send-email-dave.taht@bufferbloat.net> <1336067533-16923-2-git-send-email-dave.taht@bufferbloat.net> Date: Thu, 3 May 2012 11:01:43 -0700 Message-ID: From: Dave Taht To: =?ISO-8859-1?Q?Dave_T=E4ht?= Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Cc: codel@lists.bufferbloat.net Subject: Re: [Codel] [PATCH] Preliminary codel implementation 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 18:01:46 -0000 This does compile, and does not crash the kernel, and it even passes traffic! but... as noted I goofed on the netlink interface somehow, and as this is a transliteration from C++ and ns2 slides into C and linux network scheduling code, that I started writing at 2AM... I could also have goofed in multiple other places. I built these against linux-stable 3.3.4 and iproute current git head. So a bit of review for logical and technical correctness is highly desired. On Thu, May 3, 2012 at 10:52 AM, Dave T=E4ht wr= ote: > --- > =A0include/linux/pkt_sched.h | =A0 29 +++++ > =A0net/sched/Kconfig =A0 =A0 =A0 =A0 | =A0 11 ++ > =A0net/sched/Makefile =A0 =A0 =A0 =A0| =A0 =A01 + > =A0net/sched/sch_codel.c =A0 =A0 | =A0296 +++++++++++++++++++++++++++++++= ++++++++++++++ > =A04 files changed, 337 insertions(+) > =A0create mode 100644 net/sched/sch_codel.c > > diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h > index 0d5b793..c21b720 100644 > --- a/include/linux/pkt_sched.h > +++ b/include/linux/pkt_sched.h > @@ -633,4 +633,33 @@ struct tc_qfq_stats { > =A0 =A0 =A0 =A0__u32 lmax; > =A0}; > > +/* CODEL */ > + > +enum { > + =A0 =A0 =A0 TCA_CODEL_UNSPEC, > + =A0 =A0 =A0 TCA_CODEL_PARMS, > + =A0 =A0 =A0 TCA_CODEL_TARGET, > + =A0 =A0 =A0 TCA_CODEL_DEPTH, > + =A0 =A0 =A0 TCA_CODEL_MINBYTES, > + =A0 =A0 =A0 TCA_CODEL_INTERVAL, > + =A0 =A0 =A0 __TCA_CODEL_MAX > +}; > + > +#define TCA_CODEL_MAX =A0(__TCA_CODEL_MAX - 1) > +#define TC_CODEL_ECN 1 > + > +struct tc_codel_qopt { > + =A0 =A0 =A0 =A0__u32 flags; =A0 /* flags (e.g. ecn) */ > + =A0 =A0 =A0 __u32 target; =A0 /* max delay, in us */ > + =A0 =A0 =A0 =A0__u32 depth; =A0 /* queue depth in packets */ > + =A0 =A0 =A0 =A0__u32 minbytes; =A0 =A0 =A0 =A0/* MTU (usually) */ > + =A0 =A0 =A0 =A0__u32 interval; =A0 =A0 =A0 =A0/* Sliding min time windo= w width (us) */ > +}; > + > +struct tc_codel_stats { > + =A0 =A0 =A0 __u64 drops; > + =A0 =A0 =A0 __u64 marks; > +}; > + > + > =A0#endif > diff --git a/net/sched/Kconfig b/net/sched/Kconfig > index 2590e91..8106c42 100644 > --- a/net/sched/Kconfig > +++ b/net/sched/Kconfig > @@ -250,6 +250,17 @@ config NET_SCH_QFQ > > =A0 =A0 =A0 =A0 =A0If unsure, say N. > > +config NET_SCH_CODEL > + =A0 =A0 =A0 tristate "Controlled Delay AQM (CODEL)" > + =A0 =A0 =A0 help > + =A0 =A0 =A0 =A0 Say Y here if you want to use the Controlled Delay (COD= EL) > + =A0 =A0 =A0 =A0 packet scheduling algorithm. > + > + =A0 =A0 =A0 =A0 To compile this driver as a module, choose M here: the = module > + =A0 =A0 =A0 =A0 will be called sch_codel. > + > + =A0 =A0 =A0 =A0 If unsure, say N. > + > =A0config NET_SCH_INGRESS > =A0 =A0 =A0 =A0tristate "Ingress Qdisc" > =A0 =A0 =A0 =A0depends on NET_CLS_ACT > diff --git a/net/sched/Makefile b/net/sched/Makefile > index dc5889c..41130b5 100644 > --- a/net/sched/Makefile > +++ b/net/sched/Makefile > @@ -36,6 +36,7 @@ obj-$(CONFIG_NET_SCH_DRR) =A0 =A0 +=3D sch_drr.o > =A0obj-$(CONFIG_NET_SCH_MQPRIO) =A0 +=3D sch_mqprio.o > =A0obj-$(CONFIG_NET_SCH_CHOKE) =A0 =A0+=3D sch_choke.o > =A0obj-$(CONFIG_NET_SCH_QFQ) =A0 =A0 =A0+=3D sch_qfq.o > +obj-$(CONFIG_NET_SCH_CODEL) =A0 =A0+=3D sch_codel.o > > =A0obj-$(CONFIG_NET_CLS_U32) =A0 =A0 =A0+=3D cls_u32.o > =A0obj-$(CONFIG_NET_CLS_ROUTE4) =A0 +=3D cls_route.o > diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c > new file mode 100644 > index 0000000..159df47 > --- /dev/null > +++ b/net/sched/sch_codel.c > @@ -0,0 +1,296 @@ > +/* > + * net/sched/sch_codel.c =A0 =A0 =A0 A Codel implementation > + * > + * =A0 =A0 =A0 =A0 =A0 =A0 This program is free software; you can redist= ribute it and/or > + * =A0 =A0 =A0 =A0 =A0 =A0 modify it under the terms of the GNU General = Public License > + * =A0 =A0 =A0 =A0 =A0 =A0 as published by the Free Software Foundation;= either version > + * =A0 =A0 =A0 =A0 =A0 =A0 2 of the License, or (at your option) any lat= er version. > + * > + * Based on ns2 simulation code presented by Kathie Nichols > + * Authors: =A0 =A0Dave T=E4ht > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define MS2TIME(a) (ns_to_ktime( (u64) a*1000000)) > +#define DEFAULT_CODEL_DEPTH 1000 > + > +/* Per-queue state (codel_queue_t instance variables) */ > + > +struct codel_sched_data { > + =A0 =A0 =A0 u32 flags; > + =A0 =A0 =A0 u32 minbytes; > + =A0 =A0 =A0 u32 count; /* packets dropped since we went into drop state= */ > + =A0 =A0 =A0 bool dropping; =A0/* 1 if in drop state, might just add to = flags */ > + =A0 =A0 =A0 ktime_t target; > + =A0 =A0 =A0 ktime_t interval; > + =A0 =A0 =A0 =A0/* time to declare above q->target (0 if below)*/ > + =A0 =A0 =A0 ktime_t first_above_time; > + =A0 =A0 =A0 ktime_t drop_next; /* time to drop next packet */ > +}; > + > +struct codel_skb_cb { > + =A0 =A0 =A0 ktime_t enqueue_time; > + =A0 =A0 =A0 char data[16]; > +}; > + > +static inline struct codel_skb_cb *get_codel_cb(const struct sk_buff *sk= b) > +{ > + =A0 =A0 =A0 return (struct codel_skb_cb *)skb->cb; > +} > + > +static inline ktime_t get_enqueue_time(const struct sk_buff *skb) { > + =A0 =A0 =A0 struct codel_skb_cb *cb =3D get_codel_cb(skb); > + =A0 =A0 =A0 return cb->enqueue_time; > +} > + > +static inline ktime_t set_enqueue_time(struct sk_buff *skb, ktime_t t ) = { > + =A0 =A0 =A0 struct codel_skb_cb *cb =3D get_codel_cb(skb); > + =A0 =A0 =A0 cb->enqueue_time =3D t; > + =A0 =A0 =A0 return t; > +} > + > +static inline ktime_t control_law(const struct codel_sched_data *q, ktim= e_t t) > +{ > + =A0 =A0 =A0 t.tv64 =3D t.tv64 + q->interval.tv64 / int_sqrt(q->count); > + =A0 =A0 =A0 return t; > +} > + > +/* > +static int codel_prob_mark(const struct codel_sched_data *q) > +{ > + =A0 =A0 =A0 return q->flags & TC_CODEL_ECN; > +} > +*/ > + > + /* wrappers for ultimate statistics collection */ > + > +static int codel_drop(struct sk_buff *skb, struct Qdisc *sch) { > + =A0 =A0 =A0 return qdisc_drop(skb,sch); > +} > + > +/* > +static int codel_queue_drop(struct Qdisc *sch) { > + =A0 =A0 =A0 return qdisc_drop(skb,sch); > +} > +*/ > + > +struct sk_buff *codel_dequeue_head(struct Qdisc *sch) { > + =A0 =A0 =A0 return(qdisc_dequeue_head(sch)); > +} > + > +bool should_drop(struct sk_buff *skb, struct Qdisc *sch, ktime_t now) > +{ > + =A0 =A0 =A0 struct codel_sched_data *q =3D qdisc_priv(sch); > + =A0 =A0 =A0 bool drop =3D 0; > + =A0 =A0 =A0 if (skb =3D=3D NULL) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->first_above_time.tv64 =3D 0; > + =A0 =A0 =A0 } else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ktime_t sojourn_time =3D ktime_sub(now, get= _enqueue_time(skb)); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sojourn_time.tv64 < > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->target.tv64 || sch->qstats.backl= og < q->minbytes) { > +/* went below so we=92ll stay below for at least q->interval */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->first_above_time.tv64 = =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (q->first_above_time.tv6= 4 =3D=3D 0) { > + > +/* just went above from below. If we stay above > + * for at least q->interval we=92ll say it=92s ok to drop > + */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->first_ab= ove_time =3D > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 ktime_add(now,q->interval); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (now.tv64 >=3D q-= >first_above_time.tv64) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 drop =3D 1; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 } > + =A0 =A0 =A0 return drop; > +} > + > +static struct sk_buff *codel_dequeue(struct Qdisc *sch) > +{ > + =A0 =A0 =A0 struct codel_sched_data *q =3D qdisc_priv(sch); > + =A0 =A0 =A0 struct sk_buff *skb =3D codel_dequeue_head(sch); > + =A0 =A0 =A0 ktime_t now; > + =A0 =A0 =A0 bool drop; > + =A0 =A0 =A0 if (skb =3D=3D NULL) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->dropping =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->first_above_time.tv64 =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return skb; > + =A0 =A0 =A0 } > + =A0 =A0 =A0 now =3D ktime_get(); > + =A0 =A0 =A0 drop =3D should_drop(skb, sch, now); > + =A0 =A0 =A0 if (q->dropping) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (drop) { > +/* sojourn time below target - leave dropping state */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->dropping =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (now.tv64 >=3D q->drop_next.tv64)= { > +/* > + * It=92s time for the next drop. Drop the current packet and dequeue th= e next. > + * The dequeue might take us out of dropping state. If not, schedule the > + * next drop. A large backlog might result in drop rates so high that th= e next > + * drop should happen now, hence the =91while=92 loop. > + */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 while (now.tv64 >=3D q->dro= p_next.tv64 && q->dropping) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 codel_drop(= skb, sch); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->count++; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb =3D cod= el_dequeue_head(sch); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (should_= drop(skb,sch,now)) { > +/* leave dropping state */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 q->dropping =3D 0; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > +/* and schedule the next drop */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 q->drop_next =3D > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 control_law(q,q->drop_next); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else if (drop && > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0((now.tv64 - q->drop= _next.tv64 < > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 16 * q->int= erval.tv64) || > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (now.tv64 - q->firs= t_above_time.tv64 >=3D > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A02 * q->interval.= tv64))) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 codel_drop(skb, sch); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 skb =3D codel_dequeue_head(= sch); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* engage state machine */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 drop =3D should_drop(skb,sc= h,now); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->dropping =3D 1; > + > +/* if min went above target close to when we last went below it > + * assume that the drop rate that controlled the queue on the > + * last cycle is a good starting point to control it now. > + */ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (now.tv64 - q->drop_next= .tv64 < > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 16 * q->int= erval.tv64) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int c =3D q= ->count - 1; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->count = =3D c < 1 ? 1 : c; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->count = =3D 1; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 q->drop_next =3D control_la= w(q,now); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 } > + =A0 =A0 =A0 return skb; > +} > + > + > +static int codel_enqueue(struct sk_buff *skb, struct Qdisc *sch) > +{ > + =A0 =A0 =A0 if (likely(skb_queue_len(&sch->q) < sch->limit)) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 set_enqueue_time(skb,ktime_get()); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return qdisc_enqueue_tail(skb, sch); > + =A0 =A0 =A0 } > + =A0 =A0 =A0 return qdisc_reshape_fail(skb, sch); > +} > + > +static int codel_change(struct Qdisc *sch, struct nlattr *opt) > +{ > + =A0 =A0 =A0 struct codel_sched_data *q =3D qdisc_priv(sch); > + =A0 =A0 =A0 struct tc_codel_qopt *ctl =3D nla_data(opt); > + =A0 =A0 =A0 unsigned int qlen; > + > + =A0 =A0 =A0 if (opt->nla_len < nla_attr_size(sizeof(*ctl))) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EINVAL; > + =A0 =A0 =A0 if (ctl->depth && (ctl->depth < 2 || ctl->depth > 65536)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EINVAL; > + =A0 =A0 =A0 if (ctl->minbytes && (ctl->minbytes < 64 || ctl->minbytes >= 65536)) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -EINVAL; > + =A0 =A0 =A0 sch_tree_lock(sch); > + =A0 =A0 =A0 if (ctl->minbytes) q->minbytes =3D ctl->minbytes; > + =A0 =A0 =A0 if (ctl->flags) q->flags =3D ctl->flags; > + =A0 =A0 =A0 if (ctl->target) q->target =3D ns_to_ktime((u64) ctl->targe= t * 1000); > + =A0 =A0 =A0 if (ctl->interval) q->interval =3D > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ns_to_ktime((u64) ctl->inte= rval * 1000); > + > + =A0 =A0 =A0 /* something saner than this for depth is probably needed *= / > + > + =A0 =A0 =A0 if (ctl->depth) sch->limit =3D ctl->depth; > + =A0 =A0 =A0 qlen =3D sch->q.qlen; > +// =A0 =A0 while (sch->q.qlen > ctl->depth) > +// =A0 =A0 =A0 =A0 =A0 =A0 codel_drop(skb,sch); > +// =A0 =A0 qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen); //? > + =A0 =A0 =A0 q->drop_next.tv64 =3D q->first_above_time.tv64 =3D 0; > + =A0 =A0 =A0 q->dropping =3D 0; /* exit dropping state */ > + =A0 =A0 =A0 sch_tree_unlock(sch); > + =A0 =A0 =A0 return 0; > +} > + > +static int codel_init(struct Qdisc *sch, struct nlattr *opt) > +{ > + =A0 =A0 =A0 struct codel_sched_data *q =3D qdisc_priv(sch); > + =A0 =A0 =A0 q->target =3D MS2TIME(5); > + =A0 =A0 =A0 sch->limit =3D =A0DEFAULT_CODEL_DEPTH; > + =A0 =A0 =A0 q->minbytes =3D 1500; > + =A0 =A0 =A0 q->interval =3D MS2TIME(100); > + =A0 =A0 =A0 if (opt) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 int err =3D codel_change(sch, opt); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (err) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return err; > + =A0 =A0 =A0 } > + > +/* =A0 =A0 if (sch->limit >=3D 1) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sch->flags |=3D TCQ_F_CAN_BYPASS; > + =A0 =A0 =A0 else > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 sch->flags &=3D ~TCQ_F_CAN_BYPASS; > +*/ > + =A0 =A0 =A0 return 0; > +} > + > +static int codel_dump(struct Qdisc *sch, struct sk_buff *skb) > +{ > + =A0 =A0 =A0 struct codel_sched_data *q =3D qdisc_priv(sch); > + =A0 =A0 =A0 struct tc_codel_qopt opt; > + =A0 =A0 =A0 opt.target =3D (u32) ktime_to_us(q->target); > + =A0 =A0 =A0 opt.interval =A0=3D (u32) ktime_to_us(q->interval); > + =A0 =A0 =A0 opt.depth =A0=3D sch->limit; > + =A0 =A0 =A0 opt.flags =A0=3D q->flags; > + =A0 =A0 =A0 NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); > + =A0 =A0 =A0 return skb->len; > + > +nla_put_failure: > +// =A0 =A0 nlmsg_trim(skb, b); > + =A0 =A0 =A0 return -1; > +} > + > +static void > +codel_reset(struct Qdisc *sch) > +{ > + =A0 =A0 =A0 struct sk_buff *skb; > + > + =A0 =A0 =A0 while ((skb =3D codel_dequeue(sch)) !=3D NULL) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree_skb(skb); > +} > + > +struct Qdisc_ops codel_qdisc_ops __read_mostly =3D { > + =A0 =A0 =A0 .id =A0 =A0 =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 "codel", > + =A0 =A0 =A0 .priv_size =A0 =A0 =A0=3D =A0 =A0 =A0 sizeof(struct codel_s= ched_data), > + =A0 =A0 =A0 .enqueue =A0 =A0 =A0 =A0=3D =A0 =A0 =A0 codel_enqueue, > + =A0 =A0 =A0 .dequeue =A0 =A0 =A0 =A0=3D =A0 =A0 =A0 codel_dequeue, > + =A0 =A0 =A0 .peek =A0 =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 qdisc_peek_head, > +/* =A0 =A0 .drop =A0 =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 codel_queue_drop, *= / > + =A0 =A0 =A0 .init =A0 =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 codel_init, > + =A0 =A0 =A0 .reset =A0 =A0 =A0 =A0 =A0=3D =A0 =A0 =A0 codel_reset, > + =A0 =A0 =A0 .change =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 codel_change, > + =A0 =A0 =A0 .dump =A0 =A0 =A0 =A0 =A0 =3D =A0 =A0 =A0 codel_dump, > + =A0 =A0 =A0 .owner =A0 =A0 =A0 =A0 =A0=3D =A0 =A0 =A0 THIS_MODULE, > +}; > +EXPORT_SYMBOL(codel_qdisc_ops); > + > +static int __init codel_module_init(void) > +{ > + =A0 =A0 =A0 =A0return register_qdisc(&codel_qdisc_ops); > +} > +static void __exit codel_module_exit(void) > +{ > + =A0 =A0 =A0 =A0unregister_qdisc(&codel_qdisc_ops); > +} > +module_init(codel_module_init) > +module_exit(codel_module_exit) > +MODULE_LICENSE("GPL"); > + > -- > 1.7.9.5 > > > _______________________________________________ > Codel mailing list > Codel@lists.bufferbloat.net > https://lists.bufferbloat.net/listinfo/codel > --=20 Dave T=E4ht SKYPE: davetaht US Tel: 1-239-829-5608 http://www.bufferbloat.net