mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-07 23:11:27 +00:00
[IPV6]: Reuse inet_csk_get_port in tcp_v6_get_port
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
89cee8b1cb
commit
971af18bbf
5 changed files with 21 additions and 97 deletions
|
@ -192,8 +192,12 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
|
||||||
const __u16 rport,
|
const __u16 rport,
|
||||||
const __u32 raddr,
|
const __u32 raddr,
|
||||||
const __u32 laddr);
|
const __u32 laddr);
|
||||||
|
extern int inet_csk_bind_conflict(const struct sock *sk,
|
||||||
|
const struct inet_bind_bucket *tb);
|
||||||
extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
|
extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
|
||||||
struct sock *sk, unsigned short snum);
|
struct sock *sk, unsigned short snum,
|
||||||
|
int (*bind_conflict)(const struct sock *sk,
|
||||||
|
const struct inet_bind_bucket *tb));
|
||||||
|
|
||||||
extern struct dst_entry* inet_csk_route_req(struct sock *sk,
|
extern struct dst_entry* inet_csk_route_req(struct sock *sk,
|
||||||
const struct request_sock *req);
|
const struct request_sock *req);
|
||||||
|
|
|
@ -37,7 +37,8 @@ EXPORT_SYMBOL_GPL(dccp_hashinfo);
|
||||||
|
|
||||||
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
|
static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
|
||||||
{
|
{
|
||||||
return inet_csk_get_port(&dccp_hashinfo, sk, snum);
|
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
|
||||||
|
inet_csk_bind_conflict);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dccp_v4_hash(struct sock *sk)
|
static void dccp_v4_hash(struct sock *sk)
|
||||||
|
|
|
@ -37,7 +37,8 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg);
|
||||||
*/
|
*/
|
||||||
int sysctl_local_port_range[2] = { 1024, 4999 };
|
int sysctl_local_port_range[2] = { 1024, 4999 };
|
||||||
|
|
||||||
static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucket *tb)
|
int inet_csk_bind_conflict(const struct sock *sk,
|
||||||
|
const struct inet_bind_bucket *tb)
|
||||||
{
|
{
|
||||||
const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
|
const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
|
||||||
struct sock *sk2;
|
struct sock *sk2;
|
||||||
|
@ -62,11 +63,15 @@ static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucke
|
||||||
return node != NULL;
|
return node != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
|
||||||
|
|
||||||
/* Obtain a reference to a local port for the given sock,
|
/* Obtain a reference to a local port for the given sock,
|
||||||
* if snum is zero it means select any available local port.
|
* if snum is zero it means select any available local port.
|
||||||
*/
|
*/
|
||||||
int inet_csk_get_port(struct inet_hashinfo *hashinfo,
|
int inet_csk_get_port(struct inet_hashinfo *hashinfo,
|
||||||
struct sock *sk, unsigned short snum)
|
struct sock *sk, unsigned short snum,
|
||||||
|
int (*bind_conflict)(const struct sock *sk,
|
||||||
|
const struct inet_bind_bucket *tb))
|
||||||
{
|
{
|
||||||
struct inet_bind_hashbucket *head;
|
struct inet_bind_hashbucket *head;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
|
@ -125,7 +130,7 @@ tb_found:
|
||||||
goto success;
|
goto success;
|
||||||
} else {
|
} else {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
if (inet_csk_bind_conflict(sk, tb))
|
if (bind_conflict(sk, tb))
|
||||||
goto fail_unlock;
|
goto fail_unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,8 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
|
||||||
|
|
||||||
static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
|
static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
|
||||||
{
|
{
|
||||||
return inet_csk_get_port(&tcp_hashinfo, sk, snum);
|
return inet_csk_get_port(&tcp_hashinfo, sk, snum,
|
||||||
|
inet_csk_bind_conflict);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcp_v4_hash(struct sock *sk)
|
static void tcp_v4_hash(struct sock *sk)
|
||||||
|
|
|
@ -76,8 +76,8 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok);
|
||||||
static struct tcp_func ipv6_mapped;
|
static struct tcp_func ipv6_mapped;
|
||||||
static struct tcp_func ipv6_specific;
|
static struct tcp_func ipv6_specific;
|
||||||
|
|
||||||
static inline int tcp_v6_bind_conflict(const struct sock *sk,
|
int inet6_csk_bind_conflict(const struct sock *sk,
|
||||||
const struct inet_bind_bucket *tb)
|
const struct inet_bind_bucket *tb)
|
||||||
{
|
{
|
||||||
const struct sock *sk2;
|
const struct sock *sk2;
|
||||||
const struct hlist_node *node;
|
const struct hlist_node *node;
|
||||||
|
@ -97,97 +97,10 @@ static inline int tcp_v6_bind_conflict(const struct sock *sk,
|
||||||
return node != NULL;
|
return node != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grrr, addr_type already calculated by caller, but I don't want
|
|
||||||
* to add some silly "cookie" argument to this method just for that.
|
|
||||||
* But it doesn't matter, the recalculation is in the rarest path
|
|
||||||
* this function ever takes.
|
|
||||||
*/
|
|
||||||
static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
|
static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
|
||||||
{
|
{
|
||||||
struct inet_bind_hashbucket *head;
|
return inet_csk_get_port(&tcp_hashinfo, sk, snum,
|
||||||
struct inet_bind_bucket *tb;
|
inet6_csk_bind_conflict);
|
||||||
struct hlist_node *node;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
local_bh_disable();
|
|
||||||
if (snum == 0) {
|
|
||||||
int low = sysctl_local_port_range[0];
|
|
||||||
int high = sysctl_local_port_range[1];
|
|
||||||
int remaining = (high - low) + 1;
|
|
||||||
int rover = net_random() % (high - low) + low;
|
|
||||||
|
|
||||||
do {
|
|
||||||
head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)];
|
|
||||||
spin_lock(&head->lock);
|
|
||||||
inet_bind_bucket_for_each(tb, node, &head->chain)
|
|
||||||
if (tb->port == rover)
|
|
||||||
goto next;
|
|
||||||
break;
|
|
||||||
next:
|
|
||||||
spin_unlock(&head->lock);
|
|
||||||
if (++rover > high)
|
|
||||||
rover = low;
|
|
||||||
} while (--remaining > 0);
|
|
||||||
|
|
||||||
/* 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 (unlikely(remaining <= 0))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* OK, here is the one we will use. */
|
|
||||||
snum = rover;
|
|
||||||
} else {
|
|
||||||
head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
|
|
||||||
spin_lock(&head->lock);
|
|
||||||
inet_bind_bucket_for_each(tb, node, &head->chain)
|
|
||||||
if (tb->port == snum)
|
|
||||||
goto tb_found;
|
|
||||||
}
|
|
||||||
tb = NULL;
|
|
||||||
goto tb_not_found;
|
|
||||||
tb_found:
|
|
||||||
if (tb && !hlist_empty(&tb->owners)) {
|
|
||||||
if (tb->fastreuse > 0 && sk->sk_reuse &&
|
|
||||||
sk->sk_state != TCP_LISTEN) {
|
|
||||||
goto success;
|
|
||||||
} else {
|
|
||||||
ret = 1;
|
|
||||||
if (tcp_v6_bind_conflict(sk, tb))
|
|
||||||
goto fail_unlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tb_not_found:
|
|
||||||
ret = 1;
|
|
||||||
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;
|
|
||||||
else
|
|
||||||
tb->fastreuse = 0;
|
|
||||||
} else if (tb->fastreuse &&
|
|
||||||
(!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
|
|
||||||
tb->fastreuse = 0;
|
|
||||||
|
|
||||||
success:
|
|
||||||
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:
|
|
||||||
spin_unlock(&head->lock);
|
|
||||||
fail:
|
|
||||||
local_bh_enable();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void __tcp_v6_hash(struct sock *sk)
|
static __inline__ void __tcp_v6_hash(struct sock *sk)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue