[ICSK]: Generalise tcp_listen_{start,stop}
[deliverable/linux.git] / net / ipv6 / tcp_ipv6.c
index 0f69e800a0ad695868f1efc89d645c32a0445e19..0b51ec310ebe5651c06e391ae09e1dc2d8bb20fe 100644 (file)
@@ -65,7 +65,7 @@
 #include <linux/seq_file.h>
 
 static void    tcp_v6_send_reset(struct sk_buff *skb);
-static void    tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
+static void    tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
 static void    tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
                                  struct sk_buff *skb);
 
@@ -84,7 +84,7 @@ static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport,
        hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
        hashent ^= hashent>>16;
        hashent ^= hashent>>8;
-       return (hashent & (tcp_ehash_size - 1));
+       return (hashent & (tcp_hashinfo.ehash_size - 1));
 }
 
 static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
@@ -98,11 +98,11 @@ static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
        return tcp_v6_hashfn(laddr, lport, faddr, fport);
 }
 
-static inline int tcp_v6_bind_conflict(struct sock *sk,
-                                      struct tcp_bind_bucket *tb)
+static inline int tcp_v6_bind_conflict(const struct sock *sk,
+                                      const struct inet_bind_bucket *tb)
 {
-       struct sock *sk2;
-       struct hlist_node *node;
+       const struct sock *sk2;
+       const struct hlist_node *node;
 
        /* We must walk the whole port owner list in this case. -DaveM */
        sk_for_each_bound(sk2, node, &tb->owners) {
@@ -126,8 +126,8 @@ static inline int tcp_v6_bind_conflict(struct sock *sk,
  */
 static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
 {
-       struct tcp_bind_hashbucket *head;
-       struct tcp_bind_bucket *tb;
+       struct inet_bind_hashbucket *head;
+       struct inet_bind_bucket *tb;
        struct hlist_node *node;
        int ret;
 
@@ -138,37 +138,42 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
                int remaining = (high - low) + 1;
                int rover;
 
-               spin_lock(&tcp_portalloc_lock);
-               if (tcp_port_rover < low)
+               spin_lock(&tcp_hashinfo.portalloc_lock);
+               if (tcp_hashinfo.port_rover < low)
                        rover = low;
                else
-                       rover = tcp_port_rover;
+                       rover = tcp_hashinfo.port_rover;
                do {    rover++;
                        if (rover > high)
                                rover = low;
-                       head = &tcp_bhash[tcp_bhashfn(rover)];
+                       head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)];
                        spin_lock(&head->lock);
-                       tb_for_each(tb, node, &head->chain)
+                       inet_bind_bucket_for_each(tb, node, &head->chain)
                                if (tb->port == rover)
                                        goto next;
                        break;
                next:
                        spin_unlock(&head->lock);
                } while (--remaining > 0);
-               tcp_port_rover = rover;
-               spin_unlock(&tcp_portalloc_lock);
-
-               /* Exhausted local port range during search? */
+               tcp_hashinfo.port_rover = rover;
+               spin_unlock(&tcp_hashinfo.portalloc_lock);
+
+               /* Exhausted local port range during search?  It is not
+                * possible for us to be holding one of the bind hash
+                * locks if this test triggers, because if 'remaining'
+                * drops to zero, we broke out of the do/while loop at
+                * the top level, not from the 'break;' statement.
+                */
                ret = 1;
-               if (remaining <= 0)
+               if (unlikely(remaining <= 0))
                        goto fail;
 
                /* OK, here is the one we will use. */
                snum = rover;
        } else {
-               head = &tcp_bhash[tcp_bhashfn(snum)];
+               head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
                spin_lock(&head->lock);
-               tb_for_each(tb, node, &head->chain)
+               inet_bind_bucket_for_each(tb, node, &head->chain)
                        if (tb->port == snum)
                                goto tb_found;
        }
@@ -187,8 +192,11 @@ tb_found:
        }
 tb_not_found:
        ret = 1;
