netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/1] taprio: Handle short intervals and large packets
@ 2021-03-18  7:34 Kurt Kanzenbach
  2021-03-18  7:34 ` [PATCH net-next 1/1] " Kurt Kanzenbach
  2021-03-19 19:10 ` [PATCH net-next 0/1] " patchwork-bot+netdevbpf
  0 siblings, 2 replies; 3+ messages in thread
From: Kurt Kanzenbach @ 2021-03-18  7:34 UTC (permalink / raw)
  To: Vinicius Costa Gomes
  Cc: Vladimir Oltean, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
	David S. Miller, Jakub Kicinski, Sebastian Andrzej Siewior,
	netdev, Kurt Kanzenbach

Hi,

there is a problem with the software implementation of TAPRIO and TCP
communication. When using short intervals e.g. below one millisecond, large
packets won't be transmitted. That's because the software implementation takes
the packet length and calculates the transmission time. If the transmission time
is larger than the configured interval, no packet will be transmitted. Fix that
by segmenting the skb for the software implementation.

Tested with software only and full hardware offloading applied using iperf3.

Vinicius, do you mind testing as well?

Changes since RFC:

 * Move segmentation, so that timestamps for tx assisted mode are
   calculated for the segments
 * Skip it for the full hardware offloading case

Previous versions:

 * https://lkml.kernel.org/netdev/20210312092823.1429-1-kurt@linutronix.de/

Kurt Kanzenbach (1):
  taprio: Handle short intervals and large packets

 net/sched/sch_taprio.c | 64 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 54 insertions(+), 10 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH net-next 1/1] taprio: Handle short intervals and large packets
  2021-03-18  7:34 [PATCH net-next 0/1] taprio: Handle short intervals and large packets Kurt Kanzenbach
@ 2021-03-18  7:34 ` Kurt Kanzenbach
  2021-03-19 19:10 ` [PATCH net-next 0/1] " patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: Kurt Kanzenbach @ 2021-03-18  7:34 UTC (permalink / raw)
  To: Vinicius Costa Gomes
  Cc: Vladimir Oltean, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
	David S. Miller, Jakub Kicinski, Sebastian Andrzej Siewior,
	netdev, Kurt Kanzenbach

When using short intervals e.g. below one millisecond, large packets won't be
transmitted at all. The software implementations checks whether the packet can
be fit into the remaining interval. Therefore, it takes the packet length and
the transmission speed into account. That is correct.

However, for large packets it may be that the transmission time exceeds the
interval resulting in no packet transmission. The same situation works fine with
hardware offloading applied.

The problem has been observed with the following schedule and iperf3:

|tc qdisc replace dev lan1 parent root handle 100 taprio \
|   num_tc 8 \
|   map 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 \
|   queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \
|   base-time $base \
|   sched-entry S 0x40 500000 \
|   sched-entry S 0xbf 500000 \
|   clockid CLOCK_TAI \
|   flags 0x00

[...]

|root@tsn:~# iperf3 -c 192.168.2.105
|Connecting to host 192.168.2.105, port 5201
|[  5] local 192.168.2.121 port 52610 connected to 192.168.2.105 port 5201
|[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
|[  5]   0.00-1.00   sec  45.2 KBytes   370 Kbits/sec    0   1.41 KBytes
|[  5]   1.00-2.00   sec  0.00 Bytes  0.00 bits/sec    0   1.41 KBytes

After debugging, it seems that the packet length stored in the SKB is about
7000-8000 bytes. Using a 100 Mbit/s link the transmission time is about 600us
which larger than the interval of 500us.

Therefore, segment the SKB into smaller chunks if the packet is too big. This
yields similar results than the hardware offload:

|root@tsn:~# iperf3 -c 192.168.2.105
|Connecting to host 192.168.2.105, port 5201
|- - - - - - - - - - - - - - - - - - - - - - - - -
|[ ID] Interval           Transfer     Bitrate         Retr
|[  5]   0.00-10.00  sec  48.9 MBytes  41.0 Mbits/sec    0             sender
|[  5]   0.00-10.02  sec  48.7 MBytes  40.7 Mbits/sec                  receiver

Furthermore, the segmentation can be skipped for the full offload case, as the
driver or the hardware is expected to handle this.

Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
---
 net/sched/sch_taprio.c | 64 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 54 insertions(+), 10 deletions(-)

diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
index 8287894541e3..922ed6b91abb 100644
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -411,18 +411,10 @@ static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
 	return txtime;
 }
 
