Code refactoring:
1. Move the common code of inet_listen() and inet_dccp_listen() to
sock_common_listen().
Add new state SOCK_LISTEN and SOCK_CLOSE for sock_common_listen().

2. Modify and rename inet_listen() to tcp_listen().

3. Modify and rename inet_dccp_listen() to dccp_listen().

4. Add new callback pointer listen in struct proto for
tcp_listen() and dccp_listen().

This patch makes codes more modularized and removes redudant codes.

Signed-off-by: Firo Yang <fir...@gmail.com>
---
I test it on my x86 pc.

 include/net/sock.h  | 18 ++++++++++++++++
 include/net/tcp.h   |  1 +
 net/core/sock.c     | 36 +++++++++++++++++++++++++++++++
 net/dccp/dccp.h     |  2 +-
 net/dccp/ipv4.c     |  4 ++--
 net/dccp/ipv6.c     |  3 ++-
 net/dccp/proto.c    | 62 ++++++++++++++++-------------------------------------
 net/ipv4/af_inet.c  | 58 +------------------------------------------------
 net/ipv4/tcp.c      | 35 ++++++++++++++++++++++++++++++
 net/ipv4/tcp_ipv4.c |  1 +
 net/ipv6/af_inet6.c |  2 +-
 net/ipv6/tcp_ipv6.c |  1 +
 12 files changed, 118 insertions(+), 105 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 26c1c31..5adc7f4 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -934,6 +934,7 @@ struct proto {
        int                     (*connect)(struct sock *sk,
                                        struct sockaddr *uaddr,
                                        int addr_len);
+       int                     (*listen)(struct sock *sk, int backlog);
        int                     (*disconnect)(struct sock *sk, int flags);
 
        struct sock *           (*accept)(struct sock *sk, int flags, int *err);
@@ -1349,6 +1350,21 @@ void sk_prot_clear_portaddr_nulls(struct sock *sk, int 
size);
 #define SOCK_BINDADDR_LOCK     4
 #define SOCK_BINDPORT_LOCK     8
 
+/*
+ * Sock common state
+ * These values must be enqual to correspondent TCP state
+ * and DCCP state.
+ */
+enum {
+       SOCK_CLOSE      = TCP_CLOSE,
+       SOCK_LISTEN     = TCP_LISTEN
+};
+
+enum {
+       SOCKF_CLOSE     = TCPF_CLOSE,
+       SOCKF_LISTEN    = TCPF_LISTEN,
+};
+
 struct socket_alloc {
        struct socket socket;
        struct inode vfs_inode;
@@ -1587,6 +1603,8 @@ int compat_sock_common_setsockopt(struct socket *sock, 
int level,
 
 void sk_common_release(struct sock *sk);
 
+int sock_common_listen(struct socket *sock, int backlog);
+
 /*
  *     Default socket callbacks and setup code
  */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 978cebe..70d3f64 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -434,6 +434,7 @@ int compat_tcp_setsockopt(struct sock *sk, int level, int 
optname,
                          char __user *optval, unsigned int optlen);
 void tcp_set_keepalive(struct sock *sk, int val);
 void tcp_syn_ack_timeout(const struct request_sock *req);
+int tcp_listen(struct sock *sk, int backlog);
 int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
                int flags, int *addr_len);
 void tcp_parse_options(const struct sk_buff *skb,
diff --git a/net/core/sock.c b/net/core/sock.c
index e72633c..8016a1e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2559,6 +2559,42 @@ int sock_common_recvmsg(struct socket *sock, struct 
msghdr *msg, size_t size,
 EXPORT_SYMBOL(sock_common_recvmsg);
 
 /*
+ *     Move a socket into listening state.
+ */
+int sock_common_listen(struct socket *sock, int backlog)
+{
+       struct sock *sk = sock->sk;
+       unsigned char old_state;
+       int err;
+
+       lock_sock(sk);
+
+       err = -EINVAL;
+       if (sock->state != SS_UNCONNECTED)
+               goto out;
+
+       old_state = sk->sk_state;
+       if (!((1 << old_state) & (SOCKF_CLOSE | SOCKF_LISTEN)))
+               goto out;
+
+       /* Really, if the socket is already in listen state
+        * we can only allow the backlog to be adjusted.
+        */
+       if (old_state != SOCK_LISTEN) {
+               err = sk->sk_prot->listen(sk, backlog);
+               if (err)
+                       goto out;
+       }
+       sk->sk_max_ack_backlog = backlog;
+       err = 0;
+
+out:
+       release_sock(sk);
+       return err;
+}
+EXPORT_SYMBOL(sock_common_listen);
+
+/*
  *     Set socket options on an inet socket.
  */
 int sock_common_setsockopt(struct socket *sock, int level, int optname,
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index bebc735..5a5acbb 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -313,7 +313,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, 
size_t size);
 int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
                 int flags, int *addr_len);
 void dccp_shutdown(struct sock *sk, int how);
-int inet_dccp_listen(struct socket *sock, int backlog);
+int dccp_listen(struct sock *sk, int backlog);
 unsigned int dccp_poll(struct file *file, struct socket *sock,
                       poll_table *wait);
 int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index ccf4c56..339f253 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -952,6 +952,7 @@ static struct proto dccp_v4_prot = {
        .name                   = "DCCP",
        .owner                  = THIS_MODULE,
        .close                  = dccp_close,
+       .listen                 = dccp_listen,
        .connect                = dccp_v4_connect,
        .disconnect             = dccp_disconnect,
        .ioctl                  = dccp_ioctl,
@@ -1000,8 +1001,7 @@ static const struct proto_ops inet_dccp_ops = {
        /* FIXME: work on tcp_poll to rename it to inet_csk_poll */
        .poll              = dccp_poll,
        .ioctl             = inet_ioctl,
-       /* FIXME: work on inet_listen to rename it to sock_common_listen */
-       .listen            = inet_dccp_listen,
+       .listen            = sock_common_listen,
        .shutdown          = inet_shutdown,
        .setsockopt        = sock_common_setsockopt,
        .getsockopt        = sock_common_getsockopt,
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 5165571..1a96194 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -1011,6 +1011,7 @@ static struct proto dccp_v6_prot = {
        .name              = "DCCPv6",
        .owner             = THIS_MODULE,
        .close             = dccp_close,
+       .listen            = dccp_listen,
        .connect           = dccp_v6_connect,
        .disconnect        = dccp_disconnect,
        .ioctl             = dccp_ioctl,
@@ -1056,7 +1057,7 @@ static const struct proto_ops inet6_dccp_ops = {
        .getname           = inet6_getname,
        .poll              = dccp_poll,
        .ioctl             = inet6_ioctl,
-       .listen            = inet_dccp_listen,
+       .listen            = sock_common_listen,
        .shutdown          = inet_shutdown,
        .setsockopt        = sock_common_setsockopt,
        .getsockopt        = sock_common_getsockopt,
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 52a9401..097edab 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -231,17 +231,31 @@ void dccp_destroy_sock(struct sock *sk)
 
 EXPORT_SYMBOL_GPL(dccp_destroy_sock);
 
-static inline int dccp_listen_start(struct sock *sk, int backlog)
+int dccp_listen(struct sock *sk, int backlog)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
+       struct socket *sock = sk->sk_socket;
+       struct dccp_sock *dp;
+       int err;
 
+       err = -EINVAL;
+       if (sock->type != SOCK_DCCP)
+               goto out;
+
+       dp = dccp_sk(sk);
        dp->dccps_role = DCCP_ROLE_LISTEN;
        /* do not start to listen if feature negotiation setup fails */
-       if (dccp_feat_finalise_settings(dp))
-               return -EPROTO;
-       return inet_csk_listen_start(sk, backlog);
+       if (dccp_feat_finalise_settings(dp)) {
+               err = -EPROTO;
+               goto out;
+       }
+       err = inet_csk_listen_start(sk, backlog);
+
+out:
+       return err;
 }
 
+EXPORT_SYMBOL_GPL(dccp_listen);
+
 static inline int dccp_need_reset(int state)
 {
        return state != DCCP_CLOSED && state != DCCP_LISTEN &&
@@ -913,44 +927,6 @@ out:
 
 EXPORT_SYMBOL_GPL(dccp_recvmsg);
 
-int inet_dccp_listen(struct socket *sock, int backlog)
-{
-       struct sock *sk = sock->sk;
-       unsigned char old_state;
-       int err;
-
-       lock_sock(sk);
-
-       err = -EINVAL;
-       if (sock->state != SS_UNCONNECTED || sock->type != SOCK_DCCP)
-               goto out;
-
-       old_state = sk->sk_state;
-       if (!((1 << old_state) & (DCCPF_CLOSED | DCCPF_LISTEN)))
-               goto out;
-
-       /* Really, if the socket is already in listen state
-        * we can only allow the backlog to be adjusted.
-        */
-       if (old_state != DCCP_LISTEN) {
-               /*
-                * FIXME: here it probably should be sk->sk_prot->listen_start
-                * see tcp_listen_start
-                */
-               err = dccp_listen_start(sk, backlog);
-               if (err)
-                       goto out;
-       }
-       sk->sk_max_ack_backlog = backlog;
-       err = 0;
-
-out:
-       release_sock(sk);
-       return err;
-}
-
-EXPORT_SYMBOL_GPL(inet_dccp_listen);
-
 static void dccp_terminate_connection(struct sock *sk)
 {
        u8 next_state = DCCP_CLOSED;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index cc858ef..e2e2b19 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -187,62 +187,6 @@ static int inet_autobind(struct sock *sk)
 }
 
 /*
- *     Move a socket into listening state.
- */
-int inet_listen(struct socket *sock, int backlog)
-{
-       struct sock *sk = sock->sk;
-       unsigned char old_state;
-       int err;
-
-       lock_sock(sk);
-
-       err = -EINVAL;
-       if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
-               goto out;
-
-       old_state = sk->sk_state;
-       if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
-               goto out;
-
-       /* Really, if the socket is already in listen state
-        * we can only allow the backlog to be adjusted.
-        */
-       if (old_state != TCP_LISTEN) {
-               /* Check special setups for testing purpose to enable TFO w/o
-                * requiring TCP_FASTOPEN sockopt.
-                * Note that only TCP sockets (SOCK_STREAM) will reach here.
-                * Also fastopenq may already been allocated because this
-                * socket was in TCP_LISTEN state previously but was
-                * shutdown() (rather than close()).
-                */
-               if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) != 0 &&
-                   !inet_csk(sk)->icsk_accept_queue.fastopenq) {
-                       if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) != 0)
-                               err = fastopen_init_queue(sk, backlog);
-                       else if ((sysctl_tcp_fastopen &
-                                 TFO_SERVER_WO_SOCKOPT2) != 0)
-                               err = fastopen_init_queue(sk,
-                                   ((uint)sysctl_tcp_fastopen) >> 16);
-                       else
-                               err = 0;
-                       if (err)
-                               goto out;
-               }
-               err = inet_csk_listen_start(sk, backlog);
-               if (err)
-                       goto out;
-       }
-       sk->sk_max_ack_backlog = backlog;
-       err = 0;
-
-out:
-       release_sock(sk);
-       return err;
-}
-EXPORT_SYMBOL(inet_listen);
-
-/*
  *     Create an inet socket.
  */
 
@@ -903,7 +847,7 @@ const struct proto_ops inet_stream_ops = {
        .getname           = inet_getname,
        .poll              = tcp_poll,
        .ioctl             = inet_ioctl,
-       .listen            = inet_listen,
+       .listen            = sock_common_listen,
        .shutdown          = inet_shutdown,
        .setsockopt        = sock_common_setsockopt,
        .getsockopt        = sock_common_getsockopt,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 65f791f..3aa185b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1301,6 +1301,41 @@ out_err:
 }
 EXPORT_SYMBOL(tcp_sendmsg);
 
+int tcp_listen(struct sock *sk, int backlog)
+{
+       struct socket *sock = sk->sk_socket;
+       int err;
+
+       err = -EINVAL;
+       if (sock->type != SOCK_STREAM)
+               goto out;
+       /* Check special setups for testing purpose to enable TFO w/o
+        * requiring TCP_FASTOPEN sockopt.
+        * Note that only TCP sockets (SOCK_STREAM) will reach here.
+        * Also fastopenq may already been allocated because this
+        * socket was in TCP_LISTEN state previously but was
+        * shutdown() (rather than close()).
+        */
+       if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) != 0 &&
+           !inet_csk(sk)->icsk_accept_queue.fastopenq) {
+               if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) != 0)
+                       err = fastopen_init_queue(sk, backlog);
+               else if ((sysctl_tcp_fastopen &
+                         TFO_SERVER_WO_SOCKOPT2) != 0)
+                       err = fastopen_init_queue(sk,
+                           ((uint)sysctl_tcp_fastopen) >> 16);
+               else
+                       err = 0;
+               if (err)
+                       goto out;
+       }
+       err = inet_csk_listen_start(sk, backlog);
+
+out:
+       return err;
+}
+EXPORT_SYMBOL(tcp_listen);
+
 /*
  *     Handle reading urgent data. BSD has very simple semantics for
  *     this, no blocking and very strange errors 8)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d7d4c2b..0dff9dc 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2337,6 +2337,7 @@ struct proto tcp_prot = {
        .name                   = "TCP",
        .owner                  = THIS_MODULE,
        .close                  = tcp_close,
+       .listen                 = tcp_listen,
        .connect                = tcp_v4_connect,
        .disconnect             = tcp_disconnect,
        .accept                 = inet_csk_accept,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 7de52b6..8fd9c77 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -516,7 +516,7 @@ const struct proto_ops inet6_stream_ops = {
        .getname           = inet6_getname,
        .poll              = tcp_poll,                  /* ok           */
        .ioctl             = inet6_ioctl,               /* must change  */
-       .listen            = inet_listen,               /* ok           */
+       .listen            = sock_common_listen,        /* ok           */
        .shutdown          = inet_shutdown,             /* ok           */
        .setsockopt        = sock_common_setsockopt,    /* ok           */
        .getsockopt        = sock_common_getsockopt,    /* ok           */
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 45a7176..80cecc6 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1822,6 +1822,7 @@ struct proto tcpv6_prot = {
        .name                   = "TCPv6",
        .owner                  = THIS_MODULE,
        .close                  = tcp_close,
+       .listen                 = tcp_listen,
        .connect                = tcp_v6_connect,
        .disconnect             = tcp_disconnect,
        .accept                 = inet_csk_accept,
-- 
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to