Skip to contentSkip to conversation

TSO Reloaded

PATCH In review David S. Miller 7 participants 26 messages May 5, 2005 – May 18, 2005 1 message not in the archive

Subsystems (4)
lore
Share & tools
lore

David S. Miller

author maintainer
#0 lore raw

PATCH 1/1 TSO Reloaded

Ok, here it is, first draft of the new TSO handling I promised so long ago :-) I was lazy and waited until today to implement the entire thing.

It works with basic testing over tg3.

I'll discuss the changes in more detail tomorrow, but the only potentially sore spot right now is the tcp_push_one() avoidance done in tcp_sendmsg() and tcp_sendpages(). It may need to be changed to do so mething like "if not TSO then tcp_push_one(), else wait for N packets to accumulate" where N is configurable or dynamically measured in some way.

It would be nice to know that this thing works with e1000 and other TSO capable cards, also I did not do much sendfile() testing at all.

Thanks.

include/linux/tcp.h renamed from include/linux/tcp.h.~1~ +1 -2
@@ -280,8 +280,7 @@ struct tcp_sock {
 	__u32	snd_wnd;	/* The window we expect to receive	*/
 	__u32	max_window;	/* Maximal window ever seen from peer	*/
 	__u32	pmtu_cookie;	/* Last pmtu seen by socket		*/
-	__u32	mss_cache;	/* Cached effective mss, not including SACKS */
-	__u16	mss_cache_std;	/* Like mss_cache, but without TSO */
+	__u16	mss_cache;	/* Cached effective mss, not including SACKS */
 	__u16	ext_header_len;	/* Network protocol overhead (IP/IPv6 options) */
 	__u8	ca_state;	/* State of fast-retransmit machine 	*/
 	__u8	retransmits;	/* Number of unrecovered RTO timeouts.	*/
include/net/tcp.h renamed from include/net/tcp.h.~1~ +65 -91

223 lines not on this page · raw message

include/net/sock.h renamed from include/net/sock.h.~1~ +5 -2
@@ -1128,13 +1128,16 @@ static inline void sk_stream_moderate_sn
 static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
 						   int size, int mem, int gfp)
 {
-	struct sk_buff *skb = alloc_skb(size + sk->sk_prot->max_header, gfp);
+	struct sk_buff *skb;
+	int hdr_len;
 
+	hdr_len = SKB_DATA_ALIGN(sk->sk_prot->max_header);
+	skb = alloc_skb(size + hdr_len, gfp);
 	if (skb) {
 		skb->truesize += mem;
 		if (sk->sk_forward_alloc >= (int)skb->truesize ||
 		    sk_stream_mem_schedule(sk, skb->truesize, 0)) {
-			skb_reserve(skb, sk->sk_prot->max_header);
+			skb_reserve(skb, hdr_len);
 			return skb;
 		}
 		__kfree_skb(skb);
net/ipv4/tcp_output.c renamed from net/ipv4/tcp_output.c.~1~ +325 -246

794 lines not on this page · raw message

net/ipv4/tcp_input.c renamed from net/ipv4/tcp_input.c.~1~ +33 -110

296 lines not on this page · raw message

net/ipv4/tcp.c renamed from net/ipv4/tcp.c.~1~ +31 -19

118 lines not on this page · raw message

net/ipv4/tcp_ipv4.c renamed from net/ipv4/tcp_ipv4.c.~1~ +1 -1
@@ -2060,7 +2060,7 @@ static int tcp_v4_init_sock(struct sock 
 	 */
 	tp->snd_ssthresh = 0x7fffffff;	/* Infinity */
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache_std = tp->mss_cache = 536;
+	tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
net/ipv6/tcp_ipv6.c renamed from net/ipv6/tcp_ipv6.c.~1~ +1 -1
@@ -2021,7 +2021,7 @@ static int tcp_v6_init_sock(struct sock 
 	 */
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache_std = tp->mss_cache = 536;
+	tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
author maintainer
#1 lore raw

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

#2 lore raw
Quoted 6 lines · David S. Miller

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

I can give it a quick sniff on e1000 and r8169 (on amd64), though only to verify that its works (ie, no real perf). Is that acceptable?

Thanks,
Jon

A message that is not in the archive (sent off-list or not yet received): [email protected]

#4 lore raw
Quoted 7 lines · David S. Miller

On Thu, 5 May 2005 17:56:25 -0500

Quoted 2 lines · Jon Mason

I can give it a quick sniff on e1000 and r8169 (on amd64), though only to verify that its works (ie, no real perf). Is that acceptable?

Yes.

It worked fine for both r8169 and e1000 on my amd64 box (running 2.6.12-rc3-mm2).

#5 lore raw
In reply to David S. Miller
Quoted 6 lines

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

When I can get my machines booting to userspace Im definitely going to try it out :)

Anton

author maintainer
#6 lore raw
Quoted 9 lines · On Fri, 6 May 2005 09:11:41 +1000 Anton Blanchard <[email protected]> wrote:
Quoted 6 lines

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

When I can get my machines booting to userspace Im definitely going to try it out :)

Do you need anything besides that early-packet fix from Herbert?

#7 lore raw
Quoted 3 lines

Do you need anything besides that early-packet fix from Herbert?

Nope. I'll spin the patch up now and report back.

Anton

#8 lore raw
In reply to David S. Miller
Quoted 6 lines · On Thu, 5 May 2005 15:35:32 -0700 "David S. Miller" <[email protected]> wrote:

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

It works on tg3 that is too stupid to do TSO at least. More tests coming

author maintainer
#9 lore raw
Quoted 11 lines · On Thu, 5 May 2005 16:24:48 -0700 Stephen Hemminger <[email protected]> wrote:
Quoted 6 lines · On Thu, 5 May 2005 15:35:32 -0700 "David S. Miller" <[email protected]> wrote:

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

It works on tg3 that is too stupid to do TSO at least. More tests coming

It's off by default, "ethtool -K eth0 tso on" is necessary. I'll change that soon.

Or do you have a chip revision that really can't do TSO?

#10 lore raw
In reply to David S. Miller
Quoted 6 lines · David S. Miller

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

It's in the queue, Dave :).
Let you know if there are problems...

thanks,
Nivedita

#11 lore raw
In reply to David S. Miller

We will be testing on 10GbE NICs in the next couple weeks; will let you know.
BTW - any plans for IPv6 support?

Quoted 13 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of David S. Miller
Sent: Thursday, May 05, 2005 3:36 PM
To: [email protected]
Subject: Re: [PATCH] TSO Reloaded

Is anyone testing this or is everyone too scared? :-)

A lot of people wanted this TSO stuff fixed, so I spent time implementing the fix. Yet nobody seems interested enough to even say "it works" or "it's busted" :-/

author maintainer
#12 lore raw
Quoted 3 lines · On Thu, 5 May 2005 20:20:56 -0700 "Leonid Grossman"…

We will be testing on 10GbE NICs in the next couple weeks; will let you know.
BTW - any plans for IPv6 support?

What exactly does your NIC expect? Do you use the NETIF_F_HW_CSUM flag to indicate generic checksumming support? Otherwise, there is no other way to support ipv6 checksum offload at the moment, and that is a requirement for ipv6 TSO.

For TSO, the ipv6 header handling seems very non-trivial. What is supposed to happen in cases where certain optional extension headers should be present in some of the frames but not the others?

A specification of how your NIC support ipv6 TSO is necessary in order for support to be written, see? Seems like you are the most qualified person to write the support, therefore :-) Really, it isn't that hard and you have something on which to test whatever you write, whereas I don't.

