]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/ipv4/tcp.c
[TCP]: Allow autoloading of congestion control via setsockopt.
[mv-sheeva.git] / net / ipv4 / tcp.c
index 804458712d881dee4065f2e4cbd7e7c99296d545..c05e8edaf5443645209d3515c7e328989c44ae47 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
-int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
+int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT;
 
 DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics) __read_mostly;
 
@@ -568,7 +568,7 @@ new_segment:
                skb->truesize += copy;
                sk->sk_wmem_queued += copy;
                sk->sk_forward_alloc -= copy;
-               skb->ip_summed = CHECKSUM_HW;
+               skb->ip_summed = CHECKSUM_PARTIAL;
                tp->write_seq += copy;
                TCP_SKB_CB(skb)->end_seq += copy;
                skb_shinfo(skb)->gso_segs = 0;
@@ -723,7 +723,7 @@ new_segment:
                                 * Check whether we can use HW checksum.
                                 */
                                if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
-                                       skb->ip_summed = CHECKSUM_HW;
+                                       skb->ip_summed = CHECKSUM_PARTIAL;
 
                                skb_entail(sk, tp, skb);
                                copy = size_goal;
@@ -955,8 +955,11 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
                     * receive buffer and there was a small segment
                     * in queue.
                     */
-                   (copied > 0 && (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
-                    !icsk->icsk_ack.pingpong && !atomic_read(&sk->sk_rmem_alloc)))
+                   (copied > 0 &&
+                    ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) ||
+                     ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) &&
+                      !icsk->icsk_ack.pingpong)) &&
+                     !atomic_read(&sk->sk_rmem_alloc)))
                        time_to_ack = 1;
        }
 
@@ -1132,7 +1135,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        tp->ucopy.dma_chan = NULL;
        preempt_disable();
        if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
-           !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) {
+           !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) {
                preempt_enable_no_resched();
                tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
        } else
@@ -1659,7 +1662,8 @@ adjudge_to_death:
                        const int tmo = tcp_fin_time(sk);
 
                        if (tmo > TCP_TIMEWAIT_LEN) {
-                               inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
+                               inet_csk_reset_keepalive_timer(sk,
+                                               tmo - TCP_TIMEWAIT_LEN);
                        } else {
                                tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
                                goto out;
@@ -2170,8 +2174,19 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 
        if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
                /* Packet is from an untrusted source, reset gso_segs. */
-               int mss = skb_shinfo(skb)->gso_size;
+               int type = skb_shinfo(skb)->gso_type;
+               int mss;
+
+               if (unlikely(type &
+                            ~(SKB_GSO_TCPV4 |
+                              SKB_GSO_DODGY |
+                              SKB_GSO_TCP_ECN |
+                              SKB_GSO_TCPV6 |
+                              0) ||
+                            !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
+                       goto out;
 
+               mss = skb_shinfo(skb)->gso_size;
                skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
 
                segs = NULL;
@@ -2193,7 +2208,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
                th->fin = th->psh = 0;
 
                th->check = ~csum_fold(th->check + delta);
-               if (skb->ip_summed != CHECKSUM_HW)
+               if (skb->ip_summed != CHECKSUM_PARTIAL)
                        th->check = csum_fold(csum_partial(skb->h.raw, thlen,
                                                           skb->csum));
 
@@ -2207,7 +2222,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 
        delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
        th->check = ~csum_fold(th->check + delta);
-       if (skb->ip_summed != CHECKSUM_HW)
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
                th->check = csum_fold(csum_partial(skb->h.raw, thlen,
                                                   skb->csum));
 
@@ -2242,9 +2257,7 @@ void __init tcp_init(void)
        tcp_hashinfo.bind_bucket_cachep =
                kmem_cache_create("tcp_bind_bucket",
                                  sizeof(struct inet_bind_bucket), 0,
-                                 SLAB_HWCACHE_ALIGN, NULL, NULL);
-       if (!tcp_hashinfo.bind_bucket_cachep)
-               panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
+                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
        /* Size and allocate the main established and bind bucket
         * hash tables.
@@ -2257,7 +2270,7 @@ void __init tcp_init(void)
                                        thash_entries,
                                        (num_physpages >= 128 * 1024) ?
                                        13 : 15,
-                                       HASH_HIGHMEM,
+                                       0,
                                        &tcp_hashinfo.ehash_size,
                                        NULL,
                                        0);
@@ -2273,7 +2286,7 @@ void __init tcp_init(void)
                                        tcp_hashinfo.ehash_size,
                                        (num_physpages >= 128 * 1024) ?
                                        13 : 15,
-                                       HASH_HIGHMEM,
+                                       0,
                                        &tcp_hashinfo.bhash_size,
                                        NULL,
                                        64 * 1024);
@@ -2303,9 +2316,10 @@ void __init tcp_init(void)
                sysctl_max_syn_backlog = 128;
        }
 
-       sysctl_tcp_mem[0] =  768 << order;
-       sysctl_tcp_mem[1] = 1024 << order;
-       sysctl_tcp_mem[2] = 1536 << order;
+       /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */
+       sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order;
+       sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3;
+       sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
 
        limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
        max_share = min(4UL*1024*1024, limit);