Skip to contentSkip to conversation

net: Add sock_common_listen for TCP and DCCP

PATCH In review Firo Yang 2 participants 2 messages Jun 12, 2015 – Jun 15, 2015

Subsystems (5)
lore
Share & tools
lore

Firo Yang

author
#0 lore raw

PATCH v2 1/1 net: Add sock_common_listen for TCP and DCCP

Code refactoring:
1. Move the common code of inet_listen() and inet_dccp_listen() to 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.

---
v2:
In according to the advices of Eric Dumazet, sock_common_listen() keep using TCP_xxx state instead of introducing new aliases.

Test info:
I test it on my x86 PC.

 include/net/sock.h  |  3 +++
 include/net/tcp.h   |  1 +
 net/core/sock.c     | 39 +++++++++++++++++++++++++++++++++
 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, 106 insertions(+), 105 deletions(-)
include/net/sock.h +3 -0
index 26c1c31..8066a4c 100644
@@ -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);
@@ -1587,6 +1588,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
  */
include/net/tcp.h +1 -0
index 978cebe..70d3f64 100644
@@ -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,
net/core/sock.c +39 -0
index e72633c..e839721 100644
@@ -2559,6 +2559,45 @@ 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;
+	/* Since DCCP used the same state value as TCP, here we
+	 * just check the TCP version 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) {
+		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,
net/dccp/dccp.h +1 -1
index bebc735..5a5acbb 100644
@@ -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);
net/dccp/ipv4.c +2 -2
index ccf4c56..339f253 100644
@@ -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,
net/dccp/ipv6.c +2 -1
index 5165571..1a96194 100644
@@ -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,
net/dccp/proto.c +19 -43

80 lines not on this page · raw message

net/ipv4/af_inet.c +1 -57

70 lines not on this page · raw message

net/ipv4/tcp.c +35 -0
index 65f791f..3aa185b 100644
@@ -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)
net/ipv4/tcp_ipv4.c +1 -0
index d7d4c2b..0dff9dc 100644
@@ -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,
net/ipv6/af_inet6.c +1 -1
index 7de52b6..8fd9c77 100644
@@ -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		*/
net/ipv6/tcp_ipv6.c +1 -0
index 45a7176..80cecc6 100644
@@ -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,
Signature · 1 line
2.4.3
maintainer
#1 lore raw

From: Firo Yang <[email protected]>
Date: Fri, 12 Jun 2015 12:57:57 +0800

Quoted 13 lines

Code refactoring:
1. Move the common code of inet_listen() and inet_dccp_listen() to 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.

Quoted 8 lines

---
v2:
In according to the advices of Eric Dumazet, sock_common_listen() keep using TCP_xxx state instead of introducing new aliases.

Test info:
I test it on my x86 PC.

I don't think this is worthwhile, sorry.

Instead of having two straight line copies of a piece of logic, we now have three functions and a new callback. I'd rather have a single duplicate copy of a function than all of that.