#13 lore raw
Quoted 21 lines

-----Original Message-----
From: David S. Miller [mailto:[email protected]]
Sent: Thursday, May 05, 2005 8:31 PM
To: Leonid Grossman
Cc: [email protected]
Subject: Re: [PATCH] TSO Reloaded

Quoted 3 lines · On Thu, 5 May 2005 20:20:56 -0700 "Leonid Grossman"…

We will be testing on 10GbE NICs in the next couple weeks; will let you know.
BTW - any plans for IPv6 support?

What exactly does your NIC expect? Do you use the NETIF_F_HW_CSUM flag to indicate generic checksumming support? Otherwise, there is no other way to support ipv6 checksum offload at the moment, and that is a requirement for ipv6 TSO.

Quoted 4 lines

For TSO, the ipv6 header handling seems very non-trivial. What is supposed to happen in cases where certain optional extension headers should be present in some of the frames but not the others?

Our ASIC supports ipv6 CSUM and TSO (and header splitting) even if extension headers are present, but I suspect the majority ipv6-capable NICs will not implement this; the stack needs to query NIC header-processing capabilities (for both CSUM and TSO) and act accordingly.

Quoted 3 lines

A specification of how your NIC support ipv6 TSO is necessary in order for support to be written, see?

We are planning to release the ASIC programming manual to the community fairly soon, this will provide a better view on IPv6 LSO and some other features.

