.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * net/sched/sch_qfq.c Quick Fair Queueing Plus Scheduler. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente. |
---|
5 | 6 | * Copyright (c) 2012 Paolo Valente. |
---|
6 | | - * |
---|
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 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #include <linux/module.h> |
---|
.. | .. |
---|
217 | 214 | return container_of(clc, struct qfq_class, common); |
---|
218 | 215 | } |
---|
219 | 216 | |
---|
220 | | -static void qfq_purge_queue(struct qfq_class *cl) |
---|
221 | | -{ |
---|
222 | | - unsigned int len = cl->qdisc->q.qlen; |
---|
223 | | - unsigned int backlog = cl->qdisc->qstats.backlog; |
---|
224 | | - |
---|
225 | | - qdisc_reset(cl->qdisc); |
---|
226 | | - qdisc_tree_reduce_backlog(cl->qdisc, len, backlog); |
---|
227 | | -} |
---|
228 | | - |
---|
229 | 217 | static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = { |
---|
230 | 218 | [TCA_QFQ_WEIGHT] = { .type = NLA_U32 }, |
---|
231 | 219 | [TCA_QFQ_LMAX] = { .type = NLA_U32 }, |
---|
.. | .. |
---|
419 | 407 | return -EINVAL; |
---|
420 | 408 | } |
---|
421 | 409 | |
---|
422 | | - err = nla_parse_nested(tb, TCA_QFQ_MAX, tca[TCA_OPTIONS], qfq_policy, |
---|
423 | | - NULL); |
---|
| 410 | + err = nla_parse_nested_deprecated(tb, TCA_QFQ_MAX, tca[TCA_OPTIONS], |
---|
| 411 | + qfq_policy, NULL); |
---|
424 | 412 | if (err < 0) |
---|
425 | 413 | return err; |
---|
426 | 414 | |
---|
.. | .. |
---|
549 | 537 | |
---|
550 | 538 | sch_tree_lock(sch); |
---|
551 | 539 | |
---|
552 | | - qfq_purge_queue(cl); |
---|
| 540 | + qdisc_purge_queue(cl->qdisc); |
---|
553 | 541 | qdisc_class_hash_remove(&q->clhash, &cl->common); |
---|
554 | 542 | |
---|
555 | 543 | sch_tree_unlock(sch); |
---|
.. | .. |
---|
626 | 614 | tcm->tcm_handle = cl->common.classid; |
---|
627 | 615 | tcm->tcm_info = cl->qdisc->handle; |
---|
628 | 616 | |
---|
629 | | - nest = nla_nest_start(skb, TCA_OPTIONS); |
---|
| 617 | + nest = nla_nest_start_noflag(skb, TCA_OPTIONS); |
---|
630 | 618 | if (nest == NULL) |
---|
631 | 619 | goto nla_put_failure; |
---|
632 | 620 | if (nla_put_u32(skb, TCA_QFQ_WEIGHT, cl->agg->class_weight) || |
---|
.. | .. |
---|
653 | 641 | if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), |
---|
654 | 642 | d, NULL, &cl->bstats) < 0 || |
---|
655 | 643 | gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || |
---|
656 | | - gnet_stats_copy_queue(d, NULL, |
---|
657 | | - &cl->qdisc->qstats, cl->qdisc->q.qlen) < 0) |
---|
| 644 | + qdisc_qstats_copy(d, cl->qdisc) < 0) |
---|
658 | 645 | return -1; |
---|
659 | 646 | |
---|
660 | 647 | return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); |
---|
.. | .. |
---|
710 | 697 | case TC_ACT_STOLEN: |
---|
711 | 698 | case TC_ACT_TRAP: |
---|
712 | 699 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
---|
713 | | - /* fall through */ |
---|
| 700 | + fallthrough; |
---|
714 | 701 | case TC_ACT_SHOT: |
---|
715 | 702 | return NULL; |
---|
716 | 703 | } |
---|
.. | .. |
---|
1208 | 1195 | static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, |
---|
1209 | 1196 | struct sk_buff **to_free) |
---|
1210 | 1197 | { |
---|
| 1198 | + unsigned int len = qdisc_pkt_len(skb), gso_segs; |
---|
1211 | 1199 | struct qfq_sched *q = qdisc_priv(sch); |
---|
1212 | 1200 | struct qfq_class *cl; |
---|
1213 | 1201 | struct qfq_aggregate *agg; |
---|
1214 | 1202 | int err = 0; |
---|
| 1203 | + bool first; |
---|
1215 | 1204 | |
---|
1216 | 1205 | cl = qfq_classify(skb, sch, &err); |
---|
1217 | 1206 | if (cl == NULL) { |
---|
.. | .. |
---|
1222 | 1211 | } |
---|
1223 | 1212 | pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid); |
---|
1224 | 1213 | |
---|
1225 | | - if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) { |
---|
| 1214 | + if (unlikely(cl->agg->lmax < len)) { |
---|
1226 | 1215 | pr_debug("qfq: increasing maxpkt from %u to %u for class %u", |
---|
1227 | | - cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid); |
---|
1228 | | - err = qfq_change_agg(sch, cl, cl->agg->class_weight, |
---|
1229 | | - qdisc_pkt_len(skb)); |
---|
| 1216 | + cl->agg->lmax, len, cl->common.classid); |
---|
| 1217 | + err = qfq_change_agg(sch, cl, cl->agg->class_weight, len); |
---|
1230 | 1218 | if (err) { |
---|
1231 | 1219 | cl->qstats.drops++; |
---|
1232 | 1220 | return qdisc_drop(skb, sch, to_free); |
---|
1233 | 1221 | } |
---|
1234 | 1222 | } |
---|
1235 | 1223 | |
---|
| 1224 | + gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1; |
---|
| 1225 | + first = !cl->qdisc->q.qlen; |
---|
1236 | 1226 | err = qdisc_enqueue(skb, cl->qdisc, to_free); |
---|
1237 | 1227 | if (unlikely(err != NET_XMIT_SUCCESS)) { |
---|
1238 | 1228 | pr_debug("qfq_enqueue: enqueue failed %d\n", err); |
---|
.. | .. |
---|
1243 | 1233 | return err; |
---|
1244 | 1234 | } |
---|
1245 | 1235 | |
---|
1246 | | - bstats_update(&cl->bstats, skb); |
---|
1247 | | - qdisc_qstats_backlog_inc(sch, skb); |
---|
| 1236 | + cl->bstats.bytes += len; |
---|
| 1237 | + cl->bstats.packets += gso_segs; |
---|
| 1238 | + sch->qstats.backlog += len; |
---|
1248 | 1239 | ++sch->q.qlen; |
---|
1249 | 1240 | |
---|
1250 | 1241 | agg = cl->agg; |
---|
1251 | 1242 | /* if the queue was not empty, then done here */ |
---|
1252 | | - if (cl->qdisc->q.qlen != 1) { |
---|
| 1243 | + if (!first) { |
---|
1253 | 1244 | if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) && |
---|
1254 | 1245 | list_first_entry(&agg->active, struct qfq_class, alist) |
---|
1255 | | - == cl && cl->deficit < qdisc_pkt_len(skb)) |
---|
| 1246 | + == cl && cl->deficit < len) |
---|
1256 | 1247 | list_move_tail(&cl->alist, &agg->active); |
---|
1257 | 1248 | |
---|
1258 | 1249 | return err; |
---|
.. | .. |
---|
1467 | 1458 | qdisc_reset(cl->qdisc); |
---|
1468 | 1459 | } |
---|
1469 | 1460 | } |
---|
1470 | | - sch->qstats.backlog = 0; |
---|
1471 | | - sch->q.qlen = 0; |
---|
1472 | 1461 | } |
---|
1473 | 1462 | |
---|
1474 | 1463 | static void qfq_destroy_qdisc(struct Qdisc *sch) |
---|