]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/tcp_output.c
[TCP]: Left out sync->verify (the new meaning of it) & definify
[linux-2.6-omap-h63xx.git] / net / ipv4 / tcp_output.c
index 53232dd6fb48af5a9c4f5d2373a1630936bb7980..a92fad55cd3232f1041415de80f39484f548cc8a 100644 (file)
@@ -269,6 +269,56 @@ static u16 tcp_select_window(struct sock *sk)
        return new_win;
 }
 
+static inline void TCP_ECN_send_synack(struct tcp_sock *tp,
+                                      struct sk_buff *skb)
+{
+       TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_CWR;
+       if (!(tp->ecn_flags&TCP_ECN_OK))
+               TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_ECE;
+}
+
+static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       tp->ecn_flags = 0;
+       if (sysctl_tcp_ecn) {
+               TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR;
+               tp->ecn_flags = TCP_ECN_OK;
+       }
+}
+
+static __inline__ void
+TCP_ECN_make_synack(struct request_sock *req, struct tcphdr *th)
+{
+       if (inet_rsk(req)->ecn_ok)
+               th->ece = 1;
+}
+
+static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb,
+                               int tcp_header_len)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       if (tp->ecn_flags & TCP_ECN_OK) {
+               /* Not-retransmitted data segment: set ECT and inject CWR. */
+               if (skb->len != tcp_header_len &&
+                   !before(TCP_SKB_CB(skb)->seq, tp->snd_nxt)) {
+                       INET_ECN_xmit(sk);
+                       if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) {
+                               tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR;
+                               tcp_hdr(skb)->cwr = 1;
+                               skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
+                       }
+               } else {
+                       /* ACK or retransmitted segment: clear ECT|CE */
+                       INET_ECN_dontxmit(sk);
+               }
+               if (tp->ecn_flags & TCP_ECN_DEMAND_CWR)
+                       tcp_hdr(skb)->ece = 1;
+       }
+}
+
 static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
                                         __u32 tstamp, __u8 **md5_hash)
 {
@@ -682,23 +732,23 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
                if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
                        tp->retrans_out -= diff;
 
-               if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+               if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST)
                        tp->lost_out -= diff;
-                       tp->left_out -= diff;
-               }
 
                if (diff > 0) {
                        /* Adjust Reno SACK estimate. */
                        if (!tp->rx_opt.sack_ok) {
-                               tp->sacked_out -= diff;
-                               if ((int)tp->sacked_out < 0)
-                                       tp->sacked_out = 0;
-                               tcp_sync_left_out(tp);
+                               tcp_dec_pcount_approx_int(&tp->sacked_out, diff);
+                               tcp_verify_left_out(tp);
                        }
 
-                       tp->fackets_out -= diff;
-                       if ((int)tp->fackets_out < 0)
-                               tp->fackets_out = 0;
+                       tcp_dec_pcount_approx_int(&tp->fackets_out, diff);
+                       /* SACK fastpath might overwrite it unless dealt with */
+                       if (tp->fastpath_skb_hint != NULL &&
+                           after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq,
+                                 TCP_SKB_CB(skb)->seq)) {
+                               tcp_dec_pcount_approx_int(&tp->fastpath_cnt_hint, diff);
+                       }
                }
        }
 
@@ -1607,7 +1657,7 @@ u32 __tcp_select_window(struct sock *sk)
                if (window <= free_space - mss || window > free_space)
                        window = (free_space/mss)*mss;
                else if (mss == full_space &&
-                        free_space > window + full_space/2)
+                        free_space > window + full_space/2)
                        window = free_space;
        }
 
@@ -1675,15 +1725,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
                TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
                if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
                        tp->retrans_out -= tcp_skb_pcount(next_skb);
-               if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
+               if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST)
                        tp->lost_out -= tcp_skb_pcount(next_skb);
-                       tp->left_out -= tcp_skb_pcount(next_skb);
-               }
                /* Reno case is special. Sigh... */
-               if (!tp->rx_opt.sack_ok && tp->sacked_out) {
+               if (!tp->rx_opt.sack_ok && tp->sacked_out)
                        tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
-                       tp->left_out -= tcp_skb_pcount(next_skb);
-               }
 
                /* Not quite right: it can be > snd.fack, but
                 * it is better to underestimate fackets.
@@ -1728,7 +1774,7 @@ void tcp_simple_retransmit(struct sock *sk)
        if (!lost)
                return;
 
-       tcp_sync_left_out(tp);
+       tcp_verify_left_out(tp);
 
        /* Don't muck with the congestion window here.
         * Reason is that we do not increase amount of _data_
@@ -1937,33 +1983,28 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
         * and retransmission... Both ways have their merits...
         *
         * For now we do not retransmit anything, while we have some new
-        * segments to send.
+        * segments to send. In the other cases, follow rule 3 for
+        * NextSeg() specified in RFC3517.
         */
 
        if (tcp_may_send_now(sk))
                return;
 
-       if (tp->forward_skb_hint) {
+       /* If nothing is SACKed, highest_sack in the loop won't be valid */
+       if (!tp->sacked_out)
+               return;
+
+       if (tp->forward_skb_hint)
                skb = tp->forward_skb_hint;
-               packet_cnt = tp->forward_cnt_hint;
-       } else{
+       else
                skb = tcp_write_queue_head(sk);
-               packet_cnt = 0;
-       }
 
        tcp_for_write_queue_from(skb, sk) {
                if (skb == tcp_send_head(sk))
                        break;
-               tp->forward_cnt_hint = packet_cnt;
                tp->forward_skb_hint = skb;
 
-               /* Similar to the retransmit loop above we
-                * can pretend that the retransmitted SKB
-                * we send out here will be composed of one
-                * real MSS sized packet because tcp_retransmit_skb()
-                * will fragment it if necessary.
-                */
-               if (++packet_cnt > tp->fackets_out)
+               if (after(TCP_SKB_CB(skb)->seq, tp->highest_sack))
                        break;
 
                if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)