Skip to content

Commit

Permalink
[SOCK] proto: Add hashinfo member to struct proto
Browse files Browse the repository at this point in the history
This way we can remove TCP and DCCP specific versions of

sk->sk_prot->get_port: both v4 and v6 use inet_csk_get_port
sk->sk_prot->hash:     inet_hash is directly used, only v6 need
                       a specific version to deal with mapped sockets
sk->sk_prot->unhash:   both v4 and v6 use inet_hash directly

struct inet_connection_sock_af_ops also gets a new member, bind_conflict, so
that inet_csk_get_port can find the per family routine.

Now only the lookup routines receive as a parameter a struct inet_hashtable.

With this we further reuse code, reducing the difference among INET transport
protocols.

Eventually work has to be done on UDP and SCTP to make them share this
infrastructure and get as a bonus inet_diag interfaces so that iproute can be
used with these protocols.

net-2.6/net/ipv4/inet_hashtables.c:
  struct proto			     |   +8
  struct inet_connection_sock_af_ops |   +8
 2 structs changed
  __inet_hash_nolisten               |  +18
  __inet_hash                        | -210
  inet_put_port                      |   +8
  inet_bind_bucket_create            |   +1
  __inet_hash_connect                |   -8
 5 functions changed, 27 bytes added, 218 bytes removed, diff: -191

net-2.6/net/core/sock.c:
  proto_seq_show                     |   +3
 1 function changed, 3 bytes added, diff: +3

net-2.6/net/ipv4/inet_connection_sock.c:
  inet_csk_get_port                  |  +15
 1 function changed, 15 bytes added, diff: +15

net-2.6/net/ipv4/tcp.c:
  tcp_set_state                      |   -7
 1 function changed, 7 bytes removed, diff: -7

net-2.6/net/ipv4/tcp_ipv4.c:
  tcp_v4_get_port                    |  -31
  tcp_v4_hash                        |  -48
  tcp_v4_destroy_sock                |   -7
  tcp_v4_syn_recv_sock               |   -2
  tcp_unhash                         | -179
 5 functions changed, 267 bytes removed, diff: -267

net-2.6/net/ipv6/inet6_hashtables.c:
  __inet6_hash |   +8
 1 function changed, 8 bytes added, diff: +8

net-2.6/net/ipv4/inet_hashtables.c:
  inet_unhash                        | +190
  inet_hash                          | +242
 2 functions changed, 432 bytes added, diff: +432

vmlinux:
 16 functions changed, 485 bytes added, 492 bytes removed, diff: -7

/home/acme/git/net-2.6/net/ipv6/tcp_ipv6.c:
  tcp_v6_get_port                    |  -31
  tcp_v6_hash                        |   -7
  tcp_v6_syn_recv_sock               |   -9
 3 functions changed, 47 bytes removed, diff: -47

/home/acme/git/net-2.6/net/dccp/proto.c:
  dccp_destroy_sock                  |   -7
  dccp_unhash                        | -179
  dccp_hash                          |  -49
  dccp_set_state                     |   -7
  dccp_done                          |   +1
 5 functions changed, 1 bytes added, 242 bytes removed, diff: -241

/home/acme/git/net-2.6/net/dccp/ipv4.c:
  dccp_v4_get_port                   |  -31
  dccp_v4_request_recv_sock          |   -2
 2 functions changed, 33 bytes removed, diff: -33

/home/acme/git/net-2.6/net/dccp/ipv6.c:
  dccp_v6_get_port                   |  -31
  dccp_v6_hash                       |   -7
  dccp_v6_request_recv_sock          |   +5
 3 functions changed, 5 bytes added, 38 bytes removed, diff: -33

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Arnaldo Carvalho de Melo authored and David S. Miller committed Feb 3, 2008
1 parent 9dc7f30 commit ab1e0a1
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 141 deletions.
2 changes: 1 addition & 1 deletion include/net/inet6_hashtables.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}

extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
extern void __inet6_hash(struct sock *sk);

/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
Expand Down
8 changes: 3 additions & 5 deletions include/net/inet_connection_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#undef INET_CSK_CLEAR_TIMERS

struct inet_bind_bucket;
struct inet_hashinfo;
struct tcp_congestion_ops;

