aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index c10e4435e3b1..7114031fdc70 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -190,7 +190,7 @@ void tcp_select_initial_window(int __space, __u32 mss,
190 } 190 }
191 191
192 /* Set initial window to value enough for senders, 192 /* Set initial window to value enough for senders,
193 * following RFC1414. Senders, not following this RFC, 193 * following RFC2414. Senders, not following this RFC,
194 * will be satisfied with 2. 194 * will be satisfied with 2.
195 */ 195 */
196 if (mss > (1<<*rcv_wscale)) { 196 if (mss > (1<<*rcv_wscale)) {
@@ -435,6 +435,17 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
435 int nsize, old_factor; 435 int nsize, old_factor;
436 u16 flags; 436 u16 flags;
437 437
438 if (unlikely(len >= skb->len)) {
439 if (net_ratelimit()) {
440 printk(KERN_DEBUG "TCP: seg_size=%u, mss=%u, seq=%u, "
441 "end_seq=%u, skb->len=%u.\n", len, mss_now,
442 TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
443 skb->len);
444 WARN_ON(1);
445 }
446 return 0;
447 }
448
438 nsize = skb_headlen(skb) - len; 449 nsize = skb_headlen(skb) - len;
439 if (nsize < 0) 450 if (nsize < 0)
440 nsize = 0; 451 nsize = 0;
@@ -459,9 +470,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
459 flags = TCP_SKB_CB(skb)->flags; 470 flags = TCP_SKB_CB(skb)->flags;
460 TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); 471 TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
461 TCP_SKB_CB(buff)->flags = flags; 472 TCP_SKB_CB(buff)->flags = flags;
462 TCP_SKB_CB(buff)->sacked = 473 TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
463 (TCP_SKB_CB(skb)->sacked &
464 (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
465 TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; 474 TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
466 475
467 if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { 476 if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -499,11 +508,26 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
499 tcp_skb_pcount(buff); 508 tcp_skb_pcount(buff);
500 509
501 tp->packets_out -= diff; 510 tp->packets_out -= diff;
511
512 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
513 tp->sacked_out -= diff;
514 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
515 tp->retrans_out -= diff;
516
502 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { 517 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
503 tp->lost_out -= diff; 518 tp->lost_out -= diff;
504 tp->left_out -= diff; 519 tp->left_out -= diff;
505 } 520 }
521
506 if (diff > 0) { 522 if (diff > 0) {
523 /* Adjust Reno SACK estimate. */
524 if (!tp->rx_opt.sack_ok) {
525 tp->sacked_out -= diff;
526 if ((int)tp->sacked_out < 0)
527 tp->sacked_out = 0;
528 tcp_sync_left_out(tp);
529 }
530
507 tp->fackets_out -= diff; 531 tp->fackets_out -= diff;
508 if ((int)tp->fackets_out < 0) 532 if ((int)tp->fackets_out < 0)
509 tp->fackets_out = 0; 533 tp->fackets_out = 0;
@@ -1595,7 +1619,7 @@ void tcp_send_fin(struct sock *sk)
1595 * was unread data in the receive queue. This behavior is recommended 1619 * was unread data in the receive queue. This behavior is recommended
1596 * by draft-ietf-tcpimpl-prob-03.txt section 3.10. -DaveM 1620 * by draft-ietf-tcpimpl-prob-03.txt section 3.10. -DaveM
1597 */ 1621 */
1598void tcp_send_active_reset(struct sock *sk, unsigned int __nocast priority) 1622void tcp_send_active_reset(struct sock *sk, gfp_t priority)
1599{ 1623{
1600 struct tcp_sock *tp = tcp_sk(sk); 1624 struct tcp_sock *tp = tcp_sk(sk);
1601 struct sk_buff *skb; 1625 struct sk_buff *skb;