]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/tcp_output.c
[TCP]: Remove superflushious skb == write_queue_tail() check
[linux-2.6-omap-h63xx.git] / net / ipv4 / tcp_output.c
index b3110fc1570ea807980a20eb18648b2660793193..debf235816067cc8a268b015c9adbae851a538a1 100644 (file)
@@ -255,7 +255,7 @@ static u16 tcp_select_window(struct sock *sk)
                 *
                 * Relax Will Robinson.
                 */
-               new_win = cur_win;
+               new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale);
        }
        tp->rcv_wnd = new_win;
        tp->rcv_wup = tp->rcv_nxt;
@@ -327,6 +327,26 @@ static inline void TCP_ECN_send(struct sock *sk, struct sk_buff *skb,
        }
 }
 
+/* Constructs common control bits of non-data skb. If SYN/FIN is present,
+ * auto increment end seqno.
+ */
+static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
+{
+       skb->csum = 0;
+
+       TCP_SKB_CB(skb)->flags = flags;
+       TCP_SKB_CB(skb)->sacked = 0;
+
+       skb_shinfo(skb)->gso_segs = 1;
+       skb_shinfo(skb)->gso_size = 0;
+       skb_shinfo(skb)->gso_type = 0;
+
+       TCP_SKB_CB(skb)->seq = seq;
+       if (flags & (TCPCB_FLAG_SYN | TCPCB_FLAG_FIN))
+               seq++;
+       TCP_SKB_CB(skb)->end_seq = seq;
+}
+
 static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
                                         __u32 tstamp, __u8 **md5_hash)
 {
@@ -978,7 +998,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
        xmit_size_goal = mss_now;
 
        if (doing_tso) {
-               xmit_size_goal = (65535 -
+               xmit_size_goal = ((sk->sk_gso_max_size - 1) -
                                  inet_csk(sk)->icsk_af_ops->net_header_len -
                                  inet_csk(sk)->icsk_ext_hdr_len -
                                  tp->tcp_header_len);
@@ -995,9 +1015,8 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
 static void tcp_cwnd_validate(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       __u32 packets_out = tp->packets_out;
 
-       if (packets_out >= tp->snd_cwnd) {
+       if (tp->packets_out >= tp->snd_cwnd) {
                /* Network is feed fully. */
                tp->snd_cwnd_used = 0;
                tp->snd_cwnd_stamp = tcp_time_stamp;
@@ -1016,6 +1035,13 @@ static void tcp_cwnd_validate(struct sock *sk)
  * introducing MSS oddities to segment boundaries. In rare cases where
  * mss_now != mss_cache, we will request caller to create a small skb
  * per input skb which could be mostly avoided here (if desired).
+ *
+ * We explicitly want to create a request for splitting write queue tail
+ * to a small skb for Nagle purposes while avoiding unnecessary modulos,
+ * thus all the complexity (cwnd_len is always MSS multiple which we
+ * return whenever allowed by the other factors). Basically we need the
+ * modulo only when the receiver window alone is the limiting factor or
+ * when we would be allowed to send the split-due-to-Nagle skb fully.
  */
 static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
                                        unsigned int mss_now, unsigned int cwnd)
@@ -1029,10 +1055,11 @@ static unsigned int tcp_mss_split_point(struct sock *sk, struct sk_buff *skb,
        if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk)))
                return cwnd_len;
 
-       if (skb == tcp_write_queue_tail(sk) && cwnd_len <= skb->len)
+       needed = min(skb->len, window);
+
+       if (cwnd_len <= needed)
                return cwnd_len;
 
-       needed = min(skb->len, window);
        return needed - needed % mss_now;
 }
 
@@ -1255,7 +1282,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
        limit = min(send_win, cong_win);
 
        /* If a full-sized TSO skb can be sent, do it. */
-       if (limit >= 65536)
+       if (limit >= sk->sk_gso_max_size)
                goto send_now;
 
        if (sysctl_tcp_tso_win_divisor) {
@@ -1781,6 +1808,9 @@ void tcp_simple_retransmit(struct sock *sk)
        if (!lost)
                return;
 
+       if (tcp_is_reno(tp))
+               tcp_limit_reno_sacked(tp);
+
        tcp_verify_left_out(tp);
 
        /* Don't muck with the congestion window here.
@@ -1865,12 +1895,10 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
            (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
            tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
                if (!pskb_trim(skb, 0)) {
-                       TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
-                       skb_shinfo(skb)->gso_segs = 1;
-                       skb_shinfo(skb)->gso_size = 0;
-                       skb_shinfo(skb)->gso_type = 0;
+                       /* Reuse, even though it does some unnecessary work */
+                       tcp_init_nondata_skb(skb, TCP_SKB_CB(skb)->end_seq - 1,
+                                            TCP_SKB_CB(skb)->flags);
                        skb->ip_summed = CHECKSUM_NONE;
-                       skb->csum = 0;
                }
        }
 
@@ -2069,16 +2097,9 @@ void tcp_send_fin(struct sock *sk)
 
                /* Reserve space for headers and prepare control bits. */
                skb_reserve(skb, MAX_TCP_HEADER);
-               skb->csum = 0;
-               TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
-               TCP_SKB_CB(skb)->sacked = 0;
-               skb_shinfo(skb)->gso_segs = 1;
-               skb_shinfo(skb)->gso_size = 0;
-               skb_shinfo(skb)->gso_type = 0;
-
                /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
-               TCP_SKB_CB(skb)->seq = tp->write_seq;
-               TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+               tcp_init_nondata_skb(skb, tp->write_seq,
+                                    TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
                tcp_queue_skb(sk, skb);
        }
        __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
@@ -2102,16 +2123,9 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
 
        /* Reserve space for headers and prepare control bits. */
        skb_reserve(skb, MAX_TCP_HEADER);
-       skb->csum = 0;
-       TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
-       TCP_SKB_CB(skb)->sacked = 0;
-       skb_shinfo(skb)->gso_segs = 1;
-       skb_shinfo(skb)->gso_size = 0;
-       skb_shinfo(skb)->gso_type = 0;
-
+       tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk),
+                            TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
        /* Send it off. */