/*
Expand Down Expand Up @@ -59,6 +58,8 @@ struct inet_connection_sock_af_ops {
int level, int optname,
char __user *optval, int __user *optlen);
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
int (*bind_conflict)(const struct sock *sk,
const struct inet_bind_bucket *tb);
};

/** inet_connection_sock - INET connection oriented sock
Expand Down Expand Up @@ -244,10 +245,7 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
const __be32 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,
struct sock *sk, unsigned short snum,
int (*bind_conflict)(const struct sock *sk,
const struct inet_bind_bucket *tb));
extern int inet_csk_get_port(struct sock *sk, unsigned short snum);

extern struct dst_entry* inet_csk_route_req(struct sock *sk,
const struct request_sock *req);
Expand Down
51 changes: 9 additions & 42 deletions include/net/inet_hashtables.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
}

/* Caller must disable local BH processing. */
static inline void __inet_inherit_port(struct inet_hashinfo *table,
struct sock *sk, struct sock *child)
static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
{
struct inet_hashinfo *table = sk->sk_prot->hashinfo;
const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
struct inet_bind_hashbucket *head = &table->bhash[bhash];
struct inet_bind_bucket *tb;
Expand All @@ -235,15 +235,14 @@ static inline void __inet_inherit_port(struct inet_hashinfo *table,
spin_unlock(&head->lock);
}

static inline void inet_inherit_port(struct inet_hashinfo *table,
struct sock *sk, struct sock *child)
static inline void inet_inherit_port(struct sock *sk, struct sock *child)
{
local_bh_disable();
__inet_inherit_port(table, sk, child);
__inet_inherit_port(sk, child);
local_bh_enable();
}

extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
extern void inet_put_port(struct sock *sk);

extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);

Expand All @@ -266,41 +265,9 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
wake_up(&hashinfo->lhash_wait);
}

extern void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
extern void __inet_hash_nolisten(struct inet_hashinfo *hinfo, struct sock *sk);

static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
{
if (sk->sk_state != TCP_CLOSE) {
local_bh_disable();
__inet_hash(hashinfo, sk);
local_bh_enable();
}
}

static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
{
rwlock_t *lock;

if (sk_unhashed(sk))
goto out;

if (sk->sk_state == TCP_LISTEN) {
local_bh_disable();
inet_listen_wlock(hashinfo);
lock = &hashinfo->lhash_lock;
} else {
lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
write_lock_bh(lock);
}

if (__sk_del_node_init(sk))
sock_prot_inuse_add(sk->sk_prot, -1);
write_unlock_bh(lock);
out:
if (sk->sk_state == TCP_LISTEN)
wake_up(&hashinfo->lhash_wait);
}
extern void __inet_hash_nolisten(struct sock *sk);
extern void inet_hash(struct sock *sk);
extern void inet_unhash(struct sock *sk);

extern struct sock *__inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
Expand Down Expand Up @@ -425,7 +392,7 @@ extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk,
int (*check_established)(struct inet_timewait_death_row *,
struct sock *, __u16, struct inet_timewait_sock **),
void (*hash)(struct inet_hashinfo *, struct sock *));
void (*hash)(struct sock *sk));
extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
#endif /* _INET_HASHTABLES_H */
3 changes: 3 additions & 0 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);

struct request_sock_ops;
struct timewait_sock_ops;
struct inet_hashinfo;

/* Networking protocol blocks we attach to sockets.
* socket layer -> transport layer interface
Expand Down Expand Up @@ -578,6 +579,8 @@ struct proto {
struct request_sock_ops *rsk_prot;
struct timewait_sock_ops *twsk_prot;

struct inet_hashinfo *hashinfo;

struct module *owner;

char name[32];
Expand Down
2 changes: 0 additions & 2 deletions net/dccp/dccp.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,6 @@ extern struct sk_buff *dccp_make_response(struct sock *sk,

extern int dccp_connect(struct sock *sk);
extern int dccp_disconnect(struct sock *sk, int flags);
extern void dccp_hash(struct sock *sk);
extern void dccp_unhash(struct sock *sk);
extern int dccp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int dccp_setsockopt(struct sock *sk, int level, int optname,
Expand Down
18 changes: 7 additions & 11 deletions net/dccp/ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@
*/
static struct socket *dccp_v4_ctl_socket;

static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
{
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
inet_csk_bind_conflict);
}

int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
Expand Down Expand Up @@ -408,8 +402,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,

dccp_sync_mss(newsk, dst_mtu(dst));

__inet_hash_nolisten(&dccp_hashinfo, newsk);
__inet_inherit_port(&dccp_hashinfo, sk, newsk);
__inet_hash_nolisten(newsk);
__inet_inherit_port(sk, newsk);

return newsk;

