Skip to content

Commit 78383da

Browse files
edumazetopsiff
authored andcommitted
net_sched: sch_sfq: handle bigger packets
[ Upstream commit e4650d7 ] SFQ has an assumption on dealing with packets smaller than 64KB. Even before BIG TCP, TCA_STAB can provide arbitrary big values in qdisc_pkt_len(skb) It is time to switch (struct sfq_slot)->allot to a 32bit field. sizeof(struct sfq_slot) is now 64 bytes, giving better cache locality. Signed-off-by: Eric Dumazet <[email protected]> Reviewed-by: Toke Høiland-Jørgensen <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Stable-dep-of: 1068568 ("net_sched: sch_sfq: don't allow 1 packet limit") Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 22b730a2972b29fac216f22db53ddf894028d799)
1 parent d95101b commit 78383da

File tree

1 file changed

+13
-26
lines changed

1 file changed

+13
-26
lines changed

net/sched/sch_sfq.c

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,6 @@
7777
#define SFQ_EMPTY_SLOT 0xffff
7878
#define SFQ_DEFAULT_HASH_DIVISOR 1024
7979

80-
/* We use 16 bits to store allot, and want to handle packets up to 64K
81-
* Scale allot by 8 (1<<3) so that no overflow occurs.
82-
*/
83-
#define SFQ_ALLOT_SHIFT 3
84-
#define SFQ_ALLOT_SIZE(X) DIV_ROUND_UP(X, 1 << SFQ_ALLOT_SHIFT)
85-
8680
/* This type should contain at least SFQ_MAX_DEPTH + 1 + SFQ_MAX_FLOWS values */
8781
typedef u16 sfq_index;
8882

@@ -104,7 +98,7 @@ struct sfq_slot {
10498
sfq_index next; /* next slot in sfq RR chain */
10599
struct sfq_head dep; /* anchor in dep[] chains */
106100
unsigned short hash; /* hash value (index in ht[]) */
107-
short allot; /* credit for this slot */
101+
int allot; /* credit for this slot */
108102

109103
unsigned int backlog;
110104
struct red_vars vars;
@@ -120,7 +114,6 @@ struct sfq_sched_data {
120114
siphash_key_t perturbation;
121115
u8 cur_depth; /* depth of longest slot */
122116
u8 flags;
123-
unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
124117
struct tcf_proto __rcu *filter_list;
125118
struct tcf_block *block;
126119
sfq_index *ht; /* Hash table ('divisor' slots) */
@@ -456,7 +449,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
456449
*/
457450
q->tail = slot;
458451
/* We could use a bigger initial quantum for new flows */
459-
slot->allot = q->scaled_quantum;
452+
slot->allot = q->quantum;
460453
}
461454
if (++sch->q.qlen <= q->limit)
462455
return NET_XMIT_SUCCESS;
@@ -493,7 +486,7 @@ sfq_dequeue(struct Qdisc *sch)
493486
slot = &q->slots[a];
494487
if (slot->allot <= 0) {
495488
q->tail = slot;
496-
slot->allot += q->scaled_quantum;
489+
slot->allot += q->quantum;
497490
goto next_slot;
498491
}
499492
skb = slot_dequeue_head(slot);
@@ -512,7 +505,7 @@ sfq_dequeue(struct Qdisc *sch)
512505
}
513506
q->tail->next = next_a;
514507
} else {
515-
slot->allot -= SFQ_ALLOT_SIZE(qdisc_pkt_len(skb));
508+
slot->allot -= qdisc_pkt_len(skb);
516509
}
517510
return skb;
518511
}
@@ -595,7 +588,7 @@ static void sfq_rehash(struct Qdisc *sch)
595588
q->tail->next = x;
596589
}
597590
q->tail = slot;
598-
slot->allot = q->scaled_quantum;
591+
slot->allot = q->quantum;
599592
}
600593
}
601594
sch->q.qlen -= dropped;
@@ -628,7 +621,8 @@ static void sfq_perturbation(struct timer_list *t)
628621
rcu_read_unlock();
629622
}
630623

631-
static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
624+
static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
625+
struct netlink_ext_ack *extack)
632626
{
633627
struct sfq_sched_data *q = qdisc_priv(sch);
634628
struct tc_sfq_qopt *ctl = nla_data(opt);
@@ -646,14 +640,10 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
646640
(!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
647641
return -EINVAL;
648642

649-
/* slot->allot is a short, make sure quantum is not too big. */
650-
if (ctl->quantum) {
651-
unsigned int scaled = SFQ_ALLOT_SIZE(ctl->quantum);
652-
653-
if (scaled <= 0 || scaled > SHRT_MAX)
654-
return -EINVAL;
643+
if ((int)ctl->quantum < 0) {
644+
NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
645+
return -EINVAL;
655646
}
656-
657647
if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max,
658648
ctl_v1->Wlog, ctl_v1->Scell_log, NULL))
659649
return -EINVAL;
@@ -663,10 +653,8 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
663653
return -ENOMEM;
664654
}
665655
sch_tree_lock(sch);
666-
if (ctl->quantum) {
656+
if (ctl->quantum)
667657
q->quantum = ctl->quantum;
668-
q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
669-
}
670658
WRITE_ONCE(q->perturb_period, ctl->perturb_period * HZ);
671659
if (ctl->flows)
672660
q->maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS);
@@ -762,12 +750,11 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
762750
q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
763751
q->maxflows = SFQ_DEFAULT_FLOWS;
764752
q->quantum = psched_mtu(qdisc_dev(sch));
765-
q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
766753
q->perturb_period = 0;
767754
get_random_bytes(&q->perturbation, sizeof(q->perturbation));
768755

769756
if (opt) {
770-
int err = sfq_change(sch, opt);
757+
int err = sfq_change(sch, opt, extack);
771758
if (err)
772759
return err;
773760
}
@@ -878,7 +865,7 @@ static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
878865
if (idx != SFQ_EMPTY_SLOT) {
879866
const struct sfq_slot *slot = &q->slots[idx];
880867

881-
xstats.allot = slot->allot << SFQ_ALLOT_SHIFT;
868+
xstats.allot = slot->allot;
882869
qs.qlen = slot->qlen;
883870
qs.backlog = slot->backlog;
884871
}

0 commit comments

Comments
 (0)