aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-01-25 15:34:37 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-28 00:27:15 -0500
commitcef401de7be8c4e155c6746bfccf721a4fa5fab9 (patch)
treeaf082329bf0613ed9de5b9575e3f94f3f03b77ec /include
parent61550022b9586972082904b80de26a464c558437 (diff)
net: fix possible wrong checksum generation
Pravin Shelar mentioned that GSO could potentially generate wrong TX checksum if skb has fragments that are overwritten by the user between the checksum computation and transmit. He suggested to linearize skbs but this extra copy can be avoided for normal tcp skbs cooked by tcp_sendmsg(). This patch introduces a new SKB_GSO_SHARED_FRAG flag, set in skb_shinfo(skb)->gso_type if at least one frag can be modified by the user. Typical sources of such possible overwrites are {vm}splice(), sendfile(), and macvtap/tun/virtio_net drivers. Tested: $ netperf -H 7.7.8.84 MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.8.84 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.00 3959.52 $ netperf -H 7.7.8.84 -t TCP_SENDFILE TCP SENDFILE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.8.84 () port 0 AF_INET Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.00 3216.80 Performance of the SENDFILE is impacted by the extra allocation and copy, and because we use order-0 pages, while the TCP_STREAM uses bigger pages. Reported-by: Pravin Shelar <pshelar@nicira.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/skbuff.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8b2256e880e0..0259b719bebf 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -307,6 +307,13 @@ enum {
307 SKB_GSO_TCPV6 = 1 << 4, 307 SKB_GSO_TCPV6 = 1 << 4,
308 308
309 SKB_GSO_FCOE = 1 << 5, 309 SKB_GSO_FCOE = 1 << 5,
310
311 /* This indicates at least one fragment might be overwritten
312 * (as in vmsplice(), sendfile() ...)
313 * If we need to compute a TX checksum, we'll need to copy
314 * all frags to avoid possible bad checksum
315 */
316 SKB_GSO_SHARED_FRAG = 1 << 6,
310}; 317};
311 318
312#if BITS_PER_LONG > 32 319#if BITS_PER_LONG > 32
@@ -2201,6 +2208,18 @@ static inline int skb_linearize(struct sk_buff *skb)
2201} 2208}
2202 2209
2203/** 2210/**
2211 * skb_has_shared_frag - can any frag be overwritten
2212 * @skb: buffer to test
2213 *
2214 * Return true if the skb has at least one frag that might be modified
2215 * by an external entity (as in vmsplice()/sendfile())
2216 */
2217static inline bool skb_has_shared_frag(const struct sk_buff *skb)
2218{
2219 return skb_shinfo(skb)->gso_type & SKB_GSO_SHARED_FRAG;
2220}
2221
2222/**
2204 * skb_linearize_cow - make sure skb is linear and writable 2223 * skb_linearize_cow - make sure skb is linear and writable
2205 * @skb: buffer to process 2224 * @skb: buffer to process
2206 * 2225 *