-       if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL)
-               goto fail_unlock;
+       if (tb == NULL) {
+               tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, snum);
+               if (tb == NULL)
+                       goto fail_unlock;
+       }
        if (hlist_empty(&tb->owners)) {
                if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
                        tb->fastreuse = 1;
@@ -199,9 +207,9 @@ tb_not_found:
                tb->fastreuse = 0;
 
 success:
-       if (!tcp_sk(sk)->bind_hash)
-               tcp_bind_hash(sk, tb, snum);
-       BUG_TRAP(tcp_sk(sk)->bind_hash == tb);
+       if (!inet_csk(sk)->icsk_bind_hash)
+               inet_bind_hash(sk, tb, snum);
+       BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
        ret = 0;
 
 fail_unlock:
@@ -219,13 +227,13 @@ static __inline__ void __tcp_v6_hash(struct sock *sk)
        BUG_TRAP(sk_unhashed(sk));
 
        if (sk->sk_state == TCP_LISTEN) {
-               list = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
-               lock = &tcp_lhash_lock;
-               tcp_listen_wlock();
+               list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)];
+               lock = &tcp_hashinfo.lhash_lock;
+               inet_listen_wlock(&tcp_hashinfo);
        } else {
                sk->sk_hashent = tcp_v6_sk_hashfn(sk);
-               list = &tcp_ehash[sk->sk_hashent].chain;
-               lock = &tcp_ehash[sk->sk_hashent].lock;
+               list = &tcp_hashinfo.ehash[sk->sk_hashent].chain;
+               lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock;
                write_lock(lock);
        }
 
@@ -258,8 +266,8 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor
        int score, hiscore;
 
        hiscore=0;
-       read_lock(&tcp_lhash_lock);
-       sk_for_each(sk, node, &tcp_listening_hash[tcp_lhashfn(hnum)]) {
+       read_lock(&tcp_hashinfo.lhash_lock);
+       sk_for_each(sk, node, &tcp_hashinfo.listening_hash[inet_lhashfn(hnum)]) {
                if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) {
                        struct ipv6_pinfo *np = inet6_sk(sk);
                        
@@ -286,7 +294,7 @@ static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned shor
        }
        if (result)
                sock_hold(result);
-       read_unlock(&tcp_lhash_lock);
+       read_unlock(&tcp_hashinfo.lhash_lock);
        return result;
 }
 
