12 #include <linux/module.h>
13 #include <linux/types.h>
14 #include <linux/kernel.h>
16 #include <linux/string.h>
18 #include <linux/errno.h>
22 #include <linux/slab.h>
83 static unsigned int fq_codel_classify(
struct sk_buff *skb,
struct Qdisc *
sch,
96 return fq_codel_hash(q, skb) + 1;
101 #ifdef CONFIG_NET_CLS_ACT
129 static inline void flow_queue_add(
struct fq_codel_flow *flow,
140 static unsigned int fq_codel_drop(
struct Qdisc *sch)
144 unsigned int maxbacklog = 0,
idx = 0,
i,
len;
159 skb = dequeue_head(flow);
160 len = qdisc_pkt_len(skb);
165 sch->
qstats.backlog -= len;
170 static int fq_codel_enqueue(
struct sk_buff *skb,
struct Qdisc *sch)
177 idx = fq_codel_classify(skb, sch, &
ret);
186 codel_set_enqueue_time(skb);
188 flow_queue_add(flow, skb);
190 sch->
qstats.backlog += qdisc_pkt_len(skb);
198 if (++sch->
q.qlen < sch->
limit)
205 if (fq_codel_drop(sch) == idx)
225 skb = dequeue_head(flow);
232 static struct sk_buff *fq_codel_dequeue(
struct Qdisc *sch)
238 u32 prev_drop_count, prev_ecn_mark;
242 if (list_empty(head)) {
244 if (list_empty(head))
255 prev_drop_count = q->
cstats.drop_count;
256 prev_ecn_mark = q->
cstats.ecn_mark;
272 qdisc_bstats_update(sch, skb);
273 flow->
deficit -= qdisc_pkt_len(skb);
277 if (q->
cstats.drop_count && sch->
q.qlen) {
284 static void fq_codel_reset(
struct Qdisc *sch)
288 while ((skb = fq_codel_dequeue(sch)) !=
NULL)
316 q->
flows_cnt = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]);
324 u64 target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]);
330 u64 interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);
336 sch->
limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
339 q->
cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
342 q->
quantum =
max(256
U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
344 while (sch->
q.qlen > sch->
limit) {
345 struct sk_buff *skb = fq_codel_dequeue(sch);
353 sch_tree_unlock(sch);
357 static void *fq_codel_zalloc(
size_t sz)
366 static void fq_codel_free(
void *
addr)
369 if (is_vmalloc_addr(addr))
376 static void fq_codel_destroy(
struct Qdisc *sch)
382 fq_codel_free(q->
flows);
385 static int fq_codel_init(
struct Qdisc *sch,
struct nlattr *opt)
390 sch->
limit = 10*1024;
392 q->
quantum = psched_mtu(qdisc_dev(sch));
396 codel_params_init(&q->
cparams);
397 codel_stats_init(&q->
cstats);
401 int err = fq_codel_change(sch, opt);
413 fq_codel_free(q->
flows);
420 codel_vars_init(&flow->
cvars);
430 static int fq_codel_dump(
struct Qdisc *sch,
struct sk_buff *skb)
437 goto nla_put_failure;
439 if (nla_put_u32(skb, TCA_FQ_CODEL_TARGET,
440 codel_time_to_us(q->
cparams.target)) ||
441 nla_put_u32(skb, TCA_FQ_CODEL_LIMIT,
443 nla_put_u32(skb, TCA_FQ_CODEL_INTERVAL,
444 codel_time_to_us(q->
cparams.interval)) ||
445 nla_put_u32(skb, TCA_FQ_CODEL_ECN,
447 nla_put_u32(skb, TCA_FQ_CODEL_QUANTUM,
449 nla_put_u32(skb, TCA_FQ_CODEL_FLOWS,
451 goto nla_put_failure;
453 nla_nest_end(skb, opts);
474 st.qdisc_stats.new_flows_len++;
477 st.qdisc_stats.old_flows_len++;
487 static unsigned long fq_codel_get(
struct Qdisc *sch,
u32 classid)
492 static unsigned long fq_codel_bind(
struct Qdisc *sch,
unsigned long parent,
500 static void fq_codel_put(
struct Qdisc *q,
unsigned long cl)
504 static struct tcf_proto **fq_codel_find_tcf(
struct Qdisc *sch,
unsigned long cl)
513 static int fq_codel_dump_class(
struct Qdisc *sch,
unsigned long cl,
520 static int fq_codel_dump_class_stats(
struct Qdisc *sch,
unsigned long cl,
528 if (idx < q->flows_cnt) {
532 memset(&xstats, 0,
sizeof(xstats));
534 xstats.class_stats.deficit = flow->
deficit;
535 xstats.class_stats.ldelay =
536 codel_time_to_us(flow->
cvars.ldelay);
537 xstats.class_stats.count = flow->
cvars.count;
538 xstats.class_stats.lastcount = flow->
cvars.lastcount;
539 xstats.class_stats.dropping = flow->
cvars.dropping;
540 if (flow->
cvars.dropping) {
544 xstats.class_stats.drop_next = (delta >= 0) ?
545 codel_time_to_us(delta) :
546 -codel_time_to_us(-delta);
557 if (idx < q->flows_cnt)
571 if (list_empty(&q->
flows[i].flowchain) ||
576 if (arg->
fn(sch, i + 1, arg) < 0) {
585 .leaf = fq_codel_leaf,
588 .tcf_chain = fq_codel_find_tcf,
589 .bind_tcf = fq_codel_bind,
590 .unbind_tcf = fq_codel_put,
591 .dump = fq_codel_dump_class,
592 .dump_stats = fq_codel_dump_class_stats,
593 .walk = fq_codel_walk,
597 .cl_ops = &fq_codel_class_ops,
600 .enqueue = fq_codel_enqueue,
601 .dequeue = fq_codel_dequeue,
602 .peek = qdisc_peek_dequeued,
603 .drop = fq_codel_drop,
604 .init = fq_codel_init,
605 .reset = fq_codel_reset,
606 .destroy = fq_codel_destroy,
607 .change = fq_codel_change,
608 .dump = fq_codel_dump,
609 .dump_stats = fq_codel_dump_stats,
613 static int __init fq_codel_module_init(
void)
618 static void __exit fq_codel_module_exit(
void)