Merge master.kernel.org:/home/rmk/linux-2.6-arm
[powerpc.git] / net / ipv4 / tcp_ipv4.c
index 13dfb39..4d5021e 100644 (file)
@@ -39,7 +39,7 @@
  *                                     request_sock handling and moved
  *                                     most of it into the af independent code.
  *                                     Added tail drop and some other bugfixes.
- *                                     Added new listen sematics.
+ *                                     Added new listen semantics.
  *             Mike McLagan    :       Routing by source
  *     Juan Jose Ciarlante:            ip_dynaddr bits
  *             Andi Kleen:             various fixes.
@@ -93,8 +93,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
        .lhash_lock     = RW_LOCK_UNLOCKED,
        .lhash_users    = ATOMIC_INIT(0),
        .lhash_wait     = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
-       .portalloc_lock = SPIN_LOCK_UNLOCKED,
-       .port_rover     = 1024 - 1,
 };
 
 static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
@@ -130,19 +128,20 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
        int dif = sk->sk_bound_dev_if;
        INET_ADDR_COOKIE(acookie, saddr, daddr)
        const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
-       const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, tcp_hashinfo.ehash_size);
-       struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
+       unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
        struct sock *sk2;
        const struct hlist_node *node;
        struct inet_timewait_sock *tw;
 
+       prefetch(head->chain.first);
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
        sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
                tw = inet_twsk(sk2);
 
-               if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+               if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
                        const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
                        struct tcp_sock *tp = tcp_sk(sk);
 
@@ -179,7 +178,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
                        goto not_unique;
        }
 
@@ -188,7 +187,7 @@ unique:
         * in hash table socket with a funny identity. */
        inet->num = lport;
        inet->sport = htons(lport);
-       sk->sk_hashent = hash;
+       sk->sk_hash = hash;
        BUG_TRAP(sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
        sock_prot_inc_use(sk->sk_prot);
@@ -824,8 +823,7 @@ out:
  */
 static void tcp_v4_reqsk_destructor(struct request_sock *req)
 {
-       if (inet_rsk(req)->opt)
-               kfree(inet_rsk(req)->opt);
+       kfree(inet_rsk(req)->opt);
 }
 
 static inline void syn_flood_warning(struct sk_buff *skb)
@@ -1112,24 +1110,18 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
 static int tcp_v4_checksum_init(struct sk_buff *skb)
 {
        if (skb->ip_summed == CHECKSUM_HW) {
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
                if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
-                                 skb->nh.iph->daddr, skb->csum))
+                                 skb->nh.iph->daddr, skb->csum)) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
                        return 0;
-
-               LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v4 csum failed\n");
-               skb->ip_summed = CHECKSUM_NONE;
+               }
        }
+
+       skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr, skb->nh.iph->daddr,
+                                      skb->len, IPPROTO_TCP, 0);
+
        if (skb->len <= 76) {
-               if (tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
-                                skb->nh.iph->daddr,
-                                skb_checksum(skb, 0, skb->len, 0)))
-                       return -1;
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-       } else {
-               skb->csum = ~tcp_v4_check(skb->h.th, skb->len,
-                                         skb->nh.iph->saddr,
-                                         skb->nh.iph->daddr, 0);
+               return __skb_checksum_complete(skb);
        }
        return 0;
 }
@@ -1218,10 +1210,10 @@ int tcp_v4_rcv(struct sk_buff *skb)
 
        /* An explanation is required here, I think.
         * Packet length and doff are validated by header prediction,
-        * provided case of th->doff==0 is elimineted.
+        * provided case of th->doff==0 is eliminated.
         * So, we defer the checks. */
        if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-            tcp_v4_checksum_init(skb) < 0))
+            tcp_v4_checksum_init(skb)))
                goto bad_packet;
 
        th = skb->h.th;