@@ -300,33 +308,32 @@ static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u
                                                       struct in6_addr *daddr, u16 hnum,
                                                       int dif)
 {
-       struct tcp_ehash_bucket *head;
        struct sock *sk;
-       struct hlist_node *node;
-       __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
-       int hash;
-
+       const struct hlist_node *node;
+       const __u32 ports = INET_COMBINED_PORTS(sport, hnum);
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
-       head = &tcp_ehash[hash];
+       const int hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
+       struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
+
        read_lock(&head->lock);
        sk_for_each(sk, node, &head->chain) {
                /* For IPV6 do the cheaper port and family tests first. */
-               if(TCP_IPV6_MATCH(sk, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk, saddr, daddr, ports, dif))
                        goto hit; /* You sunk my battleship! */
        }
        /* Must check for a TIME_WAIT'er before going to listener hash. */
-       sk_for_each(sk, node, &(head + tcp_ehash_size)->chain) {
-               /* FIXME: acme: check this... */
-               struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+       sk_for_each(sk, node, &(head + tcp_hashinfo.ehash_size)->chain) {
+               const struct inet_timewait_sock *tw = inet_twsk(sk);
 
                if(*((__u32 *)&(tw->tw_dport))  == ports        &&
                   sk->sk_family                == PF_INET6) {
-                       if(ipv6_addr_equal(&tw->tw_v6_daddr, saddr)     &&
-                          ipv6_addr_equal(&tw->tw_v6_rcv_saddr, daddr) &&
-                          (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
+                       const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
+
+                       if (ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr)        &&
+                           ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr)    &&
+                           (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
                                goto hit;
                }
        }
@@ -374,7 +381,7 @@ EXPORT_SYMBOL_GPL(tcp_v6_lookup);
  * Open request hash tables.
  */
 
-static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
+static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd)
 {
        u32 a, b, c;
 
@@ -394,24 +401,27 @@ static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
        return c & (TCP_SYNQ_HSIZE - 1);
 }
 
-static struct open_request *tcp_v6_search_req(struct tcp_sock *tp,
-                                             struct open_request ***prevp,
+static struct request_sock *tcp_v6_search_req(const struct sock *sk,
+                                             struct request_sock ***prevp,
                                              __u16 rport,
                                              struct in6_addr *raddr,
                                              struct in6_addr *laddr,
                                              int iif)
 {
-       struct tcp_listen_opt *lopt = tp->listen_opt;
-       struct open_request *req, **prev;  
+       const struct inet_connection_sock *icsk = inet_csk(sk);
+       struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+       struct request_sock *req, **prev;  
 
        for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
             (req = *prev) != NULL;
             prev = &req->dl_next) {
-               if (req->rmt_port == rport &&
-                   req->class->family == AF_INET6 &&
-                   ipv6_addr_equal(&req->af.v6_req.rmt_addr, raddr) &&
-                   ipv6_addr_equal(&req->af.v6_req.loc_addr, laddr) &&
-                   (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
+               const struct tcp6_request_sock *treq = tcp6_rsk(req);
+
+               if (inet_rsk(req)->rmt_port == rport &&
+                   req->rsk_ops->family == AF_INET6 &&
+                   ipv6_addr_equal(&treq->rmt_addr, raddr) &&
+                   ipv6_addr_equal(&treq->loc_addr, laddr) &&
+                   (!treq->iif || treq->iif == iif)) {
                        BUG_TRAP(req->sk == NULL);
                        *prevp = prev;
                        return req;
@@ -445,43 +455,46 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
 }
 
 static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
-                                     struct tcp_tw_bucket **twp)
+                                     struct inet_timewait_sock **twp)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct in6_addr *daddr = &np->rcv_saddr;
        struct in6_addr *saddr = &np->daddr;
        int dif = sk->sk_bound_dev_if;
-       u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
-       int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport);
-       struct tcp_ehash_bucket *head = &tcp_ehash[hash];
+       const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+       const int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport);
+       struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
        struct sock *sk2;
-       struct hlist_node *node;
-       struct tcp_tw_bucket *tw;
+       const struct hlist_node *node;
+       struct inet_timewait_sock *tw;
 
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
-       sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) {
-               tw = (struct tcp_tw_bucket*)sk2;
+       sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
+               const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk2);
+
+               tw = inet_twsk(sk2);
 
                if(*((__u32 *)&(tw->tw_dport))  == ports        &&
                   sk2->sk_family               == PF_INET6     &&
-                  ipv6_addr_equal(&tw->tw_v6_daddr, saddr)     &&
-                  ipv6_addr_equal(&tw->tw_v6_rcv_saddr, daddr) &&
+                  ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
+                  ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr)     &&
                   sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
+                       const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
                        struct tcp_sock *tp = tcp_sk(sk);
 
-                       if (tw->tw_ts_recent_stamp &&
-                           (!twp || (sysctl_tcp_tw_reuse &&
-                                     xtime.tv_sec - 
-                                     tw->tw_ts_recent_stamp > 1))) {
+                       if (tcptw->tw_ts_recent_stamp &&
+                           (!twp ||
+                            (sysctl_tcp_tw_reuse &&
+                             xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
                                /* See comment in tcp_ipv4.c */
-                               tp->write_seq = tw->tw_snd_nxt + 65535 + 2;
+                               tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
                                if (!tp->write_seq)
                                        tp->write_seq = 1;
-                               tp->rx_opt.ts_recent tw->tw_ts_recent;
-                               tp->rx_opt.ts_recent_stamp = tw->tw_ts_recent_stamp;
+                               tp->rx_opt.ts_recent       = tcptw->tw_ts_recent;
+                               tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
                                sock_hold(sk2);
                                goto unique;
                        } else
@@ -492,7 +505,7 @@ static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if(TCP_IPV6_MATCH(sk2, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk2, saddr, daddr, ports, dif))
                        goto not_unique;
        }
 
@@ -511,7 +524,7 @@ unique:
                tcp_tw_deschedule(tw);
                NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
 
-               tcp_tw_put(tw);
+               inet_twsk_put(tw);
        }
        return 0;
 
@@ -533,8 +546,8 @@ static inline u32 tcpv6_port_offset(const struct sock *sk)
 static int tcp_v6_hash_connect(struct sock *sk)
 {
        unsigned short snum = inet_sk(sk)->num;
-       struct tcp_bind_hashbucket *head;
-       struct tcp_bind_bucket *tb;
+       struct inet_bind_hashbucket *head;
+       struct inet_bind_bucket *tb;
        int ret;
 
        if (!snum) {
@@ -546,19 +559,19 @@ static int tcp_v6_hash_connect(struct sock *sk)
                static u32 hint;
                u32 offset = hint + tcpv6_port_offset(sk);
                struct hlist_node *node;
-               struct tcp_tw_bucket *tw = NULL;
+               struct inet_timewait_sock *tw = NULL;
 
                local_bh_disable();
                for (i = 1; i <= range; i++) {
                        port = low + (i + offset) % range;
-                       head = &tcp_bhash[tcp_bhashfn(port)];
+                       head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)];
                        spin_lock(&head->lock);
 
                        /* Does not bother with rcv_saddr checks,
                         * because the established check is already
                         * unique enough.
                         */
-                       tb_for_each(tb, node, &head->chain) {
+                       inet_bind_bucket_for_each(tb, node, &head->chain) {
                                if (tb->port == port) {
                                        BUG_TRAP(!hlist_empty(&tb->owners));
                                        if (tb->fastreuse >= 0)
@@ -571,7 +584,7 @@ static int tcp_v6_hash_connect(struct sock *sk)
                                }
                        }
 
-                       tb = tcp_bucket_create(head, port);
+                       tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
                        if (!tb) {
                                spin_unlock(&head->lock);
                                break;
@@ -590,7 +603,7 @@ ok:
                hint += i;
 
                /* Head lock still held and bh's disabled */
-               tcp_bind_hash(sk, tb, port);
+               inet_bind_hash(sk, tb, port);
                if (sk_unhashed(sk)) {
                        inet_sk(sk)->sport = htons(port);
                        __tcp_v6_hash(sk);
@@ -599,15 +612,15 @@ ok:
 
                if (tw) {
                        tcp_tw_deschedule(tw);
-                       tcp_tw_put(tw);
+                       inet_twsk_put(tw);
                }
 
                ret = 0;
                goto out;
        }
 
-       head  = &tcp_bhash[tcp_bhashfn(snum)];
-       tb  = tcp_sk(sk)->bind_hash;
+       head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
+       tb   = inet_csk(sk)->icsk_bind_hash;
        spin_lock_bh(&head->lock);
 
        if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
@@ -835,7 +848,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        }
 
        if (sk->sk_state == TCP_TIME_WAIT) {
-               tcp_tw_put((struct tcp_tw_bucket*)sk);
+               inet_twsk_put((struct inet_timewait_sock *)sk);
                return;
        }
 
@@ -906,14 +919,14 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        icmpv6_err_convert(type, code, &err);
 
-       /* Might be for an open_request */
+       /* Might be for an request_sock */
        switch (sk->sk_state) {
-               struct open_request *req, **prev;
+               struct request_sock *req, **prev;
        case TCP_LISTEN:
                if (sock_owned_by_user(sk))
                        goto out;
 
-               req = tcp_v6_search_req(tp, &prev, th->dest, &hdr->daddr,
+               req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr,
                                        &hdr->saddr, tcp_v6_iif(skb));
                if (!req)
                        goto out;
@@ -923,12 +936,12 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                 */
                BUG_TRAP(req->sk == NULL);
 
-               if (seq != req->snt_isn) {
+               if (seq != tcp_rsk(req)->snt_isn) {
                        NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
                        goto out;
                }
 
-               tcp_synq_drop(sk, req, prev);
+               inet_csk_reqsk_queue_drop(sk, req, prev);
                goto out;
 
        case TCP_SYN_SENT:
@@ -957,9 +970,10 @@ out:
 }
 
 
-static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
+static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
                              struct dst_entry *dst)
 {
+       struct tcp6_request_sock *treq = tcp6_rsk(req);
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sk_buff * skb;
        struct ipv6_txoptions *opt = NULL;
@@ -969,19 +983,19 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
 
        memset(&fl, 0, sizeof(fl));
        fl.proto = IPPROTO_TCP;
-       ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
-       ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+       ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
+       ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
        fl.fl6_flowlabel = 0;
-       fl.oif = req->af.v6_req.iif;
-       fl.fl_ip_dport = req->rmt_port;
+       fl.oif = treq->iif;
+       fl.fl_ip_dport = inet_rsk(req)->rmt_port;
        fl.fl_ip_sport = inet_sk(sk)->sport;
 
        if (dst == NULL) {
                opt = np->opt;
                if (opt == NULL &&
                    np->rxopt.bits.srcrt == 2 &&
-                   req->af.v6_req.pktopts) {
-                       struct sk_buff *pktopts = req->af.v6_req.pktopts;
+                   treq->pktopts) {
+                       struct sk_buff *pktopts = treq->pktopts;
                        struct inet6_skb_parm *rxopt = IP6CB(pktopts);
                        if (rxopt->srcrt)
                                opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
@@ -1008,10 +1022,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
                struct tcphdr *th = skb->h.th;
 
                th->check = tcp_v6_check(th, skb->len,
-                                        &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
+                                        &treq->loc_addr, &treq->rmt_addr,
                                         csum_partial((char *)th, skb->len, skb->csum));
 
-               ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+               ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
                err = ip6_xmit(sk, skb, &fl, opt, 0);
                if (err == NET_XMIT_CN)
                        err = 0;
@@ -1024,17 +1038,18 @@ done:
        return err;
 }
 
-static void tcp_v6_or_free(struct open_request *req)
+static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
-       if (req->af.v6_req.pktopts)
-               kfree_skb(req->af.v6_req.pktopts);
+       if (tcp6_rsk(req)->pktopts)
+               kfree_skb(tcp6_rsk(req)->pktopts);
 }
 
-static struct or_calltable or_ipv6 = {
+static struct request_sock_ops tcp6_request_sock_ops = {
        .family         =       AF_INET6,
+       .obj_size       =       sizeof(struct tcp6_request_sock),
        .rtx_syn_ack    =       tcp_v6_send_synack,
-       .send_ack       =       tcp_v6_or_send_ack,
-       .destructor     =       tcp_v6_or_free,
+       .send_ack       =       tcp_v6_reqsk_send_ack,
+       .destructor     =       tcp_v6_reqsk_destructor,
        .send_reset     =       tcp_v6_send_reset
 };
 
@@ -1211,29 +1226,30 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 
 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 {
-       struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+       struct inet_timewait_sock *tw = inet_twsk(sk);
+       const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-       tcp_v6_send_ack(skb, tw->tw_snd_nxt, tw->tw_rcv_nxt,
-                       tw->tw_rcv_wnd >> tw->tw_rcv_wscale, tw->tw_ts_recent);
+       tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+                       tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
+                       tcptw->tw_ts_recent);
 
-       tcp_tw_put(tw);
+       inet_twsk_put(tw);
 }
 
-static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req)
+static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
 {
-       tcp_v6_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd, req->ts_recent);
+       tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
 }
 
 
 static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
 {
-       struct open_request *req, **prev;
+       struct request_sock *req, **prev;
        struct tcphdr *th = skb->h.th;
-       struct tcp_sock *tp = tcp_sk(sk);
        struct sock *nsk;
 
        /* Find possible connection requests. */
-       req = tcp_v6_search_req(tp, &prev, th->source, &skb->nh.ipv6h->saddr,
+       req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
                                &skb->nh.ipv6h->daddr, tcp_v6_iif(skb));
        if (req)
                return tcp_check_req(sk, skb, req, prev);
@@ -1249,7 +1265,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
                        bh_lock_sock(nsk);
                        return nsk;
                }
-               tcp_tw_put((struct tcp_tw_bucket*)nsk);
+               inet_twsk_put((struct inet_timewait_sock *)nsk);
                return NULL;
        }
 
@@ -1260,22 +1276,14 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
        return sk;
 }
 
-static void tcp_v6_synq_add(struct sock *sk, struct open_request *req)
+static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
 {
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct tcp_listen_opt *lopt = tp->listen_opt;
-       u32 h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port, lopt->hash_rnd);
-
-       req->sk = NULL;
-       req->expires = jiffies + TCP_TIMEOUT_INIT;
-       req->retrans = 0;
-       req->dl_next = lopt->syn_table[h];
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+       const u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
 
-       write_lock(&tp->syn_wait_lock);
-       lopt->syn_table[h] = req;
-       write_unlock(&tp->syn_wait_lock);
-
-       tcp_synq_added(sk);
+       reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT);
+       inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT);
 }
 
 