-       TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk);
-       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
        if (tcp_transmit_skb(sk, skb, 0, priority))
                NET_INC_STATS(LINUX_MIB_TCPABORTFAILED);
@@ -2199,12 +2213,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        TCP_ECN_make_synack(req, th);
        th->source = inet_sk(sk)->sport;
        th->dest = ireq->rmt_port;
-       TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
-       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
-       TCP_SKB_CB(skb)->sacked = 0;
-       skb_shinfo(skb)->gso_segs = 1;
-       skb_shinfo(skb)->gso_size = 0;
-       skb_shinfo(skb)->gso_type = 0;
+       /* Setting of flags are superfluous here for callers (and ECE is
+        * not even correctly set)
+        */
+       tcp_init_nondata_skb(skb, tcp_rsk(req)->snt_isn,
+                            TCPCB_FLAG_SYN | TCPCB_FLAG_ACK);
        th->seq = htonl(TCP_SKB_CB(skb)->seq);
        th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
        if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
@@ -2223,7 +2236,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 
        /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
        th->window = htons(min(req->rcv_wnd, 65535U));
-
+#ifdef CONFIG_SYN_COOKIES
+       if (unlikely(req->cookie_ts))
+               TCP_SKB_CB(skb)->when = cookie_init_timestamp(req);
+       else
+#endif
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
        tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
                              ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
@@ -2236,7 +2253,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
                               NULL)
                              );
 
-       skb->csum = 0;
        th->doff = (tcp_header_size >> 2);
        TCP_INC_STATS(TCP_MIB_OUTSEGS);
 
@@ -2328,16 +2344,9 @@ int tcp_connect(struct sock *sk)
        /* Reserve space for headers. */
        skb_reserve(buff, MAX_TCP_HEADER);
 
-       TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
-       TCP_ECN_send_syn(sk, buff);
-       TCP_SKB_CB(buff)->sacked = 0;
-       skb_shinfo(buff)->gso_segs = 1;
-       skb_shinfo(buff)->gso_size = 0;
-       skb_shinfo(buff)->gso_type = 0;
-       buff->csum = 0;
        tp->snd_nxt = tp->write_seq;
-       TCP_SKB_CB(buff)->seq = tp->write_seq++;
-       TCP_SKB_CB(buff)->end_seq = tp->write_seq;
+       tcp_init_nondata_skb(buff, tp->write_seq++, TCPCB_FLAG_SYN);
+       TCP_ECN_send_syn(sk, buff);
 
        /* Send it off. */
        TCP_SKB_CB(buff)->when = tcp_time_stamp;
@@ -2442,15 +2451,9 @@ void tcp_send_ack(struct sock *sk)
 
        /* Reserve space for headers and prepare control bits. */
        skb_reserve(buff, MAX_TCP_HEADER);
-       buff->csum = 0;
-       TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
-       TCP_SKB_CB(buff)->sacked = 0;
-       skb_shinfo(buff)->gso_segs = 1;
-       skb_shinfo(buff)->gso_size = 0;
-       skb_shinfo(buff)->gso_type = 0;
+       tcp_init_nondata_skb(buff, tcp_acceptable_seq(sk), TCPCB_FLAG_ACK);
 
        /* Send it off, this clears delayed acks for us. */
-       TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk);
        TCP_SKB_CB(buff)->when = tcp_time_stamp;
        tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC);
 }
@@ -2478,19 +2481,11 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
 
        /* Reserve space for headers and set control bits. */
        skb_reserve(skb, MAX_TCP_HEADER);
-       skb->csum = 0;
-       TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
-       TCP_SKB_CB(skb)->sacked = 0;
-       skb_shinfo(skb)->gso_segs = 1;
-       skb_shinfo(skb)->gso_size = 0;
-       skb_shinfo(skb)->gso_type = 0;
-
        /* Use a previous sequence.  This should cause the other
         * end to send an ack.  Don't queue or clone SKB, just
         * send it.
         */
-       TCP_SKB_CB(skb)->seq = urgent ? tp->snd_una : tp->snd_una - 1;
-       TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+       tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPCB_FLAG_ACK);
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
        return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC);
 }
@@ -2580,9 +2575,9 @@ void tcp_send_probe0(struct sock *sk)
        }
 }
 
+EXPORT_SYMBOL(tcp_select_initial_window);
 EXPORT_SYMBOL(tcp_connect);
 EXPORT_SYMBOL(tcp_make_synack);
 EXPORT_SYMBOL(tcp_simple_retransmit);
 EXPORT_SYMBOL(tcp_sync_mss);
-EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor);
 EXPORT_SYMBOL(tcp_mtup_init);