Quoted 4 lines

Seems like you are
the most qualified person to write the support, therefore :-) Really, it isn't that hard and you have something on which to test whatever you write, whereas I don't.

We will probably get to it sometime down the road; at the moment support for UDP LSO and receive side offloads are much higher on our list.

Getting a vanilla (no support for extension headers) implementation from someone who knows the stack better than we do would be a good thing :-), I suspect this should be useful for more than one NIC vendor.

Leonid

#14 lore raw
In reply to David S. Miller

Hi Dave,

Quoted 3 lines

Ok, here it is, first draft of the new TSO handling I promised so long ago :-) I was lazy and waited until today to implement the entire thing.

I fired off socklib (just a TCP stream test) and things look much better. I dumped the size of the data+frags for each packet that the e1000 created. It looks like frags are working in multiples of MTU, but we also have to split when we hit page boundaries. Is this expected?

BTW the 4 bytes at the end is due to an e1000 workaround for a hw bug.

Thanks for working on this :)

Anton

data: 42 frags:
data: 74 frags:
data: 66 frags: 1448 1444 4
data: 66 frags: 1024 424 1444 4
data: 66 frags: 1448 512 932 4
data: 66 frags: 1448 1444 4
data: 66 frags: 1448
data: 66 frags: 1448 1024 424 1448 1448 512 936 1444 4
data: 66 frags: 1448 1444 4
data: 66 frags: 1448 1024 420 4
data: 66 frags: 1448 1444 4
data: 66 frags: 512 936 1448 1448 1448 1448 1024 424 1448 1448 512 936 1444 4
data: 66 frags: 1448 1448 1444 4
data: 66 frags: 1024 424 1448 1448 512 936 1448 1448 1444 4
data: 66 frags: 1448 1024 424 1448 1448 372 4
data: 66 frags: 128 1320 1448 1152 296 1448 1448 640 808 1444 4
data: 66 frags: 1448 128 1320 1444 4
data: 66 frags: 1152 296 1448 1448 640 804 4
data: 66 frags: 1448 1448 128 1316 4
data: 66 frags: 1448 1152 296 1444 4
data: 66 frags: 1448 640 808 1448 1448 128 1320 1448 1152 296 1448 1448 640 808 1448 1444 4
data: 66 frags: 128 1320 1448 1152 296 1448 1444 4
data: 66 frags: 640 808 1448 1444 4
data: 66 frags: 128 1320 1448 1152 296 1448 1448 372 4
data: 66 frags: 256 1192 1448 1280 168 1448 1448 768 680 1448 1448 256 1192 1448 1280 168 1444 4
data: 66 frags: 1448 768 680 1448 1444 4
data: 66 frags: 256 1192 1448 1280 168 1448 1444 4

#15 lore raw

Hi,

With a 9000 byte MTU I see page sized frags as expected. There are still some pages broken in two which is interesting.

Anton

data: 66 frags: 3584 4096 1268 2816 4096 2032 4
data: 66 frags: 2048 4096 2804 1280 4096 3568 4
data: 66 frags: 512 4096 4096 244 3840 4096 1008 4
data: 66 frags: 3072 4096 1780 2304 4096 2544 4
data: 66 frags: 1536 4096 3316 768 4096 4080 4
data: 66 frags: 4096 4096 756 3328 4096 1520 4
data: 66 frags: 2560 4096 2292 1792 4096 3056 4
data: 66 frags: 1024 4096 3828 256 4096 4096 496 4
data: 66 frags: 3584 4096 1268 2816 4096 2032 4
data: 66 frags: 2048 4096 2804 1280 4096 3568 4
data: 66 frags: 512 4096 4096 244 3840 4096 1008 4
data: 66 frags: 3072 4096 1780 2304 4096 2544 4
data: 66 frags: 1536 4096 3316 768 4096 4080 4
data: 66 frags: 4096 4096 756 3328 4096 1520 4
data: 66 frags: 2560 4096 2292 1792 4096 3056 4
data: 66 frags: 1024 4096 3828 256 4096 4096 496 4
data: 66 frags: 3584 4096 1268 2816 4096 2032 4