@@ -1284,10 +1292,11 @@ static void tcp_v6_synq_add(struct sock *sk, struct open_request *req)
  */
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 {
+       struct tcp6_request_sock *treq;
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct tcp_options_received tmp_opt;
        struct tcp_sock *tp = tcp_sk(sk);
-       struct open_request *req = NULL;
+       struct request_sock *req = NULL;
        __u32 isn = TCP_SKB_CB(skb)->when;
 
        if (skb->protocol == htons(ETH_P_IP))
@@ -1299,16 +1308,16 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        /*
         *      There are no SYN attacks on IPv6, yet...        
         */
-       if (tcp_synq_is_full(sk) && !isn) {
+       if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
                if (net_ratelimit())
                        printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
                goto drop;              
        }
 
-       if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+       if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
                goto drop;
 
-       req = tcp_openreq_alloc();
+       req = reqsk_alloc(&tcp6_request_sock_ops);
        if (req == NULL)
                goto drop;
 
@@ -1321,28 +1330,28 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
        tcp_openreq_init(req, &tmp_opt, skb);
 
-       req->class = &or_ipv6;
-       ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr);
-       ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr);
+       treq = tcp6_rsk(req);
+       ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
+       ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
        TCP_ECN_create_request(req, skb->h.th);
-       req->af.v6_req.pktopts = NULL;
+       treq->pktopts = NULL;
        if (ipv6_opt_accepted(sk, skb) ||
            np->rxopt.bits.rxinfo ||
            np->rxopt.bits.rxhlim) {
                atomic_inc(&skb->users);
-               req->af.v6_req.pktopts = skb;
+               treq->pktopts = skb;
        }
