diff options
| author | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2005-08-09 23:11:08 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:49:14 -0400 |
| commit | 3f421baa4720b708022f8bcc52a61e5cd6f10bf8 (patch) | |
| tree | e4201b1e2356cea8b7bd8d68dfba06e84002a77d /net/ipv4/tcp_ipv4.c | |
| parent | 463c84b97f24010a67cd871746d6a7e4c925a5f9 (diff) | |
[NET]: Just move the inet_connection_sock function from tcp sources
Completing the previous changeset, this also generalises tcp_v4_synq_add,
renaming it to inet_csk_reqsk_queue_hash_add, already geing used in the
DCCP tree, which I plan to merge RSN.
Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 210 |
1 files changed, 1 insertions, 209 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2cd41265d17f..2f605b9e6b67 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -97,138 +97,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | |||
| 97 | .port_rover = 1024 - 1, | 97 | .port_rover = 1024 - 1, |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | /* | ||
| 101 | * This array holds the first and last local port number. | ||
| 102 | * For high-usage systems, use sysctl to change this to | ||
| 103 | * 32768-61000 | ||
| 104 | */ | ||
| 105 | int sysctl_local_port_range[2] = { 1024, 4999 }; | ||
| 106 | |||
| 107 | static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucket *tb) | ||
| 108 | { | ||
| 109 | const u32 sk_rcv_saddr = inet_rcv_saddr(sk); | ||
| 110 | struct sock *sk2; | ||
| 111 | struct hlist_node *node; | ||
| 112 | int reuse = sk->sk_reuse; | ||
| 113 | |||
| 114 | sk_for_each_bound(sk2, node, &tb->owners) { | ||
| 115 | if (sk != sk2 && | ||
| 116 | !inet_v6_ipv6only(sk2) && | ||
| 117 | (!sk->sk_bound_dev_if || | ||
| 118 | !sk2->sk_bound_dev_if || | ||
| 119 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { | ||
| 120 | if (!reuse || !sk2->sk_reuse || | ||
| 121 | sk2->sk_state == TCP_LISTEN) { | ||
| 122 | const u32 sk2_rcv_saddr = inet_rcv_saddr(sk2); | ||
| 123 | if (!sk2_rcv_saddr || !sk_rcv_saddr || | ||
| 124 | sk2_rcv_saddr == sk_rcv_saddr) | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | } | ||
| 129 | return node != NULL; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Obtain a reference to a local port for the given sock, | ||
| 133 | * if snum is zero it means select any available local port. | ||
| 134 | */ | ||
| 135 | int inet_csk_get_port(struct inet_hashinfo *hashinfo, | ||
| 136 | struct sock *sk, unsigned short snum) | ||
| 137 | { | ||
| 138 | struct inet_bind_hashbucket *head; | ||
| 139 | struct hlist_node *node; | ||
| 140 | struct inet_bind_bucket *tb; | ||
| 141 | int ret; | ||
| 142 | |||
| 143 | local_bh_disable(); | ||
| 144 | if (!snum) { | ||
| 145 | int low = sysctl_local_port_range[0]; | ||
| 146 | int high = sysctl_local_port_range[1]; | ||
| 147 | int remaining = (high - low) + 1; | ||
| 148 | int rover; | ||
| 149 | |||
| 150 | spin_lock(&hashinfo->portalloc_lock); | ||
| 151 | if (hashinfo->port_rover < low) | ||
| 152 | rover = low; | ||
| 153 | else | ||
| 154 | rover = hashinfo->port_rover; | ||
| 155 | do { | ||
| 156 | rover++; | ||
| 157 | if (rover > high) | ||
| 158 | rover = low; | ||
| 159 | head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; | ||
| 160 | spin_lock(&head->lock); | ||
| 161 | inet_bind_bucket_for_each(tb, node, &head->chain) | ||
| 162 | if (tb->port == rover) | ||
| 163 | goto next; | ||
| 164 | break; | ||
| 165 | next: | ||
| 166 | spin_unlock(&head->lock); | ||
| 167 | } while (--remaining > 0); | ||
| 168 | hashinfo->port_rover = rover; | ||
| 169 | spin_unlock(&hashinfo->portalloc_lock); | ||
| 170 | |||
| 171 | /* Exhausted local port range during search? It is not | ||
| 172 | * possible for us to be holding one of the bind hash | ||
| 173 | * locks if this test triggers, because if 'remaining' | ||
| 174 | * drops to zero, we broke out of the do/while loop at | ||
| 175 | * the top level, not from the 'break;' statement. | ||
| 176 | */ | ||
| 177 | ret = 1; | ||
| 178 | if (unlikely(remaining <= 0)) | ||
| 179 | goto fail; | ||
| 180 | |||
| 181 | /* OK, here is the one we will use. HEAD is | ||
| 182 | * non-NULL and we hold it's mutex. | ||
| 183 | */ | ||
| 184 | snum = rover; | ||
| 185 | } else { | ||
| 186 | head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)]; | ||
| 187 | spin_lock(&head->lock); | ||
| 188 | inet_bind_bucket_for_each(tb, node, &head->chain) | ||
| 189 | if (tb->port == snum) | ||
| 190 | goto tb_found; | ||
| 191 | } | ||
| 192 | tb = NULL; | ||
| 193 | goto tb_not_found; | ||
| 194 | tb_found: | ||
| 195 | if (!hlist_empty(&tb->owners)) { | ||
| 196 | if (sk->sk_reuse > 1) | ||
| 197 | goto success; | ||
| 198 | if (tb->fastreuse > 0 && | ||
| 199 | sk->sk_reuse && sk->sk_state != TCP_LISTEN) { | ||
| 200 | goto success; | ||
| 201 | } else { | ||
| 202 | ret = 1; | ||
| 203 | if (inet_csk_bind_conflict(sk, tb)) | ||
| 204 | goto fail_unlock; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | tb_not_found: | ||
| 208 | ret = 1; | ||
| 209 | if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, head, snum)) == NULL) | ||
| 210 | goto fail_unlock; | ||
| 211 | if (hlist_empty(&tb->owners)) { | ||
| 212 | if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) | ||
| 213 | tb->fastreuse = 1; | ||
| 214 | else | ||
| 215 | tb->fastreuse = 0; | ||
| 216 | } else if (tb->fastreuse && | ||
| 217 | (!sk->sk_reuse || sk->sk_state == TCP_LISTEN)) | ||
| 218 | tb->fastreuse = 0; | ||
| 219 | success: | ||
| 220 | if (!inet_csk(sk)->icsk_bind_hash) | ||
| 221 | inet_bind_hash(sk, tb, snum); | ||
| 222 | BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb); | ||
| 223 | ret = 0; | ||
| 224 | |||
| 225 | fail_unlock: | ||
| 226 | spin_unlock(&head->lock); | ||
| 227 | fail: | ||
| 228 | local_bh_enable(); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) | 100 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) |
| 233 | { | 101 | { |
| 234 | return inet_csk_get_port(&tcp_hashinfo, sk, snum); | 102 | return inet_csk_get_port(&tcp_hashinfo, sk, snum); |
| @@ -568,52 +436,6 @@ static inline int inet_iif(const struct sk_buff *skb) | |||
| 568 | return ((struct rtable *)skb->dst)->rt_iif; | 436 | return ((struct rtable *)skb->dst)->rt_iif; |
| 569 | } | 437 | } |
| 570 | 438 | ||
| 571 | static inline u32 inet_synq_hash(const u32 raddr, const u16 rport, | ||
| 572 | const u32 rnd, const u16 synq_hsize) | ||
| 573 | { | ||
| 574 | return jhash_2words(raddr, (u32)rport, rnd) & (synq_hsize - 1); | ||
| 575 | } | ||
| 576 | |||
| 577 | struct request_sock *inet_csk_search_req(const struct sock *sk, | ||
| 578 | struct request_sock ***prevp, | ||
| 579 | const __u16 rport, const __u32 raddr, | ||
| 580 | const __u32 laddr) | ||
| 581 | { | ||
| 582 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 583 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; | ||
| 584 | struct request_sock *req, **prev; | ||
| 585 | |||
| 586 | for (prev = &lopt->syn_table[inet_synq_hash(raddr, rport, lopt->hash_rnd, | ||
| 587 | lopt->nr_table_entries)]; | ||
| 588 | (req = *prev) != NULL; | ||
| 589 | prev = &req->dl_next) { | ||
| 590 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
| 591 | |||
| 592 | if (ireq->rmt_port == rport && | ||
| 593 | ireq->rmt_addr == raddr && | ||
| 594 | ireq->loc_addr == laddr && | ||
| 595 | AF_INET_FAMILY(req->rsk_ops->family)) { | ||
| 596 | BUG_TRAP(!req->sk); | ||
| 597 | *prevp = prev; | ||
| 598 | break; | ||
| 599 | } | ||
| 600 | } | ||
| 601 | |||
| 602 | return req; | ||
| 603 | } | ||
| 604 | |||
| 605 | static void tcp_v4_synq_add(struct sock *sk, struct request_sock *req) | ||
| 606 | { | ||
| 607 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 608 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; | ||
| 609 | const u32 h = inet_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, | ||
| 610 | lopt->hash_rnd, lopt->nr_table_entries); | ||
| 611 | |||
| 612 | reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT); | ||
| 613 | inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT); | ||
| 614 | } | ||
| 615 | |||
| 616 | |||
| 617 | /* | 439 | /* |
| 618 | * This routine does path mtu discovery as defined in RFC1191. | 440 | * This routine does path mtu discovery as defined in RFC1191. |
| 619 | */ | 441 | */ |
| @@ -963,36 +785,6 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | |||
| 963 | req->ts_recent); | 785 | req->ts_recent); |
| 964 | } | 786 | } |
| 965 | 787 | ||
| 966 | struct dst_entry* inet_csk_route_req(struct sock *sk, | ||
| 967 | const struct request_sock *req) | ||
| 968 | { | ||
| 969 | struct rtable *rt; | ||
| 970 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
| 971 | struct ip_options *opt = inet_rsk(req)->opt; | ||
| 972 | struct flowi fl = { .oif = sk->sk_bound_dev_if, | ||
| 973 | .nl_u = { .ip4_u = | ||
| 974 | { .daddr = ((opt && opt->srr) ? | ||
| 975 | opt->faddr : | ||
| 976 | ireq->rmt_addr), | ||
| 977 | .saddr = ireq->loc_addr, | ||
| 978 | .tos = RT_CONN_FLAGS(sk) } }, | ||
| 979 | .proto = sk->sk_protocol, | ||
| 980 | .uli_u = { .ports = | ||
| 981 | { .sport = inet_sk(sk)->sport, | ||
| 982 | .dport = ireq->rmt_port } } }; | ||
| 983 | |||
| 984 | if (ip_route_output_flow(&rt, &fl, sk, 0)) { | ||
| 985 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | ||
| 986 | return NULL; | ||
| 987 | } | ||
| 988 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) { | ||
| 989 | ip_rt_put(rt); | ||
| 990 | IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | ||
| 991 | return NULL; | ||
| 992 | } | ||
| 993 | return &rt->u.dst; | ||
| 994 | } | ||
| 995 | |||
| 996 | /* | 788 | /* |
| 997 | * Send a SYN-ACK after having received an ACK. | 789 | * Send a SYN-ACK after having received an ACK. |
| 998 | * This still operates on a request_sock only, not on a big | 790 | * This still operates on a request_sock only, not on a big |
| @@ -1222,7 +1014,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1222 | if (want_cookie) { | 1014 | if (want_cookie) { |
| 1223 | reqsk_free(req); | 1015 | reqsk_free(req); |
| 1224 | } else { | 1016 | } else { |
| 1225 | tcp_v4_synq_add(sk, req); | 1017 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
| 1226 | } | 1018 | } |
| 1227 | return 0; | 1019 | return 0; |
| 1228 | 1020 | ||
