| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * net/sched/sch_sfb.c Stochastic Fair Blue |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2008-2011 Juliusz Chroboczek <jch@pps.jussieu.fr> |
|---|
| 5 | 6 | * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com> |
|---|
| 6 | 7 | * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify it under the terms of the GNU General Public License |
|---|
| 9 | | - * version 2 as published by the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | 8 | * W. Feng, D. Kandlur, D. Saha, K. Shin. Blue: |
|---|
| 12 | 9 | * A New Class of Active Queue Management Algorithms. |
|---|
| 13 | 10 | * U. Michigan CSE-TR-387-99, April 1999. |
|---|
| 14 | 11 | * |
|---|
| 15 | 12 | * http://www.thefengs.com/wuchang/blue/CSE-TR-387-99.pdf |
|---|
| 16 | | - * |
|---|
| 17 | 13 | */ |
|---|
| 18 | 14 | |
|---|
| 19 | 15 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 139 | 135 | } |
|---|
| 140 | 136 | } |
|---|
| 141 | 137 | |
|---|
| 142 | | -static void increment_qlen(const struct sk_buff *skb, struct sfb_sched_data *q) |
|---|
| 138 | +static void increment_qlen(const struct sfb_skb_cb *cb, struct sfb_sched_data *q) |
|---|
| 143 | 139 | { |
|---|
| 144 | 140 | u32 sfbhash; |
|---|
| 145 | 141 | |
|---|
| 146 | | - sfbhash = sfb_hash(skb, 0); |
|---|
| 142 | + sfbhash = cb->hashes[0]; |
|---|
| 147 | 143 | if (sfbhash) |
|---|
| 148 | 144 | increment_one_qlen(sfbhash, 0, q); |
|---|
| 149 | 145 | |
|---|
| 150 | | - sfbhash = sfb_hash(skb, 1); |
|---|
| 146 | + sfbhash = cb->hashes[1]; |
|---|
| 151 | 147 | if (sfbhash) |
|---|
| 152 | 148 | increment_one_qlen(sfbhash, 1, q); |
|---|
| 153 | 149 | } |
|---|
| .. | .. |
|---|
| 269 | 265 | case TC_ACT_QUEUED: |
|---|
| 270 | 266 | case TC_ACT_TRAP: |
|---|
| 271 | 267 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
|---|
| 272 | | - /* fall through */ |
|---|
| 268 | + fallthrough; |
|---|
| 273 | 269 | case TC_ACT_SHOT: |
|---|
| 274 | 270 | return false; |
|---|
| 275 | 271 | } |
|---|
| .. | .. |
|---|
| 285 | 281 | { |
|---|
| 286 | 282 | |
|---|
| 287 | 283 | struct sfb_sched_data *q = qdisc_priv(sch); |
|---|
| 284 | + unsigned int len = qdisc_pkt_len(skb); |
|---|
| 288 | 285 | struct Qdisc *child = q->qdisc; |
|---|
| 289 | 286 | struct tcf_proto *fl; |
|---|
| 287 | + struct sfb_skb_cb cb; |
|---|
| 290 | 288 | int i; |
|---|
| 291 | 289 | u32 p_min = ~0; |
|---|
| 292 | 290 | u32 minqlen = ~0; |
|---|
| .. | .. |
|---|
| 403 | 401 | } |
|---|
| 404 | 402 | |
|---|
| 405 | 403 | enqueue: |
|---|
| 404 | + memcpy(&cb, sfb_skb_cb(skb), sizeof(cb)); |
|---|
| 406 | 405 | ret = qdisc_enqueue(skb, child, to_free); |
|---|
| 407 | 406 | if (likely(ret == NET_XMIT_SUCCESS)) { |
|---|
| 408 | | - qdisc_qstats_backlog_inc(sch, skb); |
|---|
| 407 | + sch->qstats.backlog += len; |
|---|
| 409 | 408 | sch->q.qlen++; |
|---|
| 410 | | - increment_qlen(skb, q); |
|---|
| 409 | + increment_qlen(&cb, q); |
|---|
| 411 | 410 | } else if (net_xmit_drop_count(ret)) { |
|---|
| 412 | 411 | q->stats.childdrop++; |
|---|
| 413 | 412 | qdisc_qstats_drop(sch); |
|---|
| .. | .. |
|---|
| 456 | 455 | { |
|---|
| 457 | 456 | struct sfb_sched_data *q = qdisc_priv(sch); |
|---|
| 458 | 457 | |
|---|
| 459 | | - qdisc_reset(q->qdisc); |
|---|
| 460 | | - sch->qstats.backlog = 0; |
|---|
| 461 | | - sch->q.qlen = 0; |
|---|
| 458 | + if (likely(q->qdisc)) |
|---|
| 459 | + qdisc_reset(q->qdisc); |
|---|
| 462 | 460 | q->slot = 0; |
|---|
| 463 | 461 | q->double_buffering = false; |
|---|
| 464 | 462 | sfb_zero_all_buckets(q); |
|---|
| .. | .. |
|---|
| 493 | 491 | struct netlink_ext_ack *extack) |
|---|
| 494 | 492 | { |
|---|
| 495 | 493 | struct sfb_sched_data *q = qdisc_priv(sch); |
|---|
| 496 | | - struct Qdisc *child; |
|---|
| 494 | + struct Qdisc *child, *old; |
|---|
| 497 | 495 | struct nlattr *tb[TCA_SFB_MAX + 1]; |
|---|
| 498 | 496 | const struct tc_sfb_qopt *ctl = &sfb_default_ops; |
|---|
| 499 | 497 | u32 limit; |
|---|
| 500 | 498 | int err; |
|---|
| 501 | 499 | |
|---|
| 502 | 500 | if (opt) { |
|---|
| 503 | | - err = nla_parse_nested(tb, TCA_SFB_MAX, opt, sfb_policy, NULL); |
|---|
| 501 | + err = nla_parse_nested_deprecated(tb, TCA_SFB_MAX, opt, |
|---|
| 502 | + sfb_policy, NULL); |
|---|
| 504 | 503 | if (err < 0) |
|---|
| 505 | 504 | return -EINVAL; |
|---|
| 506 | 505 | |
|---|
| .. | .. |
|---|
| 522 | 521 | qdisc_hash_add(child, true); |
|---|
| 523 | 522 | sch_tree_lock(sch); |
|---|
| 524 | 523 | |
|---|
| 525 | | - qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen, |
|---|
| 526 | | - q->qdisc->qstats.backlog); |
|---|
| 527 | | - qdisc_put(q->qdisc); |
|---|
| 524 | + qdisc_purge_queue(q->qdisc); |
|---|
| 525 | + old = q->qdisc; |
|---|
| 528 | 526 | q->qdisc = child; |
|---|
| 529 | 527 | |
|---|
| 530 | 528 | q->rehash_interval = msecs_to_jiffies(ctl->rehash_interval); |
|---|
| .. | .. |
|---|
| 547 | 545 | sfb_init_perturbation(1, q); |
|---|
| 548 | 546 | |
|---|
| 549 | 547 | sch_tree_unlock(sch); |
|---|
| 548 | + qdisc_put(old); |
|---|
| 550 | 549 | |
|---|
| 551 | 550 | return 0; |
|---|
| 552 | 551 | } |
|---|
| .. | .. |
|---|
| 582 | 581 | }; |
|---|
| 583 | 582 | |
|---|
| 584 | 583 | sch->qstats.backlog = q->qdisc->qstats.backlog; |
|---|
| 585 | | - opts = nla_nest_start(skb, TCA_OPTIONS); |
|---|
| 584 | + opts = nla_nest_start_noflag(skb, TCA_OPTIONS); |
|---|
| 586 | 585 | if (opts == NULL) |
|---|
| 587 | 586 | goto nla_put_failure; |
|---|
| 588 | 587 | if (nla_put(skb, TCA_SFB_PARMS, sizeof(opt), &opt)) |
|---|