-       req->af.v6_req.iif = sk->sk_bound_dev_if;
+       treq->iif = sk->sk_bound_dev_if;
 
        /* So that link locals have meaning */
        if (!sk->sk_bound_dev_if &&
-           ipv6_addr_type(&req->af.v6_req.rmt_addr) & IPV6_ADDR_LINKLOCAL)
-               req->af.v6_req.iif = tcp_v6_iif(skb);
+           ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+               treq->iif = tcp_v6_iif(skb);
 
        if (isn == 0) 
                isn = tcp_v6_init_sequence(sk,skb);
 
-       req->snt_isn = isn;
+       tcp_rsk(req)->snt_isn = isn;
 
        if (tcp_v6_send_synack(sk, req, NULL))
                goto drop;
@@ -1353,16 +1362,17 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 
 drop:
        if (req)
-               tcp_openreq_free(req);
+               reqsk_free(req);
 
        TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
        return 0; /* don't send reset */
 }
 
 static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-                                         struct open_request *req,
+                                         struct request_sock *req,
                                          struct dst_entry *dst)
 {
+       struct tcp6_request_sock *treq = tcp6_rsk(req);
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
        struct tcp6_sock *newtcp6sk;
        struct inet_sock *newinet;
@@ -1404,12 +1414,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                newnp->mcast_oif   = tcp_v6_iif(skb);
                newnp->mcast_hops  = skb->nh.ipv6h->hop_limit;
 
-               /* Charge newly allocated IPv6 socket. Though it is mapped,
-                * it is IPv6 yet.
+               /*
+                * No need to charge this sock to the relevant IPv6 refcnt debug socks count
+                * here, tcp_create_openreq_child now does this for us, see the comment in
+                * that function for the gory details. -acme
                 */
-#ifdef INET_REFCNT_DEBUG
-               atomic_inc(&inet6_sock_nr);
-#endif
 
                /* It is tricky place. Until this moment IPv4 tcp
                   worked with IPv6 af_tcp.af_specific.
@@ -1426,10 +1435,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                goto out_overflow;
 
        if (np->rxopt.bits.srcrt == 2 &&
-           opt == NULL && req->af.v6_req.pktopts) {
-               struct inet6_skb_parm *rxopt = IP6CB(req->af.v6_req.pktopts);
+           opt == NULL && treq->pktopts) {
+               struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
                if (rxopt->srcrt)
-                       opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt));
+                       opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));
        }
 
        if (dst == NULL) {
@@ -1438,16 +1447,16 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
                memset(&fl, 0, sizeof(fl));
                fl.proto = IPPROTO_TCP;
-               ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+               ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
                if (opt && opt->srcrt) {
                        struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
                        ipv6_addr_copy(&final, &fl.fl6_dst);
                        ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
                        final_p = &final;
                }
-               ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+               ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
                fl.oif = sk->sk_bound_dev_if;
-               fl.fl_ip_dport = req->rmt_port;
+               fl.fl_ip_dport = inet_rsk(req)->rmt_port;
                fl.fl_ip_sport = inet_sk(sk)->sport;
 
                if (ip6_dst_lookup(sk, &dst, &fl))
@@ -1464,10 +1473,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        if (newsk == NULL)
                goto out;
 
-       /* Charge newly allocated IPv6 socket */
-#ifdef INET_REFCNT_DEBUG
-       atomic_inc(&inet6_sock_nr);
-#endif
+       /*
+        * No need to charge this sock to the relevant IPv6 refcnt debug socks
+        * count here, tcp_create_openreq_child now does this for us, see the
+        * comment in that function for the gory details. -acme
+        */
 
        ip6_dst_store(newsk, dst, NULL);
        newsk->sk_route_caps = dst->dev->features &
@@ -1482,10 +1492,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
 
-       ipv6_addr_copy(&newnp->daddr, &req->af.v6_req.rmt_addr);
-       ipv6_addr_copy(&newnp->saddr, &req->af.v6_req.loc_addr);
-       ipv6_addr_copy(&newnp->rcv_saddr, &req->af.v6_req.loc_addr);
-       newsk->sk_bound_dev_if = req->af.v6_req.iif;
+       ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);
+       ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);
+       ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
+       newsk->sk_bound_dev_if = treq->iif;
 
        /* Now IPv6 options... 
 
@@ -1498,11 +1508,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        /* Clone pktoptions received with SYN */
        newnp->pktoptions = NULL;
