aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2011-04-05 01:30:30 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-05 01:30:30 -0400
commitc6e1a0d12ca7b4f22c58e55a16beacfb7d3d8462 (patch)
tree6955c20538050329d0bdffdf24a787507ae6fdf1 /net
parent14f98f258f1936e0dba77474bd7eda63f61a9826 (diff)
net: Allow no-cache copy from user on transmit
This patch uses __copy_from_user_nocache on transmit to bypass data cache for a performance improvement. skb_add_data_nocache and skb_copy_to_page_nocache can be called by sendmsg functions to use this feature, initial support is in tcp_sendmsg. This functionality is configurable per device using ethtool. Presumably, this feature would only be useful when the driver does not touch the data. The feature is turned on by default if a device indicates that it does some form of checksum offload; it is off by default for devices that do no checksum offload or indicate no checksum is necessary. For the former case copy-checksum is probably done anyway, in the latter case the device is likely loopback in which case the no cache copy is probably not beneficial. This patch was tested using 200 instances of netperf TCP_RR with 1400 byte request and one byte reply. Platform is 16 core AMD x86. No-cache copy disabled: 672703 tps, 97.13% utilization 50/90/99% latency:244.31 484.205 1028.41 No-cache copy enabled: 702113 tps, 96.16% utilization, 50/90/99% latency 238.56 467.56 956.955 Using 14000 byte request and response sizes demonstrate the effects more dramatically: No-cache copy disabled: 79571 tps, 34.34 %utlization 50/90/95% latency 1584.46 2319.59 5001.76 No-cache copy enabled: 83856 tps, 34.81% utilization 50/90/95% latency 2508.42 2622.62 2735.88 Note especially the effect on latency tail (95th percentile). This seems to provide a nice performance improvement and is consistent in the tests I ran. Presumably, this would provide the greatest benfits in the presence of an application workload stressing the cache and a lot of transmit data happening. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c12
-rw-r--r--net/core/ethtool.c2
-rw-r--r--net/ipv4/tcp.c7
3 files changed, 17 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 02f56376fe99..5d0b4f6f1a72 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5425,6 +5425,14 @@ int register_netdevice(struct net_device *dev)
5425 dev->features &= ~NETIF_F_GSO; 5425 dev->features &= ~NETIF_F_GSO;
5426 } 5426 }
5427 5427
5428 /* Turn on no cache copy if HW is doing checksum */
5429 dev->hw_features |= NETIF_F_NOCACHE_COPY;
5430 if ((dev->features & NETIF_F_ALL_CSUM) &&
5431 !(dev->features & NETIF_F_NO_CSUM)) {
5432 dev->wanted_features |= NETIF_F_NOCACHE_COPY;
5433 dev->features |= NETIF_F_NOCACHE_COPY;
5434 }
5435
5428 /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, 5436 /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
5429 * vlan_dev_init() will do the dev->features check, so these features 5437 * vlan_dev_init() will do the dev->features check, so these features
5430 * are enabled only if supported by underlying device. 5438 * are enabled only if supported by underlying device.
@@ -6182,6 +6190,10 @@ u32 netdev_increment_features(u32 all, u32 one, u32 mask)
6182 } 6190 }
6183 } 6191 }
6184 6192
6193 /* If device can't no cache copy, don't do for all */
6194 if (!(one & NETIF_F_NOCACHE_COPY))
6195 all &= ~NETIF_F_NOCACHE_COPY;
6196
6185 one |= NETIF_F_ALL_CSUM; 6197 one |= NETIF_F_ALL_CSUM;
6186 6198
6187 one |= all & NETIF_F_ONE_FOR_ALL; 6199 one |= all & NETIF_F_ONE_FOR_ALL;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 439e4b0e1312..719670ae199c 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -359,7 +359,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS
359 /* NETIF_F_NTUPLE */ "rx-ntuple-filter", 359 /* NETIF_F_NTUPLE */ "rx-ntuple-filter",
360 /* NETIF_F_RXHASH */ "rx-hashing", 360 /* NETIF_F_RXHASH */ "rx-hashing",
361 /* NETIF_F_RXCSUM */ "rx-checksum", 361 /* NETIF_F_RXCSUM */ "rx-checksum",
362 "", 362 /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy"
363 "", 363 "",
364}; 364};
365 365
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b22d45010545..054a59d21eb0 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -999,7 +999,8 @@ new_segment:
999 /* We have some space in skb head. Superb! */ 999 /* We have some space in skb head. Superb! */
1000 if (copy > skb_tailroom(skb)) 1000 if (copy > skb_tailroom(skb))
1001 copy = skb_tailroom(skb); 1001 copy = skb_tailroom(skb);
1002 if ((err = skb_add_data(skb, from, copy)) != 0) 1002 err = skb_add_data_nocache(sk, skb, from, copy);
1003 if (err)
1003 goto do_fault; 1004 goto do_fault;
1004 } else { 1005 } else {
1005 int merge = 0; 1006 int merge = 0;
@@ -1042,8 +1043,8 @@ new_segment:
1042 1043
1043 /* Time to copy data. We are close to 1044 /* Time to copy data. We are close to
1044 * the end! */ 1045 * the end! */
1045 err = skb_copy_to_page(sk, from, skb, page, 1046 err = skb_copy_to_page_nocache(sk, from, skb,
1046 off, copy); 1047 page, off, copy);
1047 if (err) { 1048 if (err) {
1048 /* If this page was new, give it to the 1049 /* If this page was new, give it to the
1049 * socket so it does not get leaked. 1050 * socket so it does not get leaked.