author maintainer
#16 lore raw
Quoted 2 lines · On Fri, 6 May 2005 15:45:16 +1000 Anton Blanchard <[email protected]> wrote:

With a 9000 byte MTU I see page sized frags as expected. There are still some pages broken in two which is interesting.

I know what is causing the breaks, it's the "cache line align" crap in tcp_sendmsg().

Comment out this alignment code in net/ipv4/tcp.c and see how it goes:

					/* If page is cached, align
					 * offset to L1 cache boundary
					 */
					off = (off + L1_CACHE_BYTES - 1) &
					      ~(L1_CACHE_BYTES - 1);

This alignment causes TSO coalescing to fail at these spots.

You should not see this effect when sendfile() is used for the transfer.

#17 lore raw
Quoted 12 lines

I know what is causing the breaks, it's the "cache line align" crap in tcp_sendmsg().

Comment out this alignment code in net/ipv4/tcp.c and see how it goes:

					/* If page is cached, align
					 * offset to L1 cache boundary
					 */
					off = (off + L1_CACHE_BYTES - 1) &
					      ~(L1_CACHE_BYTES - 1);
Quoted 4 lines

This alignment causes TSO coalescing to fail at these spots.

You should not see this effect when sendfile() is used for the transfer.

Nice work! Its looking much better now.

Anton

1500 MTU:
eth0 data: 74 frags:
eth0 data: 66 frags: 2892 4
eth0 data: 66 frags: 1200 1692 4
eth0 data: 66 frags: 2400 492 4
eth0 data: 66 frags: 2892 4
eth0 data: 66 frags: 704 744
eth0 data: 66 frags: 3352 4096 1236 4
eth0 data: 66 frags: 2856 36 4

1500 MTU+sendfile:
eth0 data: 74 frags:
eth0 data: 66 frags: 2892 4
eth0 data: 66 frags: 1200 1692 4
eth0 data: 66 frags: 2400 492 4
eth0 data: 66 frags: 2892 4
eth0 data: 66 frags: 704 744
eth0 data: 66 frags: 3348 4
eth0 data: 66 frags: 4092 4

9000 MTU:
eth0 data: 74 frags:
eth0 data: 66 frags: 4096 4096 4096 4096 1508 4
eth0 data: 66 frags: 2584 4096 2268
eth0 data: 66 frags: 1828 4096 3024
eth0 data: 66 frags: 1072 4096 4096 4096 4096 4096 4096 1192 4 eth0 data: 66 frags: 2900 4096 4096 4096 2704 4
eth0 data: 66 frags: 1388 4096 3464
eth0 data: 66 frags: 632 4096 4096 4096 4096 876 4

9000 MTU+sendfile:
eth0 data: 74 frags:
eth0 data: 66 frags: 4096 4096 4092 4
eth0 data: 66 frags: 4096 4096 4096 4096 1508 4 eth0 data: 66 frags: 2584 4096 4092 4
eth0 data: 66 frags: 4096 4096 4096 4096 1508 4 eth0 data: 66 frags: 2584 4096 4096 4096 3020 4 eth0 data: 66 frags: 1072 4096 4096 4096 4096 436 4 eth0 data: 66 frags: 3656 4096 4096 4096 1948 4

author maintainer
#18 lore raw
Quoted 1 line · On Fri, 6 May 2005 17:10:05 +1000 Anton Blanchard <[email protected]> wrote:

Nice work! Its looking much better now.

Great, thanks for testing.

BTW:

Quoted 1 line

eth0 data: 66 frags: 2892 4

What does this "66 frags" mean? Is it "tso_segs" from the SKB? skb_shinfo(skb)->nr_frags can never be that large (MAX_SKB_FRAGS is (65536/PAGE_SIZE + 2)) so it can't be that.

#19 lore raw
Quoted 7 lines
Quoted 2 lines

eth0 data: 66 frags: 2892 4

What does this "66 frags" mean? Is it "tso_segs" from the SKB? skb_shinfo(skb)->nr_frags can never be that large (MAX_SKB_FRAGS is (65536/PAGE_SIZE + 2)) so it can't be that.

