.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Fair Queue CoDel discipline |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version |
---|
7 | | - * 2 of the License, or (at your option) any later version. |
---|
8 | 4 | * |
---|
9 | 5 | * Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com> |
---|
10 | 6 | */ |
---|
.. | .. |
---|
18 | 14 | #include <linux/errno.h> |
---|
19 | 15 | #include <linux/init.h> |
---|
20 | 16 | #include <linux/skbuff.h> |
---|
21 | | -#include <linux/jhash.h> |
---|
22 | 17 | #include <linux/slab.h> |
---|
23 | 18 | #include <linux/vmalloc.h> |
---|
24 | 19 | #include <net/netlink.h> |
---|
.. | .. |
---|
49 | 44 | struct sk_buff *tail; |
---|
50 | 45 | struct list_head flowchain; |
---|
51 | 46 | int deficit; |
---|
52 | | - u32 dropped; /* number of drops (or ECN marks) on this flow */ |
---|
53 | 47 | struct codel_vars cvars; |
---|
54 | 48 | }; /* please try to keep this structure <= 64 bytes */ |
---|
55 | 49 | |
---|
.. | .. |
---|
105 | 99 | case TC_ACT_QUEUED: |
---|
106 | 100 | case TC_ACT_TRAP: |
---|
107 | 101 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
---|
108 | | - /* fall through */ |
---|
| 102 | + fallthrough; |
---|
109 | 103 | case TC_ACT_SHOT: |
---|
110 | 104 | return 0; |
---|
111 | 105 | } |
---|
.. | .. |
---|
124 | 118 | struct sk_buff *skb = flow->head; |
---|
125 | 119 | |
---|
126 | 120 | flow->head = skb->next; |
---|
127 | | - skb->next = NULL; |
---|
| 121 | + skb_mark_not_on_list(skb); |
---|
128 | 122 | return skb; |
---|
129 | 123 | } |
---|
130 | 124 | |
---|
.. | .. |
---|
177 | 171 | __qdisc_drop(skb, to_free); |
---|
178 | 172 | } while (++i < max_packets && len < threshold); |
---|
179 | 173 | |
---|
180 | | - flow->dropped += i; |
---|
| 174 | + /* Tell codel to increase its signal strength also */ |
---|
| 175 | + flow->cvars.count += i; |
---|
181 | 176 | q->backlogs[idx] -= len; |
---|
182 | 177 | q->memory_usage -= mem; |
---|
183 | 178 | sch->qstats.drops += i; |
---|
.. | .. |
---|
192 | 187 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
---|
193 | 188 | unsigned int idx, prev_backlog, prev_qlen; |
---|
194 | 189 | struct fq_codel_flow *flow; |
---|
195 | | - int uninitialized_var(ret); |
---|
| 190 | + int ret; |
---|
196 | 191 | unsigned int pkt_len; |
---|
197 | 192 | bool memory_limited; |
---|
198 | 193 | |
---|
.. | .. |
---|
215 | 210 | list_add_tail(&flow->flowchain, &q->new_flows); |
---|
216 | 211 | q->new_flow_count++; |
---|
217 | 212 | flow->deficit = q->quantum; |
---|
218 | | - flow->dropped = 0; |
---|
219 | 213 | } |
---|
220 | 214 | get_codel_cb(skb)->mem_usage = skb->truesize; |
---|
221 | 215 | q->memory_usage += get_codel_cb(skb)->mem_usage; |
---|
.. | .. |
---|
290 | 284 | struct sk_buff *skb; |
---|
291 | 285 | struct fq_codel_flow *flow; |
---|
292 | 286 | struct list_head *head; |
---|
293 | | - u32 prev_drop_count, prev_ecn_mark; |
---|
294 | 287 | |
---|
295 | 288 | begin: |
---|
296 | 289 | head = &q->new_flows; |
---|
.. | .. |
---|
307 | 300 | goto begin; |
---|
308 | 301 | } |
---|
309 | 302 | |
---|
310 | | - prev_drop_count = q->cstats.drop_count; |
---|
311 | | - prev_ecn_mark = q->cstats.ecn_mark; |
---|
312 | | - |
---|
313 | 303 | skb = codel_dequeue(sch, &sch->qstats.backlog, &q->cparams, |
---|
314 | 304 | &flow->cvars, &q->cstats, qdisc_pkt_len, |
---|
315 | 305 | codel_get_enqueue_time, drop_func, dequeue_func); |
---|
316 | | - |
---|
317 | | - flow->dropped += q->cstats.drop_count - prev_drop_count; |
---|
318 | | - flow->dropped += q->cstats.ecn_mark - prev_ecn_mark; |
---|
319 | 306 | |
---|
320 | 307 | if (!skb) { |
---|
321 | 308 | /* force a pass through old_flows to prevent starvation */ |
---|
.. | .. |
---|
360 | 347 | codel_vars_init(&flow->cvars); |
---|
361 | 348 | } |
---|
362 | 349 | memset(q->backlogs, 0, q->flows_cnt * sizeof(u32)); |
---|
363 | | - sch->q.qlen = 0; |
---|
364 | | - sch->qstats.backlog = 0; |
---|
365 | 350 | q->memory_usage = 0; |
---|
366 | 351 | } |
---|
367 | 352 | |
---|
.. | .. |
---|
388 | 373 | if (!opt) |
---|
389 | 374 | return -EINVAL; |
---|
390 | 375 | |
---|
391 | | - err = nla_parse_nested(tb, TCA_FQ_CODEL_MAX, opt, fq_codel_policy, |
---|
392 | | - NULL); |
---|
| 376 | + err = nla_parse_nested_deprecated(tb, TCA_FQ_CODEL_MAX, opt, |
---|
| 377 | + fq_codel_policy, NULL); |
---|
393 | 378 | if (err < 0) |
---|
394 | 379 | return err; |
---|
395 | 380 | if (tb[TCA_FQ_CODEL_FLOWS]) { |
---|
.. | .. |
---|
535 | 520 | struct fq_codel_sched_data *q = qdisc_priv(sch); |
---|
536 | 521 | struct nlattr *opts; |
---|
537 | 522 | |
---|
538 | | - opts = nla_nest_start(skb, TCA_OPTIONS); |
---|
| 523 | + opts = nla_nest_start_noflag(skb, TCA_OPTIONS); |
---|
539 | 524 | if (opts == NULL) |
---|
540 | 525 | goto nla_put_failure; |
---|
541 | 526 | |
---|
.. | .. |
---|
670 | 655 | sch_tree_unlock(sch); |
---|
671 | 656 | } |
---|
672 | 657 | qs.backlog = q->backlogs[idx]; |
---|
673 | | - qs.drops = flow->dropped; |
---|
| 658 | + qs.drops = 0; |
---|
674 | 659 | } |
---|
675 | 660 | if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0) |
---|
676 | 661 | return -1; |
---|
.. | .. |
---|
742 | 727 | module_exit(fq_codel_module_exit) |
---|
743 | 728 | MODULE_AUTHOR("Eric Dumazet"); |
---|
744 | 729 | MODULE_LICENSE("GPL"); |
---|
| 730 | +MODULE_DESCRIPTION("Fair Queue CoDel discipline"); |
---|