-       if (req->af.v6_req.pktopts) {
-               newnp->pktoptions = skb_clone(req->af.v6_req.pktopts,
-                                             GFP_ATOMIC);
-               kfree_skb(req->af.v6_req.pktopts);
-               req->af.v6_req.pktopts = NULL;
+       if (treq->pktopts != NULL) {
+               newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
+               kfree_skb(treq->pktopts);
+               treq->pktopts = NULL;
                if (newnp->pktoptions)
                        skb_set_owner_r(newnp->pktoptions, newsk);
        }
@@ -1534,7 +1543,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
 
        __tcp_v6_hash(newsk);
-       tcp_inherit_port(sk, newsk);
+       inet_inherit_port(&tcp_hashinfo, sk, newsk);
 
        return newsk;
 
@@ -1793,26 +1802,26 @@ discard_and_relse:
 
 do_time_wait:
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-               tcp_tw_put((struct tcp_tw_bucket *) sk);
+               inet_twsk_put((struct inet_timewait_sock *)sk);
                goto discard_it;
        }
 
        if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
                TCP_INC_STATS_BH(TCP_MIB_INERRS);
-               tcp_tw_put((struct tcp_tw_bucket *) sk);
+               inet_twsk_put((struct inet_timewait_sock *)sk);
                goto discard_it;
        }
 