Expand Down Expand Up @@ -898,6 +892,7 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
.getsockopt = ip_getsockopt,
.addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
.bind_conflict = inet_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
Expand Down Expand Up @@ -937,17 +932,18 @@ static struct proto dccp_v4_prot = {
.sendmsg = dccp_sendmsg,
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v4_do_rcv,
.hash = dccp_hash,
.unhash = dccp_unhash,
.hash = inet_hash,
.unhash = inet_unhash,
.accept = inet_csk_accept,
.get_port = dccp_v4_get_port,
.get_port = inet_csk_get_port,
.shutdown = dccp_shutdown,
.destroy = dccp_destroy_sock,
.orphan_count = &dccp_orphan_count,
.max_header = MAX_DCCP_HEADER,
.obj_size = sizeof(struct dccp_sock),
.rsk_prot = &dccp_request_sock_ops,
.twsk_prot = &dccp_timewait_sock_ops,
.hashinfo = &dccp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
Expand Down
20 changes: 8 additions & 12 deletions net/dccp/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,15 @@ static struct socket *dccp_v6_ctl_socket;
static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;

static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
{
return inet_csk_get_port(&dccp_hashinfo, sk, snum,
inet6_csk_bind_conflict);
}

static void dccp_v6_hash(struct sock *sk)
{
if (sk->sk_state != DCCP_CLOSED) {
if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
dccp_hash(sk);
inet_hash(sk);
return;
}
local_bh_disable();
__inet6_hash(&dccp_hashinfo, sk);
__inet6_hash(sk);
local_bh_enable();
}
}
Expand Down Expand Up @@ -630,8 +624,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,

newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;

__inet6_hash(&dccp_hashinfo, newsk);
inet_inherit_port(&dccp_hashinfo, sk, newsk);
__inet6_hash(newsk);
inet_inherit_port(sk, newsk);

return newsk;

Expand Down Expand Up @@ -1054,6 +1048,7 @@ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
.bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
Expand Down Expand Up @@ -1123,16 +1118,17 @@ static struct proto dccp_v6_prot = {
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v6_do_rcv,
.hash = dccp_v6_hash,
.unhash = dccp_unhash,
.unhash = inet_unhash,
.accept = inet_csk_accept,
.get_port = dccp_v6_get_port,
.get_port = inet_csk_get_port,
.shutdown = dccp_shutdown,
.destroy = dccp_v6_destroy_sock,
.orphan_count = &dccp_orphan_count,
.max_header = MAX_DCCP_HEADER,
.obj_size = sizeof(struct dccp6_sock),
.rsk_prot = &dccp6_request_sock_ops,
.twsk_prot = &dccp6_timewait_sock_ops,
.hashinfo = &dccp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
Expand Down
18 changes: 2 additions & 16 deletions net/dccp/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void dccp_set_state(struct sock *sk, const int state)
sk->sk_prot->unhash(sk);
if (inet_csk(sk)->icsk_bind_hash != NULL &&
!(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
inet_put_port(&dccp_hashinfo, sk);
inet_put_port(sk);
/* fall through */
default:
if (oldstate == DCCP_OPEN)
Expand Down Expand Up @@ -173,20 +173,6 @@ const char *dccp_state_name(const int state)

EXPORT_SYMBOL_GPL(dccp_state_name);

void dccp_hash(struct sock *sk)
{
inet_hash(&dccp_hashinfo, sk);
}

EXPORT_SYMBOL_GPL(dccp_hash);

void dccp_unhash(struct sock *sk)
{
inet_unhash(&dccp_hashinfo, sk);
}

EXPORT_SYMBOL_GPL(dccp_unhash);

int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
{
struct dccp_sock *dp = dccp_sk(sk);
Expand Down Expand Up @@ -268,7 +254,7 @@ int dccp_destroy_sock(struct sock *sk)

/* Clean up a referenced DCCP bind bucket. */
if (inet_csk(sk)->icsk_bind_hash != NULL)
inet_put_port(&dccp_hashinfo, sk);
inet_put_port(sk);

kfree(dp->dccps_service_list);
dp->dccps_service_list = NULL;
Expand Down
8 changes: 3 additions & 5 deletions net/ipv4/inet_connection_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,9 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
*/
int inet_csk_get_port(struct inet_hashinfo *hashinfo,
struct sock *sk, unsigned short snum,
int (*bind_conflict)(const struct sock *sk,
const struct inet_bind_bucket *tb))
int inet_csk_get_port(struct sock *sk, unsigned short snum)
{
struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
struct inet_bind_hashbucket *head;
struct hlist_node *node;
struct inet_bind_bucket *tb;
Expand Down Expand Up @@ -142,7 +140,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
goto success;
} else {
ret = 1;
if (bind_conflict(sk, tb))
if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
goto fail_unlock;
}
}
Expand Down
Loading

0 comments on commit ab1e0a1

Please sign in to comment.