-static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
-			  struct sk_buff **to_free)
+static int taprio_enqueue_one(struct sk_buff *skb, struct Qdisc *sch,
+			      struct Qdisc *child, struct sk_buff **to_free)
 {
 	struct taprio_sched *q = qdisc_priv(sch);
-	struct Qdisc *child;
-	int queue;
-
-	queue = skb_get_queue_mapping(skb);
-
-	child = q->qdiscs[queue];
-	if (unlikely(!child))
-		return qdisc_drop(skb, sch, to_free);
 
 	if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
 		if (!is_valid_interval(skb, sch))
@@ -439,6 +431,58 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 	return qdisc_enqueue(skb, child, to_free);
 }
 
+static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+			  struct sk_buff **to_free)
+{
+	struct taprio_sched *q = qdisc_priv(sch);
+	struct Qdisc *child;
+	int queue;
+
+	queue = skb_get_queue_mapping(skb);
+
+	child = q->qdiscs[queue];
+	if (unlikely(!child))
+		return qdisc_drop(skb, sch, to_free);
+
+	/* Large packets might not be transmitted when the transmission duration
+	 * exceeds any configured interval. Therefore, segment the skb into
+	 * smaller chunks. Skip it for the full offload case, as the driver
+	 * and/or the hardware is expected to handle this.
+	 */
+	if (skb_is_gso(skb) && !FULL_OFFLOAD_IS_ENABLED(q->flags)) {
+		unsigned int slen = 0, numsegs = 0, len = qdisc_pkt_len(skb);
+		netdev_features_t features = netif_skb_features(skb);
+		struct sk_buff *segs, *nskb;
+		int ret;
+
+		segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+		if (IS_ERR_OR_NULL(segs))
+			return qdisc_drop(skb, sch, to_free);
+
+		skb_list_walk_safe(segs, segs, nskb) {
+			skb_mark_not_on_list(segs);
+			qdisc_skb_cb(segs)->pkt_len = segs->len;
+			slen += segs->len;
+
+			ret = taprio_enqueue_one(segs, sch, child, to_free);
+			if (ret != NET_XMIT_SUCCESS) {
+				if (net_xmit_drop_count(ret))
+					qdisc_qstats_drop(sch);
+			} else {
+				numsegs++;
+			}
+		}
+
+		if (numsegs > 1)
+			qdisc_tree_reduce_backlog(sch, 1 - numsegs, len - slen);
+		consume_skb(skb);
+
+		return numsegs > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
+	}
+
+	return taprio_enqueue_one(skb, sch, child, to_free);
+}
+
 static struct sk_buff *taprio_peek_soft(struct Qdisc *sch)
 {
 	struct taprio_sched *q = qdisc_priv(sch);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next 0/1] taprio: Handle short intervals and large packets
  2021-03-18  7:34 [PATCH net-next 0/1] taprio: Handle short intervals and large packets Kurt Kanzenbach
  2021-03-18  7:34 ` [PATCH net-next 1/1] " Kurt Kanzenbach
@ 2021-03-19 19:10 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-03-19 19:10 UTC (permalink / raw)
  To: Kurt Kanzenbach
  Cc: vinicius.gomes, olteanv, jhs, xiyou.wangcong, jiri, davem, kuba,
	bigeasy, netdev

Hello:

This patch was applied to netdev/net-next.git (refs/heads/master):

On Thu, 18 Mar 2021 08:34:54 +0100 you wrote:
> Hi,
> 
> there is a problem with the software implementation of TAPRIO and TCP
> communication. When using short intervals e.g. below one millisecond, large
> packets won't be transmitted. That's because the software implementation takes
> the packet length and calculates the transmission time. If the transmission time
> is larger than the configured interval, no packet will be transmitted. Fix that
> by segmenting the skb for the software implementation.
> 
> [...]

Here is the summary with links:
  - [net-next,1/1] taprio: Handle short intervals and large packets
    https://git.kernel.org/netdev/net-next/c/497cc00224cf

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-03-19 19:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-18  7:34 [PATCH net-next 0/1] taprio: Handle short intervals and large packets Kurt Kanzenbach
2021-03-18  7:34 ` [PATCH net-next 1/1] " Kurt Kanzenbach
2021-03-19 19:10 ` [PATCH net-next 0/1] " patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).