[Cake] cake infinite loop(?) with hfsc on one-armed router
Toke Høiland-Jørgensen
toke at toke.dk
Sat Jan 5 05:06:59 EST 2019
Pete Heist <pete at heistp.net> writes:
>> On Jan 4, 2019, at 11:34 PM, Toke Høiland-Jørgensen <toke at toke.dk> wrote:
>>
>> Pete Heist <pete at heistp.net> writes:
>>
>> This basically means that we can't use CAKE as a leaf qdisc with GSO
>> splitting as it stands currently. I *think* the solution is for CAKE to
>> notify its parents; could you try the patch below and see if it helps?
>
> Aha, good news. :)
>
> I’m probably not currently in a position to try it on my old kernels with the out of tree build:
>
> On 3.16.7:
Hmm, try this version for 3.16 - probably doesn't work on later kernels.
I'll look into a proper backport once you've confirmed that it works :)
-Toke
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index b910cd5c56f7..ef3acdbb8429 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -1617,6 +1617,44 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t,
static void cake_reconfigure(struct Qdisc *sch);
+
+static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
+{
+ struct Qdisc *q;
+
+ if (!(root->flags & TCQ_F_BUILTIN) &&
+ root->handle == handle)
+ return root;
+
+ list_for_each_entry(q, &root->list, list) {
+ if (q->handle == handle)
+ return q;
+ }
+ return NULL;
+}
+
+void adjust_parent_qlen(struct Qdisc *sch, unsigned int n,
+ unsigned int len)
+{
+ u32 parentid;
+ if (n == 0 && len == 0)
+ return;
+ rcu_read_lock();
+ while ((parentid = sch->parent)) {
+ if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS))
+ break;
+
+ sch = qdisc_match_from_root(qdisc_dev(sch), TC_H_MAJ(parentid));
+ if (sch == NULL) {
+ WARN_ON_ONCE(parentid != TC_H_ROOT);
+ break;
+ }
+ sch->q.qlen += n;
+ sch->qstats.backlog += len;
+ }
+ rcu_read_unlock();
+}
+
static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
@@ -1667,7 +1705,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) {
struct sk_buff *segs, *nskb;
netdev_features_t features = netif_skb_features(skb);
- unsigned int slen = 0;
+ unsigned int slen = 0, numsegs = 0;
segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
if (IS_ERR_OR_NULL(segs))
@@ -1684,6 +1722,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
sch->q.qlen++;
slen += segs->len;
+ numsegs++;
q->buffer_used += segs->truesize;
b->packets++;
segs = nskb;
@@ -1696,7 +1735,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
sch->qstats.backlog += slen;
q->avg_window_bytes += slen;
- qdisc_tree_reduce_backlog(sch, 1, len);
+ adjust_parent_qlen(sch, numsegs - 1, slen - len);
consume_skb(skb);
} else {
/* not splitting */
More information about the Cake
mailing list