-       switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
-                                         skb, th, skb->len)) {
+       switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
+                                          skb, th)) {
        case TCP_TW_SYN:
        {
                struct sock *sk2;
 
                sk2 = tcp_v6_lookup_listener(&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb));
                if (sk2 != NULL) {
-                       tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
-                       tcp_tw_put((struct tcp_tw_bucket *)sk);
+                       tcp_tw_deschedule((struct inet_timewait_sock *)sk);
+                       inet_twsk_put((struct inet_timewait_sock *)sk);
                        sk = sk2;
                        goto process;
                }
@@ -1981,7 +1990,7 @@ static struct tcp_func ipv6_specific = {
 static struct tcp_func ipv6_mapped = {
        .queue_xmit     =       ip_queue_xmit,
        .send_check     =       tcp_v4_send_check,
-       .rebuild_header =       tcp_v4_rebuild_header,
+       .rebuild_header =       inet_sk_rebuild_header,
        .conn_request   =       tcp_v6_conn_request,
        .syn_recv_sock  =       tcp_v6_syn_recv_sock,
        .remember_stamp =       tcp_v4_remember_stamp,
@@ -2006,7 +2015,7 @@ static int tcp_v6_init_sock(struct sock *sk)
        tcp_init_xmit_timers(sk);
        tcp_prequeue_init(tp);
 
-       tp->rto  = TCP_TIMEOUT_INIT;
+       inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
        tp->mdev = TCP_TIMEOUT_INIT;
 
        /* So many TCP implementations out there (incorrectly) count the
@@ -2021,14 +2030,14 @@ static int tcp_v6_init_sock(struct sock *sk)
         */
        tp->snd_ssthresh = 0x7fffffff;
        tp->snd_cwnd_clamp = ~0;
-       tp->mss_cache_std = tp->mss_cache = 536;
+       tp->mss_cache = 536;
 
        tp->reordering = sysctl_tcp_reordering;
 
        sk->sk_state = TCP_CLOSE;
 
        tp->af_specific = &ipv6_specific;
-
+       tp->ca_ops = &tcp_init_congestion_ops;
        sk->sk_write_space = sk_stream_write_space;
        sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
 
@@ -2050,7 +2059,7 @@ static int tcp_v6_destroy_sock(struct sock *sk)
 
 /* Proc filesystem TCPv6 sock list dumping. */
 static void get_openreq6(struct seq_file *seq, 
-                        struct sock *sk, struct open_request *req, int i, int uid)
+                        struct sock *sk, struct request_sock *req, int i, int uid)
 {
        struct in6_addr *dest, *src;
        int ttd = req->expires - jiffies;
@@ -2058,8 +2067,8 @@ static void get_openreq6(struct seq_file *seq,
        if (ttd < 0)
                ttd = 0;
 
-       src = &req->af.v6_req.loc_addr;
-       dest = &req->af.v6_req.rmt_addr;
+       src = &tcp6_rsk(req)->loc_addr;
+       dest = &tcp6_rsk(req)->rmt_addr;
        seq_printf(seq,
                   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
                   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
@@ -2069,7 +2078,7 @@ static void get_openreq6(struct seq_file *seq,
                   ntohs(inet_sk(sk)->sport),
                   dest->s6_addr32[0], dest->s6_addr32[1],
                   dest->s6_addr32[2], dest->s6_addr32[3],
-                  ntohs(req->rmt_port),
+                  ntohs(inet_rsk(req)->rmt_port),
                   TCP_SYN_RECV,
                   0,0, /* could print option size, but that is af dependent. */
                   1,   /* timers active (only the expire timer) */  
@@ -2089,18 +2098,20 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
        unsigned long timer_expires;
        struct inet_sock *inet = inet_sk(sp);
        struct tcp_sock *tp = tcp_sk(sp);
+       const struct inet_connection_sock *icsk = inet_csk(sp);
        struct ipv6_pinfo *np = inet6_sk(sp);
 
        dest  = &np->daddr;
        src   = &np->rcv_saddr;
        destp = ntohs(inet->dport);
        srcp  = ntohs(inet->sport);
-       if (tp->pending == TCP_TIME_RETRANS) {
+
+       if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
                timer_active    = 1;
-               timer_expires   = tp->timeout;
-       } else if (tp->pending == TCP_TIME_PROBE0) {
+               timer_expires   = icsk->icsk_timeout;
+       } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
                timer_active    = 4;
-               timer_expires   = tp->timeout;
+               timer_expires   = icsk->icsk_timeout;
        } else if (timer_pending(&sp->sk_timer)) {
                timer_active    = 2;
                timer_expires   = sp->sk_timer.expires;
@@ -2121,28 +2132,31 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
                   timer_active,
                   jiffies_to_clock_t(timer_expires - jiffies),
-                  tp->retransmits,
+                  icsk->icsk_retransmits,
                   sock_i_uid(sp),
                   tp->probes_out,
                   sock_i_ino(sp),
                   atomic_read(&sp->sk_refcnt), sp,
-                  tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+                  icsk->icsk_rto,
+                  icsk->icsk_ack.ato,
+                  (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
                   tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
                   );
 }
 
 static void get_timewait6_sock(struct seq_file *seq, 
-                              struct tcp_tw_bucket *tw, int i)
+                              struct inet_timewait_sock *tw, int i)
 {
        struct in6_addr *dest, *src;
        __u16 destp, srcp;
+       struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
        int ttd = tw->tw_ttd - jiffies;
 
        if (ttd < 0)
                ttd = 0;
 
-       dest  = &tw->tw_v6_daddr;
-       src   = &tw->tw_v6_rcv_saddr;
+       dest = &tcp6tw->tw_v6_daddr;
+       src  = &tcp6tw->tw_v6_rcv_saddr;
        destp = ntohs(tw->tw_dport);
        srcp  = ntohs(tw->tw_sport);
 
@@ -2217,7 +2231,7 @@ struct proto tcpv6_prot = {
        .close                  = tcp_close,
        .connect                = tcp_v6_connect,
        .disconnect             = tcp_disconnect,
-       .accept                 = tcp_accept,
+       .accept                 = inet_csk_accept,
        .ioctl                  = tcp_ioctl,
        .init                   = tcp_v6_init_sock,
        .destroy                = tcp_v6_destroy_sock,
@@ -2234,11 +2248,14 @@ struct proto tcpv6_prot = {
        .sockets_allocated      = &tcp_sockets_allocated,
        .memory_allocated       = &tcp_memory_allocated,
        .memory_pressure        = &tcp_memory_pressure,
+       .orphan_count           = &tcp_orphan_count,
        .sysctl_mem             = sysctl_tcp_mem,
        .sysctl_wmem            = sysctl_tcp_wmem,
        .sysctl_rmem            = sysctl_tcp_rmem,
        .max_header             = MAX_TCP_HEADER,
        .obj_size               = sizeof(struct tcp6_sock),
+       .twsk_obj_size          = sizeof(struct tcp6_timewait_sock),
+       .rsk_prot               = &tcp6_request_sock_ops,
 };
 
 static struct inet6_protocol tcpv6_protocol = {
This page took 0.043791 seconds and 5 git commands to generate.