aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-02-11 04:27:41 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-13 13:30:10 -0500
commitc9af6db4c11ccc6c3e7f19bbc15d54023956f97c (patch)
treec596e747d8940b848931ac31701e245a6c0efaf6 /net/ipv4/tcp_output.c
parentb8fa4100350432504df438014e2e5e9c1bbb6325 (diff)
net: Fix possible wrong checksum generation.
Patch cef401de7be8c4e (net: fix possible wrong checksum generation) fixed wrong checksum calculation but it broke TSO by defining new GSO type but not a netdev feature for that type. net_gso_ok() would not allow hardware checksum/segmentation offload of such packets without the feature. Following patch fixes TSO and wrong checksum. This patch uses same logic that Eric Dumazet used. Patch introduces new flag SKBTX_SHARED_FRAG if at least one frag can be modified by the user. but SKBTX_SHARED_FRAG flag is kept in skb shared info tx_flags rather than gso_type. tx_flags is better compared to gso_type since we can have skb with shared frag without gso packet. It does not link SHARED_FRAG to GSO, So there is no need to define netdev feature for this. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 564bf89d9fd3..6182d90e97b0 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1133,7 +1133,6 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
1133static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, 1133static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
1134 unsigned int mss_now) 1134 unsigned int mss_now)
1135{ 1135{
1136 skb_shinfo(skb)->gso_type &= SKB_GSO_SHARED_FRAG;
1137 if (skb->len <= mss_now || !sk_can_gso(sk) || 1136 if (skb->len <= mss_now || !sk_can_gso(sk) ||
1138 skb->ip_summed == CHECKSUM_NONE) { 1137 skb->ip_summed == CHECKSUM_NONE) {
1139 /* Avoid the costly divide in the normal 1138 /* Avoid the costly divide in the normal
@@ -1141,10 +1140,11 @@ static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
1141 */ 1140 */
1142 skb_shinfo(skb)->gso_segs = 1; 1141 skb_shinfo(skb)->gso_segs = 1;
1143 skb_shinfo(skb)->gso_size = 0; 1142 skb_shinfo(skb)->gso_size = 0;
1143 skb_shinfo(skb)->gso_type = 0;
1144 } else { 1144 } else {
1145 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now); 1145 skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now);
1146 skb_shinfo(skb)->gso_size = mss_now; 1146 skb_shinfo(skb)->gso_size = mss_now;
1147 skb_shinfo(skb)->gso_type |= sk->sk_gso_type; 1147 skb_shinfo(skb)->gso_type = sk->sk_gso_type;
1148 } 1148 }
1149} 1149}
1150 1150