Nah I just dump the skb mapping then the subsequent frags. So 66 is the size of the header. In this case there is only 2 frags.

Anton

#20 lore raw
In reply to David S. Miller

Though it may be moot by now, I just ran some tests of my own with this patch. This was on a dual 2.4 GHz Xeon booted with a UP kernel, running iperf over an e1000 at a 1500 byte MTU. I measured idle CPU by running a process which sits in a gettimeofday() loop. Numbers are CPU utilization, all turned out +/- 1%.

No TSO:  86.6%
Old TSO: 61.0%
New TSO: 88.5%

-John

author maintainer
#21 lore raw

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 22:26:09 -0400

Quoted 9 lines

Though it may be moot by now, I just ran some tests of my own with this patch. This was on a dual 2.4 GHz Xeon booted with a UP kernel, running iperf over an e1000 at a 1500 byte MTU. I measured idle CPU by running a process which sits in a gettimeofday() loop. Numbers are CPU utilization, all turned out +/- 1%.

No TSO:  86.6%
Old TSO: 61.0%
New TSO: 88.5%

Yeah, TSO Reloaded really stinks. :-)

Try the "Super TSO" patch I just posted instead.

#22 lore raw
Quoted 9 lines · David S. Miller

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 22:26:09 -0400

Quoted 6 lines

Though it may be moot by now, I just ran some tests of my own with this patch. This was on a dual 2.4 GHz Xeon booted with a UP kernel, running iperf over an e1000 at a 1500 byte MTU. I measured idle CPU by running a process which sits in a gettimeofday() loop. Numbers are CPU utilization, all turned out +/- 1%.

Quoted 7 lines
Quoted 3 lines
No TSO:  86.6%
Old TSO: 61.0%
New TSO: 88.5%

Yeah, TSO Reloaded really stinks. :-)

Try the "Super TSO" patch I just posted instead.

Interesting timing. :)
With the new patch I'm getting 78.0%.

-John

author maintainer
#23 lore raw

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 22:51:53 -0400

Quoted 9 lines · David S. Miller
Quoted 8 lines

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 22:26:09 -0400

Quoted 3 lines
No TSO:  86.6%
Old TSO: 61.0%
New TSO: 88.5%
Quoted 6 lines
Quoted 3 lines

Yeah, TSO Reloaded really stinks. :-)

Try the "Super TSO" patch I just posted instead.

Interesting timing. :)
With the new patch I'm getting 78.0%.

Thanks for testing.

I actually expected the new code to do better. Splitting could be a little bit expensive, but that only occurs at the beginning of the connection as we ramp up the congestion and send window. Afterwards, we should be able to release full unsplit TSO frames onto the wire.

#24 lore raw
Quoted 5 lines · David S. Miller

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 22:51:53 -0400

Quoted 1 line

With the new patch I'm getting 78.0%.

Quoted 8 lines

Thanks for testing.

I actually expected the new code to do better. Splitting could be a little bit expensive, but that only occurs at the beginning of the connection as we ramp up the congestion and send window. Afterwards, we should be able to release full unsplit TSO frames onto the wire.

With different (larger than default) buffer sizes, I'm getting 63.4%. Not surprising I guess.

-John

author maintainer
#25 lore raw

From: John Heffner <[email protected]>
Date: Tue, 17 May 2005 23:47:48 -0400

Quoted 11 lines · David S. Miller
Quoted 7 lines

I actually expected the new code to do better. Splitting could be a little bit expensive, but that only occurs at the beginning of the connection as we ramp up the congestion and send window. Afterwards, we should be able to release full unsplit TSO frames onto the wire.

With different (larger than default) buffer sizes, I'm getting 63.4%. Not surprising I guess.

Thanks for the data.

How long are your transfers? Just curious.

I think what I need to investigate is some kind of light cwnd prediction. This, plus some TSO packet coalescing logic when we undershoot, should do the trick.

But first I'll study the segmenting behavior of the current code. It could be simply a matter of tweaking when we wake up the user when he sleeps on the send buffer filling up.

#26 lore raw
Quoted 4 lines · David S. Miller

Thanks for the data.

How long are your transfers? Just curious.

I was actually measuring 10 second intervals in the middle of a long running flow.

-John