aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h1
-rw-r--r--net/ipv4/tcp.c12
-rw-r--r--net/ipv4/tcp_output.c2
3 files changed, 14 insertions, 1 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 4475aaf0af57..5bba80fbd1d9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -370,6 +370,7 @@ extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
370extern int tcp_sendpage(struct sock *sk, struct page *page, int offset, 370extern int tcp_sendpage(struct sock *sk, struct page *page, int offset,
371 size_t size, int flags); 371 size_t size, int flags);
372extern void tcp_release_cb(struct sock *sk); 372extern void tcp_release_cb(struct sock *sk);
373extern void tcp_wfree(struct sk_buff *skb);
373extern void tcp_write_timer_handler(struct sock *sk); 374extern void tcp_write_timer_handler(struct sock *sk);
374extern void tcp_delack_timer_handler(struct sock *sk); 375extern void tcp_delack_timer_handler(struct sock *sk);
375extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); 376extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a96f7b586277..963bda18486f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2885,6 +2885,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
2885 __be32 delta; 2885 __be32 delta;
2886 unsigned int oldlen; 2886 unsigned int oldlen;
2887 unsigned int mss; 2887 unsigned int mss;
2888 struct sk_buff *gso_skb = skb;
2888 2889
2889 if (!pskb_may_pull(skb, sizeof(*th))) 2890 if (!pskb_may_pull(skb, sizeof(*th)))
2890 goto out; 2891 goto out;
@@ -2953,6 +2954,17 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
2953 th->cwr = 0; 2954 th->cwr = 0;
2954 } while (skb->next); 2955 } while (skb->next);
2955 2956
2957 /* Following permits TCP Small Queues to work well with GSO :
2958 * The callback to TCP stack will be called at the time last frag
2959 * is freed at TX completion, and not right now when gso_skb
2960 * is freed by GSO engine
2961 */
2962 if (gso_skb->destructor == tcp_wfree) {
2963 swap(gso_skb->sk, skb->sk);
2964 swap(gso_skb->destructor, skb->destructor);
2965 swap(gso_skb->truesize, skb->truesize);
2966 }
2967
2956 delta = htonl(oldlen + (skb->tail - skb->transport_header) + 2968 delta = htonl(oldlen + (skb->tail - skb->transport_header) +
2957 skb->data_len); 2969 skb->data_len);
2958 th->check = ~csum_fold((__force __wsum)((__force u32)th->check + 2970 th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index af354c98fdb5..d12694353540 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -787,7 +787,7 @@ void __init tcp_tasklet_init(void)
787 * We cant xmit new skbs from this context, as we might already 787 * We cant xmit new skbs from this context, as we might already
788 * hold qdisc lock. 788 * hold qdisc lock.
789 */ 789 */
790static void tcp_wfree(struct sk_buff *skb) 790void tcp_wfree(struct sk_buff *skb)
791{ 791{
792 struct sock *sk = skb->sk; 792 struct sock *sk = skb->sk;
793 struct tcp_sock *tp = tcp_sk(sk); 793 struct tcp_sock *tp = tcp_sk(sk);