aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-07-05 18:19:38 -0400
committerDavid S. Miller <davem@davemloft.net>2005-07-05 18:19:38 -0400
commit55c97f3e990c1ff63957c64f6cb10711a09fd70e (patch)
tree003c5ca17005c8b22cc4cbe0b10721fc4ea676fd
parenta2e2a59c93cc8ba39caa9011c2573f429e40ccd9 (diff)
[TCP]: Fix __tcp_push_pending_frames() 'nonagle' handling.
'nonagle' should be passed to the tcp_snd_test() function as 'TCP_NAGLE_PUSH' if we are checking an SKB not at the tail of the write_queue. This is because Nagle does not apply to such frames since we cannot possibly tack more data onto them. However, while doing this __tcp_push_pending_frames() makes all of the packets in the write_queue use this modified 'nonagle' value. Fix the bug and simplify this function by just calling tcp_write_xmit() directly if sk_send_head is non-NULL. As a result, we can now make tcp_data_snd_check() just call tcp_push_pending_frames() instead of the specialized __tcp_data_snd_check(). Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/tcp.h1
-rw-r--r--net/ipv4/tcp_input.c17
-rw-r--r--net/ipv4/tcp_output.c15
3 files changed, 8 insertions, 25 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 9416236cc395..b19238027da8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -848,7 +848,6 @@ extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
848 848
849/* tcp_output.c */ 849/* tcp_output.c */
850 850
851extern void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb);
852extern void __tcp_push_pending_frames(struct sock *sk, struct tcp_sock *tp, 851extern void __tcp_push_pending_frames(struct sock *sk, struct tcp_sock *tp,
853 unsigned int cur_mss, int nonagle); 852 unsigned int cur_mss, int nonagle);
854extern int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp); 853extern int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 577424323d59..b27be2f819ac 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3346,12 +3346,9 @@ static inline void tcp_check_space(struct sock *sk)
3346 } 3346 }
3347} 3347}
3348 3348
3349static __inline__ void tcp_data_snd_check(struct sock *sk) 3349static __inline__ void tcp_data_snd_check(struct sock *sk, struct tcp_sock *tp)
3350{ 3350{
3351 struct sk_buff *skb = sk->sk_send_head; 3351 tcp_push_pending_frames(sk, tp);
3352
3353 if (skb != NULL)
3354 __tcp_data_snd_check(sk, skb);
3355 tcp_check_space(sk); 3352 tcp_check_space(sk);
3356} 3353}
3357 3354
@@ -3645,7 +3642,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
3645 */ 3642 */
3646 tcp_ack(sk, skb, 0); 3643 tcp_ack(sk, skb, 0);
3647 __kfree_skb(skb); 3644 __kfree_skb(skb);
3648 tcp_data_snd_check(sk); 3645 tcp_data_snd_check(sk, tp);
3649 return 0; 3646 return 0;
3650 } else { /* Header too small */ 3647 } else { /* Header too small */
3651 TCP_INC_STATS_BH(TCP_MIB_INERRS); 3648 TCP_INC_STATS_BH(TCP_MIB_INERRS);
@@ -3711,7 +3708,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
3711 if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) { 3708 if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) {
3712 /* Well, only one small jumplet in fast path... */ 3709 /* Well, only one small jumplet in fast path... */
3713 tcp_ack(sk, skb, FLAG_DATA); 3710 tcp_ack(sk, skb, FLAG_DATA);
3714 tcp_data_snd_check(sk); 3711 tcp_data_snd_check(sk, tp);
3715 if (!tcp_ack_scheduled(tp)) 3712 if (!tcp_ack_scheduled(tp))
3716 goto no_ack; 3713 goto no_ack;
3717 } 3714 }
@@ -3789,7 +3786,7 @@ step5:
3789 /* step 7: process the segment text */ 3786 /* step 7: process the segment text */
3790 tcp_data_queue(sk, skb); 3787 tcp_data_queue(sk, skb);
3791 3788
3792 tcp_data_snd_check(sk); 3789 tcp_data_snd_check(sk, tp);
3793 tcp_ack_snd_check(sk); 3790 tcp_ack_snd_check(sk);
3794 return 0; 3791 return 0;
3795 3792
@@ -4099,7 +4096,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
4099 /* Do step6 onward by hand. */ 4096 /* Do step6 onward by hand. */
4100 tcp_urg(sk, skb, th); 4097 tcp_urg(sk, skb, th);
4101 __kfree_skb(skb); 4098 __kfree_skb(skb);
4102 tcp_data_snd_check(sk); 4099 tcp_data_snd_check(sk, tp);
4103 return 0; 4100 return 0;
4104 } 4101 }
4105 4102
@@ -4290,7 +4287,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
4290 4287
4291 /* tcp_data could move socket to TIME-WAIT */ 4288 /* tcp_data could move socket to TIME-WAIT */
4292 if (sk->sk_state != TCP_CLOSE) { 4289 if (sk->sk_state != TCP_CLOSE) {
4293 tcp_data_snd_check(sk); 4290 tcp_data_snd_check(sk, tp);
4294 tcp_ack_snd_check(sk); 4291 tcp_ack_snd_check(sk);
4295 } 4292 }
4296 4293
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index e292e11c7319..ce1d7cfbecfc 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -894,24 +894,11 @@ void __tcp_push_pending_frames(struct sock *sk, struct tcp_sock *tp,
894 struct sk_buff *skb = sk->sk_send_head; 894 struct sk_buff *skb = sk->sk_send_head;
895 895
896 if (skb) { 896 if (skb) {
897 if (!tcp_skb_is_last(sk, skb)) 897 if (tcp_write_xmit(sk, cur_mss, nonagle))
898 nonagle = TCP_NAGLE_PUSH;
899 if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
900 tcp_write_xmit(sk, cur_mss, nonagle))
901 tcp_check_probe_timer(sk, tp); 898 tcp_check_probe_timer(sk, tp);
902 } 899 }
903} 900}
904 901
905void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
906{
907 struct tcp_sock *tp = tcp_sk(sk);
908
909 if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) ||
910 tcp_packets_in_flight(tp) >= tp->snd_cwnd ||
911 tcp_write_xmit(sk, tcp_current_mss(sk, 1), tp->nonagle))
912 tcp_check_probe_timer(sk, tp);
913}
914
915/* This function returns the amount that we can raise the 902/* This function returns the amount that we can raise the
916 * usable window based on the following constraints 903 * usable window based on the following constraints
917 * 904 *