aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2010-08-04 08:05:07 -0400
committerMichal Marek <mmarek@suse.cz>2010-08-04 08:05:07 -0400
commit7a996d3ab150bb0e1b71fa182f70199a703efdd1 (patch)
tree96a36947d90c9b96580899abd38cb3b70cd9d40b /net/ipv4/tcp_output.c
parent7cf3d73b4360e91b14326632ab1aeda4cb26308d (diff)
parent9fe6206f400646a2322096b56c59891d530e8d51 (diff)
Merge commit 'v2.6.35' into kbuild/kconfig
Conflicts: scripts/kconfig/Makefile
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c69
1 files changed, 39 insertions, 30 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 383ce237640f..7ed9dc1042d1 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -37,6 +37,7 @@
37#include <net/tcp.h> 37#include <net/tcp.h>
38 38
39#include <linux/compiler.h> 39#include <linux/compiler.h>
40#include <linux/gfp.h>
40#include <linux/module.h> 41#include <linux/module.h>
41 42
42/* People can turn this off for buggy TCP's found in printers etc. */ 43/* People can turn this off for buggy TCP's found in printers etc. */
@@ -183,7 +184,8 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
183 */ 184 */
184void tcp_select_initial_window(int __space, __u32 mss, 185void tcp_select_initial_window(int __space, __u32 mss,
185 __u32 *rcv_wnd, __u32 *window_clamp, 186 __u32 *rcv_wnd, __u32 *window_clamp,
186 int wscale_ok, __u8 *rcv_wscale) 187 int wscale_ok, __u8 *rcv_wscale,
188 __u32 init_rcv_wnd)
187{ 189{
188 unsigned int space = (__space < 0 ? 0 : __space); 190 unsigned int space = (__space < 0 ? 0 : __space);
189 191
@@ -232,7 +234,13 @@ void tcp_select_initial_window(int __space, __u32 mss,
232 init_cwnd = 2; 234 init_cwnd = 2;
233 else if (mss > 1460) 235 else if (mss > 1460)
234 init_cwnd = 3; 236 init_cwnd = 3;
235 if (*rcv_wnd > init_cwnd * mss) 237 /* when initializing use the value from init_rcv_wnd
238 * rather than the default from above
239 */
240 if (init_rcv_wnd &&
241 (*rcv_wnd > init_rcv_wnd * mss))
242 *rcv_wnd = init_rcv_wnd * mss;
243 else if (*rcv_wnd > init_cwnd * mss)
236 *rcv_wnd = init_cwnd * mss; 244 *rcv_wnd = init_cwnd * mss;
237 } 245 }
238 246
@@ -342,6 +350,7 @@ static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb,
342 */ 350 */
343static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags) 351static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
344{ 352{
353 skb->ip_summed = CHECKSUM_PARTIAL;
345 skb->csum = 0; 354 skb->csum = 0;
346 355
347 TCP_SKB_CB(skb)->flags = flags; 356 TCP_SKB_CB(skb)->flags = flags;
@@ -659,7 +668,6 @@ static unsigned tcp_synack_options(struct sock *sk,
659 u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ? 668 u8 cookie_plus = (xvp != NULL && !xvp->cookie_out_never) ?
660 xvp->cookie_plus : 669 xvp->cookie_plus :
661 0; 670 0;
662 bool doing_ts = ireq->tstamp_ok;
663 671
664#ifdef CONFIG_TCP_MD5SIG 672#ifdef CONFIG_TCP_MD5SIG
665 *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); 673 *md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
@@ -672,7 +680,7 @@ static unsigned tcp_synack_options(struct sock *sk,
672 * rather than TS in order to fit in better with old, 680 * rather than TS in order to fit in better with old,
673 * buggy kernels, but that was deemed to be unnecessary. 681 * buggy kernels, but that was deemed to be unnecessary.
674 */ 682 */
675 doing_ts &= !ireq->sack_ok; 683 ireq->tstamp_ok &= !ireq->sack_ok;
676 } 684 }
677#else 685#else
678 *md5 = NULL; 686 *md5 = NULL;
@@ -687,7 +695,7 @@ static unsigned tcp_synack_options(struct sock *sk,
687 opts->options |= OPTION_WSCALE; 695 opts->options |= OPTION_WSCALE;
688 remaining -= TCPOLEN_WSCALE_ALIGNED; 696 remaining -= TCPOLEN_WSCALE_ALIGNED;
689 } 697 }
690 if (likely(doing_ts)) { 698 if (likely(ireq->tstamp_ok)) {
691 opts->options |= OPTION_TS; 699 opts->options |= OPTION_TS;
692 opts->tsval = TCP_SKB_CB(skb)->when; 700 opts->tsval = TCP_SKB_CB(skb)->when;
693 opts->tsecr = req->ts_recent; 701 opts->tsecr = req->ts_recent;
@@ -695,7 +703,7 @@ static unsigned tcp_synack_options(struct sock *sk,
695 } 703 }
696 if (likely(ireq->sack_ok)) { 704 if (likely(ireq->sack_ok)) {
697 opts->options |= OPTION_SACK_ADVERTISE; 705 opts->options |= OPTION_SACK_ADVERTISE;
698 if (unlikely(!doing_ts)) 706 if (unlikely(!ireq->tstamp_ok))
699 remaining -= TCPOLEN_SACKPERM_ALIGNED; 707 remaining -= TCPOLEN_SACKPERM_ALIGNED;
700 } 708 }
701 709
@@ -703,7 +711,7 @@ static unsigned tcp_synack_options(struct sock *sk,
703 * If the <SYN> options fit, the same options should fit now! 711 * If the <SYN> options fit, the same options should fit now!
704 */ 712 */
705 if (*md5 == NULL && 713 if (*md5 == NULL &&
706 doing_ts && 714 ireq->tstamp_ok &&
707 cookie_plus > TCPOLEN_COOKIE_BASE) { 715 cookie_plus > TCPOLEN_COOKIE_BASE) {
708 int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */ 716 int need = cookie_plus; /* has TCPOLEN_COOKIE_BASE */
709 717
@@ -852,7 +860,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
852 th->urg_ptr = htons(tp->snd_up - tcb->seq); 860 th->urg_ptr = htons(tp->snd_up - tcb->seq);
853 th->urg = 1; 861 th->urg = 1;
854 } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { 862 } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) {
855 th->urg_ptr = 0xFFFF; 863 th->urg_ptr = htons(0xFFFF);
856 th->urg = 1; 864 th->urg = 1;
857 } 865 }
858 } 866 }
@@ -864,13 +872,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
864#ifdef CONFIG_TCP_MD5SIG 872#ifdef CONFIG_TCP_MD5SIG
865 /* Calculate the MD5 hash, as we have all we need now */ 873 /* Calculate the MD5 hash, as we have all we need now */
866 if (md5) { 874 if (md5) {
867 sk->sk_route_caps &= ~NETIF_F_GSO_MASK; 875 sk_nocaps_add(sk, NETIF_F_GSO_MASK);
868 tp->af_specific->calc_md5_hash(opts.hash_location, 876 tp->af_specific->calc_md5_hash(opts.hash_location,
869 md5, sk, NULL, skb); 877 md5, sk, NULL, skb);
870 } 878 }
871#endif 879#endif
872 880
873 icsk->icsk_af_ops->send_check(sk, skb->len, skb); 881 icsk->icsk_af_ops->send_check(sk, skb);
874 882
875 if (likely(tcb->flags & TCPCB_FLAG_ACK)) 883 if (likely(tcb->flags & TCPCB_FLAG_ACK))
876 tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); 884 tcp_event_ack_sent(sk, tcp_skb_pcount(skb));
@@ -879,9 +887,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
879 tcp_event_data_sent(tp, skb, sk); 887 tcp_event_data_sent(tp, skb, sk);
880 888
881 if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) 889 if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
882 TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); 890 TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS,
891 tcp_skb_pcount(skb));
883 892
884 err = icsk->icsk_af_ops->queue_xmit(skb, 0); 893 err = icsk->icsk_af_ops->queue_xmit(skb);
885 if (likely(err <= 0)) 894 if (likely(err <= 0))
886 return err; 895 return err;
887 896
@@ -1794,11 +1803,6 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
1794void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, 1803void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
1795 int nonagle) 1804 int nonagle)
1796{ 1805{
1797 struct sk_buff *skb = tcp_send_head(sk);
1798
1799 if (!skb)
1800 return;
1801
1802 /* If we are closed, the bytes will have to remain here. 1806 /* If we are closed, the bytes will have to remain here.
1803 * In time closedown will finish, we empty the write queue and 1807 * In time closedown will finish, we empty the write queue and
1804 * all will be happy. 1808 * all will be happy.
@@ -2204,6 +2208,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
2204 int mib_idx; 2208 int mib_idx;
2205 int fwd_rexmitting = 0; 2209 int fwd_rexmitting = 0;
2206 2210
2211 if (!tp->packets_out)
2212 return;
2213
2207 if (!tp->lost_out) 2214 if (!tp->lost_out)
2208 tp->retransmit_high = tp->snd_una; 2215 tp->retransmit_high = tp->snd_una;
2209 2216
@@ -2393,13 +2400,17 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2393 struct tcp_extend_values *xvp = tcp_xv(rvp); 2400 struct tcp_extend_values *xvp = tcp_xv(rvp);
2394 struct inet_request_sock *ireq = inet_rsk(req); 2401 struct inet_request_sock *ireq = inet_rsk(req);
2395 struct tcp_sock *tp = tcp_sk(sk); 2402 struct tcp_sock *tp = tcp_sk(sk);
2403 const struct tcp_cookie_values *cvp = tp->cookie_values;
2396 struct tcphdr *th; 2404 struct tcphdr *th;
2397 struct sk_buff *skb; 2405 struct sk_buff *skb;
2398 struct tcp_md5sig_key *md5; 2406 struct tcp_md5sig_key *md5;
2399 int tcp_header_size; 2407 int tcp_header_size;
2400 int mss; 2408 int mss;
2409 int s_data_desired = 0;
2401 2410
2402 skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); 2411 if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
2412 s_data_desired = cvp->s_data_desired;
2413 skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC);
2403 if (skb == NULL) 2414 if (skb == NULL)
2404 return NULL; 2415 return NULL;
2405 2416
@@ -2422,7 +2433,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2422 &req->rcv_wnd, 2433 &req->rcv_wnd,
2423 &req->window_clamp, 2434 &req->window_clamp,
2424 ireq->wscale_ok, 2435 ireq->wscale_ok,
2425 &rcv_wscale); 2436 &rcv_wscale,
2437 dst_metric(dst, RTAX_INITRWND));
2426 ireq->rcv_wscale = rcv_wscale; 2438 ireq->rcv_wscale = rcv_wscale;
2427 } 2439 }
2428 2440
@@ -2454,16 +2466,12 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2454 TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); 2466 TCPCB_FLAG_SYN | TCPCB_FLAG_ACK);
2455 2467
2456 if (OPTION_COOKIE_EXTENSION & opts.options) { 2468 if (OPTION_COOKIE_EXTENSION & opts.options) {
2457 const struct tcp_cookie_values *cvp = tp->cookie_values; 2469 if (s_data_desired) {
2458 2470 u8 *buf = skb_put(skb, s_data_desired);
2459 if (cvp != NULL &&
2460 cvp->s_data_constant &&
2461 cvp->s_data_desired > 0) {
2462 u8 *buf = skb_put(skb, cvp->s_data_desired);
2463 2471
2464 /* copy data directly from the listening socket. */ 2472 /* copy data directly from the listening socket. */
2465 memcpy(buf, cvp->s_data_payload, cvp->s_data_desired); 2473 memcpy(buf, cvp->s_data_payload, s_data_desired);
2466 TCP_SKB_CB(skb)->end_seq += cvp->s_data_desired; 2474 TCP_SKB_CB(skb)->end_seq += s_data_desired;
2467 } 2475 }
2468 2476
2469 if (opts.hash_size > 0) { 2477 if (opts.hash_size > 0) {
@@ -2480,7 +2488,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2480 *tail-- ^= TCP_SKB_CB(skb)->seq + 1; 2488 *tail-- ^= TCP_SKB_CB(skb)->seq + 1;
2481 2489
2482 /* recommended */ 2490 /* recommended */
2483 *tail-- ^= ((th->dest << 16) | th->source); 2491 *tail-- ^= (((__force u32)th->dest << 16) | (__force u32)th->source);
2484 *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */ 2492 *tail-- ^= (u32)(unsigned long)cvp; /* per sockopt */
2485 2493
2486 sha_transform((__u32 *)&xvp->cookie_bakery[0], 2494 sha_transform((__u32 *)&xvp->cookie_bakery[0],
@@ -2498,7 +2506,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2498 th->window = htons(min(req->rcv_wnd, 65535U)); 2506 th->window = htons(min(req->rcv_wnd, 65535U));
2499 tcp_options_write((__be32 *)(th + 1), tp, &opts); 2507 tcp_options_write((__be32 *)(th + 1), tp, &opts);
2500 th->doff = (tcp_header_size >> 2); 2508 th->doff = (tcp_header_size >> 2);
2501 TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); 2509 TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, tcp_skb_pcount(skb));
2502 2510
2503#ifdef CONFIG_TCP_MD5SIG 2511#ifdef CONFIG_TCP_MD5SIG
2504 /* Okay, we have all we need - do the md5 hash if needed */ 2512 /* Okay, we have all we need - do the md5 hash if needed */
@@ -2549,7 +2557,8 @@ static void tcp_connect_init(struct sock *sk)
2549 &tp->rcv_wnd, 2557 &tp->rcv_wnd,
2550 &tp->window_clamp, 2558 &tp->window_clamp,
2551 sysctl_tcp_window_scaling, 2559 sysctl_tcp_window_scaling,
2552 &rcv_wscale); 2560 &rcv_wscale,
2561 dst_metric(dst, RTAX_INITRWND));
2553 2562
2554 tp->rx_opt.rcv_wscale = rcv_wscale; 2563 tp->rx_opt.rcv_wscale = rcv_wscale;
2555 tp->rcv_ssthresh = tp->rcv_wnd; 2564 tp->rcv_ssthresh = tp->rcv_wnd;