Commit 39b02d6d authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net/sched: taprio: don't segment unnecessarily

Improve commit 497cc002 ("taprio: Handle short intervals and large
packets") to only perform segmentation when skb->len exceeds what
taprio_dequeue() expects.

In practice, this will make the biggest difference when a traffic class
gate is always open in the schedule. This is because the max_frm_len
will be U32_MAX, and such large skb->len values as Kurt reported will be
sent just fine unsegmented.

What I don't seem to know how to handle is how to make sure that the
segmented skbs themselves are smaller than the maximum frame size given
by the current queueMaxSDU[tc]. Nonetheless, we still need to drop
those, otherwise the Qdisc will hang.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Kurt Kanzenbach's avatarKurt Kanzenbach <kurt@linutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2d5e8071
...@@ -566,9 +566,6 @@ static int taprio_enqueue_one(struct sk_buff *skb, struct Qdisc *sch, ...@@ -566,9 +566,6 @@ static int taprio_enqueue_one(struct sk_buff *skb, struct Qdisc *sch,
return qdisc_drop(skb, sch, to_free); return qdisc_drop(skb, sch, to_free);
} }
if (taprio_skb_exceeds_queue_max_sdu(sch, skb))
return qdisc_drop(skb, sch, to_free);
qdisc_qstats_backlog_inc(sch, skb); qdisc_qstats_backlog_inc(sch, skb);
sch->q.qlen++; sch->q.qlen++;
...@@ -593,7 +590,14 @@ static int taprio_enqueue_segmented(struct sk_buff *skb, struct Qdisc *sch, ...@@ -593,7 +590,14 @@ static int taprio_enqueue_segmented(struct sk_buff *skb, struct Qdisc *sch,
qdisc_skb_cb(segs)->pkt_len = segs->len; qdisc_skb_cb(segs)->pkt_len = segs->len;
slen += segs->len; slen += segs->len;
ret = taprio_enqueue_one(segs, sch, child, to_free); /* FIXME: we should be segmenting to a smaller size
* rather than dropping these
*/
if (taprio_skb_exceeds_queue_max_sdu(sch, segs))
ret = qdisc_drop(segs, sch, to_free);
else
ret = taprio_enqueue_one(segs, sch, child, to_free);
if (ret != NET_XMIT_SUCCESS) { if (ret != NET_XMIT_SUCCESS) {
if (net_xmit_drop_count(ret)) if (net_xmit_drop_count(ret))
qdisc_qstats_drop(sch); qdisc_qstats_drop(sch);
...@@ -625,13 +629,18 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch, ...@@ -625,13 +629,18 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (unlikely(!child)) if (unlikely(!child))
return qdisc_drop(skb, sch, to_free); return qdisc_drop(skb, sch, to_free);
/* Large packets might not be transmitted when the transmission duration if (taprio_skb_exceeds_queue_max_sdu(sch, skb)) {
* exceeds any configured interval. Therefore, segment the skb into /* Large packets might not be transmitted when the transmission
* smaller chunks. Drivers with full offload are expected to handle * duration exceeds any configured interval. Therefore, segment
* this in hardware. * the skb into smaller chunks. Drivers with full offload are
*/ * expected to handle this in hardware.
if (skb_is_gso(skb)) */
return taprio_enqueue_segmented(skb, sch, child, to_free); if (skb_is_gso(skb))
return taprio_enqueue_segmented(skb, sch, child,
to_free);
return qdisc_drop(skb, sch, to_free);
}
return taprio_enqueue_one(skb, sch, child, to_free); return taprio_enqueue_one(skb, sch, child, to_free);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment