xref: /openbmc/linux/net/rds/tcp_listen.c (revision cc8bbe1a)
1 /*
2  * Copyright (c) 2006 Oracle.  All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  *
32  */
33 #include <linux/kernel.h>
34 #include <linux/gfp.h>
35 #include <linux/in.h>
36 #include <net/tcp.h>
37 
38 #include "rds.h"
39 #include "tcp.h"
40 
41 int rds_tcp_keepalive(struct socket *sock)
42 {
43 	/* values below based on xs_udp_default_timeout */
44 	int keepidle = 5; /* send a probe 'keepidle' secs after last data */
45 	int keepcnt = 5; /* number of unack'ed probes before declaring dead */
46 	int keepalive = 1;
47 	int ret = 0;
48 
49 	ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
50 				(char *)&keepalive, sizeof(keepalive));
51 	if (ret < 0)
52 		goto bail;
53 
54 	ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT,
55 				(char *)&keepcnt, sizeof(keepcnt));
56 	if (ret < 0)
57 		goto bail;
58 
59 	ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE,
60 				(char *)&keepidle, sizeof(keepidle));
61 	if (ret < 0)
62 		goto bail;
63 
64 	/* KEEPINTVL is the interval between successive probes. We follow
65 	 * the model in xs_tcp_finish_connecting() and re-use keepidle.
66 	 */
67 	ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL,
68 				(char *)&keepidle, sizeof(keepidle));
69 bail:
70 	return ret;
71 }
72 
73 int rds_tcp_accept_one(struct socket *sock)
74 {
75 	struct socket *new_sock = NULL;
76 	struct rds_connection *conn;
77 	int ret;
78 	struct inet_sock *inet;
79 	struct rds_tcp_connection *rs_tcp;
80 
81 	ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
82 			       sock->sk->sk_type, sock->sk->sk_protocol,
83 			       &new_sock);
84 	if (ret)
85 		goto out;
86 
87 	new_sock->type = sock->type;
88 	new_sock->ops = sock->ops;
89 	ret = sock->ops->accept(sock, new_sock, O_NONBLOCK);
90 	if (ret < 0)
91 		goto out;
92 
93 	ret = rds_tcp_keepalive(new_sock);
94 	if (ret < 0)
95 		goto out;
96 
97 	rds_tcp_tune(new_sock);
98 
99 	inet = inet_sk(new_sock->sk);
100 
101 	rdsdebug("accepted tcp %pI4:%u -> %pI4:%u\n",
102 		 &inet->inet_saddr, ntohs(inet->inet_sport),
103 		 &inet->inet_daddr, ntohs(inet->inet_dport));
104 
105 	conn = rds_conn_create(sock_net(sock->sk),
106 			       inet->inet_saddr, inet->inet_daddr,
107 			       &rds_tcp_transport, GFP_KERNEL);
108 	if (IS_ERR(conn)) {
109 		ret = PTR_ERR(conn);
110 		goto out;
111 	}
112 	/* An incoming SYN request came in, and TCP just accepted it.
113 	 *
114 	 * If the client reboots, this conn will need to be cleaned up.
115 	 * rds_tcp_state_change() will do that cleanup
116 	 */
117 	rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data;
118 	if (rs_tcp->t_sock &&
119 	    ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
120 		struct sock *nsk = new_sock->sk;
121 
122 		nsk->sk_user_data = NULL;
123 		nsk->sk_prot->disconnect(nsk, 0);
124 		tcp_done(nsk);
125 		new_sock = NULL;
126 		ret = 0;
127 		goto out;
128 	} else if (rs_tcp->t_sock) {
129 		rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
130 		conn->c_outgoing = 0;
131 	}
132 
133 	rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
134 	rds_tcp_set_callbacks(new_sock, conn);
135 	rds_connect_complete(conn);
136 	new_sock = NULL;
137 	ret = 0;
138 
139 out:
140 	if (new_sock)
141 		sock_release(new_sock);
142 	return ret;
143 }
144 
145 void rds_tcp_listen_data_ready(struct sock *sk)
146 {
147 	void (*ready)(struct sock *sk);
148 
149 	rdsdebug("listen data ready sk %p\n", sk);
150 
151 	read_lock(&sk->sk_callback_lock);
152 	ready = sk->sk_user_data;
153 	if (!ready) { /* check for teardown race */
154 		ready = sk->sk_data_ready;
155 		goto out;
156 	}
157 
158 	/*
159 	 * ->sk_data_ready is also called for a newly established child socket
160 	 * before it has been accepted and the accepter has set up their
161 	 * data_ready.. we only want to queue listen work for our listening
162 	 * socket
163 	 */
164 	if (sk->sk_state == TCP_LISTEN)
165 		rds_tcp_accept_work(sk);
166 
167 out:
168 	read_unlock(&sk->sk_callback_lock);
169 	ready(sk);
170 }
171 
172 struct socket *rds_tcp_listen_init(struct net *net)
173 {
174 	struct sockaddr_in sin;
175 	struct socket *sock = NULL;
176 	int ret;
177 
178 	ret = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
179 	if (ret < 0)
180 		goto out;
181 
182 	sock->sk->sk_reuse = SK_CAN_REUSE;
183 	rds_tcp_nonagle(sock);
184 
185 	write_lock_bh(&sock->sk->sk_callback_lock);
186 	sock->sk->sk_user_data = sock->sk->sk_data_ready;
187 	sock->sk->sk_data_ready = rds_tcp_listen_data_ready;
188 	write_unlock_bh(&sock->sk->sk_callback_lock);
189 
190 	sin.sin_family = PF_INET;
191 	sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
192 	sin.sin_port = (__force u16)htons(RDS_TCP_PORT);
193 
194 	ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
195 	if (ret < 0)
196 		goto out;
197 
198 	ret = sock->ops->listen(sock, 64);
199 	if (ret < 0)
200 		goto out;
201 
202 	return sock;
203 out:
204 	if (sock)
205 		sock_release(sock);
206 	return NULL;
207 }
208 
209 void rds_tcp_listen_stop(struct socket *sock)
210 {
211 	struct sock *sk;
212 
213 	if (!sock)
214 		return;
215 
216 	sk = sock->sk;
217 
218 	/* serialize with and prevent further callbacks */
219 	lock_sock(sk);
220 	write_lock_bh(&sk->sk_callback_lock);
221 	if (sk->sk_user_data) {
222 		sk->sk_data_ready = sk->sk_user_data;
223 		sk->sk_user_data = NULL;
224 	}
225 	write_unlock_bh(&sk->sk_callback_lock);
226 	release_sock(sk);
227 
228 	/* wait for accepts to stop and close the socket */
229 	flush_workqueue(rds_wq);
230 	sock_release(sock);
231 }
232