Whamcloud - gitweb
642d8b53bb2b22115ec91b0fe8fe96b8341835b5
[fs/lustre-release.git] / lnet / lnet / lib-socket.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2015, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_LNET
33
34 #include <linux/if.h>
35 #include <linux/in.h>
36 #include <linux/net.h>
37 #include <linux/file.h>
38 #include <linux/pagemap.h>
39 /* For sys_open & sys_close */
40 #include <linux/syscalls.h>
41 #include <net/sock.h>
42
43 #include <libcfs/libcfs.h>
44 #include <lnet/lib-lnet.h>
45
46 /*
47  * kernel 5.1: commit 7f1bc6e95d7840d4305595b3e4025cddda88cee5
48  * Y2038 64-bit time.
49  *  SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTAMPING options, the
50  *  way they are currently defined, are not y2038 safe.
51  *  Subsequent patches in the series add new y2038 safe versions
52  *  of these options which provide 64 bit timestamps on all
53  *  architectures uniformly.
54  *  Hence, rename existing options with OLD tag suffixes.
55  *
56  * NOTE: When updating to timespec64 change change these to '_NEW'.
57  *
58  */
59 #ifndef SO_SNDTIMEO
60 #define SO_SNDTIMEO SO_SNDTIMEO_OLD
61 #endif
62
63 #ifndef SO_RCVTIMEO
64 #define SO_RCVTIMEO SO_RCVTIMEO_OLD
65 #endif
66
67 int
68 lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
69 {
70         int             rc;
71         long            jiffies_left = cfs_time_seconds(timeout);
72         unsigned long   then;
73         struct timeval  tv;
74
75         LASSERT(nob > 0);
76         /* Caller may pass a zero timeout if she thinks the socket buffer is
77          * empty enough to take the whole message immediately */
78
79         for (;;) {
80                 struct kvec  iov = {
81                         .iov_base = buffer,
82                         .iov_len  = nob
83                 };
84                 struct msghdr msg = {
85                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
86                 };
87
88                 if (timeout != 0) {
89                         /* Set send timeout to remaining time */
90                         jiffies_to_timeval(jiffies_left, &tv);
91                         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
92                                                (char *)&tv, sizeof(tv));
93                         if (rc != 0) {
94                                 CERROR("Can't set socket send timeout "
95                                        "%ld.%06d: %d\n",
96                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
97                                 return rc;
98                         }
99                 }
100
101                 then = jiffies;
102                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
103                 jiffies_left -= jiffies - then;
104
105                 if (rc == nob)
106                         return 0;
107
108                 if (rc < 0)
109                         return rc;
110
111                 if (rc == 0) {
112                         CERROR("Unexpected zero rc\n");
113                         return -ECONNABORTED;
114                 }
115
116                 if (jiffies_left <= 0)
117                         return -EAGAIN;
118
119                 buffer = ((char *)buffer) + rc;
120                 nob -= rc;
121         }
122         return 0;
123 }
124 EXPORT_SYMBOL(lnet_sock_write);
125
126 int
127 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
128 {
129         int             rc;
130         long            jiffies_left = cfs_time_seconds(timeout);
131         unsigned long   then;
132         struct timeval  tv;
133
134         LASSERT(nob > 0);
135         LASSERT(jiffies_left > 0);
136
137         for (;;) {
138                 struct kvec  iov = {
139                         .iov_base = buffer,
140                         .iov_len  = nob
141                 };
142                 struct msghdr msg = {
143                         .msg_flags      = 0
144                 };
145
146                 /* Set receive timeout to remaining time */
147                 jiffies_to_timeval(jiffies_left, &tv);
148                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
149                                        (char *)&tv, sizeof(tv));
150                 if (rc != 0) {
151                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
152                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
153                         return rc;
154                 }
155
156                 then = jiffies;
157                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
158                 jiffies_left -= jiffies - then;
159
160                 if (rc < 0)
161                         return rc;
162
163                 if (rc == 0)
164                         return -ECONNRESET;
165
166                 buffer = ((char *)buffer) + rc;
167                 nob -= rc;
168
169                 if (nob == 0)
170                         return 0;
171
172                 if (jiffies_left <= 0)
173                         return -ETIMEDOUT;
174         }
175 }
176 EXPORT_SYMBOL(lnet_sock_read);
177
178 static int
179 lnet_sock_create(struct socket **sockp, int *fatal,
180                  __u32 local_ip, int local_port, struct net *ns)
181 {
182         struct sockaddr_in  locaddr;
183         struct socket      *sock;
184         int                 rc;
185         int                 option;
186
187         /* All errors are fatal except bind failure if the port is in use */
188         *fatal = 1;
189
190 #ifdef HAVE_SOCK_CREATE_KERN_USE_NET
191         rc = sock_create_kern(ns, PF_INET, SOCK_STREAM, 0, &sock);
192 #else
193         rc = sock_create_kern(PF_INET, SOCK_STREAM, 0, &sock);
194 #endif
195         *sockp = sock;
196         if (rc != 0) {
197                 CERROR("Can't create socket: %d\n", rc);
198                 return rc;
199         }
200
201         option = 1;
202         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
203                                (char *)&option, sizeof(option));
204         if (rc != 0) {
205                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
206                 goto failed;
207         }
208
209         if (local_ip != 0 || local_port != 0) {
210                 memset(&locaddr, 0, sizeof(locaddr));
211                 locaddr.sin_family = AF_INET;
212                 locaddr.sin_port = htons(local_port);
213                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
214                                           INADDR_ANY : htonl(local_ip);
215
216                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
217                                  sizeof(locaddr));
218                 if (rc == -EADDRINUSE) {
219                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
220                         *fatal = 0;
221                         goto failed;
222                 }
223                 if (rc != 0) {
224                         CERROR("Error trying to bind to port %d: %d\n",
225                                local_port, rc);
226                         goto failed;
227                 }
228         }
229         return 0;
230
231 failed:
232         sock_release(sock);
233         return rc;
234 }
235
236 int
237 lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
238 {
239         int                 option;
240         int                 rc;
241
242         if (txbufsize != 0) {
243                 option = txbufsize;
244                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
245                                        (char *)&option, sizeof(option));
246                 if (rc != 0) {
247                         CERROR("Can't set send buffer %d: %d\n",
248                                 option, rc);
249                         return rc;
250                 }
251         }
252
253         if (rxbufsize != 0) {
254                 option = rxbufsize;
255                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
256                                        (char *)&option, sizeof(option));
257                 if (rc != 0) {
258                         CERROR("Can't set receive buffer %d: %d\n",
259                                 option, rc);
260                         return rc;
261                 }
262         }
263         return 0;
264 }
265 EXPORT_SYMBOL(lnet_sock_setbuf);
266
267 int
268 lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port)
269 {
270         struct sockaddr_in sin;
271         int rc;
272 #ifndef HAVE_KERN_SOCK_GETNAME_2ARGS
273         int len = sizeof(sin);
274 #endif
275
276         if (remote)
277                 rc = lnet_kernel_getpeername(sock,
278                                              (struct sockaddr *)&sin, &len);
279         else
280                 rc = lnet_kernel_getsockname(sock,
281                                              (struct sockaddr *)&sin, &len);
282         if (rc < 0) {
283                 CERROR("Error %d getting sock %s IP/port\n",
284                         rc, remote ? "peer" : "local");
285                 return rc;
286         }
287
288         if (ip != NULL)
289                 *ip = ntohl(sin.sin_addr.s_addr);
290
291         if (port != NULL)
292                 *port = ntohs(sin.sin_port);
293
294         return 0;
295 }
296 EXPORT_SYMBOL(lnet_sock_getaddr);
297
298 int
299 lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
300 {
301         if (txbufsize != NULL)
302                 *txbufsize = sock->sk->sk_sndbuf;
303
304         if (rxbufsize != NULL)
305                 *rxbufsize = sock->sk->sk_rcvbuf;
306
307         return 0;
308 }
309 EXPORT_SYMBOL(lnet_sock_getbuf);
310
311 int
312 lnet_sock_listen(struct socket **sockp,
313                    __u32 local_ip, int local_port, int backlog, struct net *ns)
314 {
315         int      fatal;
316         int      rc;
317
318         rc = lnet_sock_create(sockp, &fatal, local_ip, local_port, ns);
319         if (rc != 0) {
320                 if (!fatal)
321                         CERROR("Can't create socket: port %d already in use\n",
322                                local_port);
323                 return rc;
324         }
325
326         rc = kernel_listen(*sockp, backlog);
327         if (rc == 0)
328                 return 0;
329
330         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
331         sock_release(*sockp);
332         return rc;
333 }
334
335 int
336 lnet_sock_accept(struct socket **newsockp, struct socket *sock)
337 {
338         wait_queue_entry_t wait;
339         struct socket *newsock;
340         int            rc;
341
342         /* XXX this should add a ref to sock->ops->owner, if
343          * TCP could be a module */
344         rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
345         if (rc) {
346                 CERROR("Can't allocate socket\n");
347                 return rc;
348         }
349
350         newsock->ops = sock->ops;
351
352 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
353         rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
354 #else
355         rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
356 #endif
357         if (rc == -EAGAIN) {
358                 /* Nothing ready, so wait for activity */
359                 init_waitqueue_entry(&wait, current);
360                 add_wait_queue(sk_sleep(sock->sk), &wait);
361                 set_current_state(TASK_INTERRUPTIBLE);
362                 schedule();
363                 remove_wait_queue(sk_sleep(sock->sk), &wait);
364 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
365                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
366 #else
367                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
368 #endif
369         }
370
371         if (rc != 0)
372                 goto failed;
373
374         *newsockp = newsock;
375         return 0;
376
377 failed:
378         sock_release(newsock);
379         return rc;
380 }
381
382 int
383 lnet_sock_connect(struct socket **sockp, int *fatal,
384                   __u32 local_ip, int local_port,
385                   __u32 peer_ip, int peer_port,
386                   struct net *ns)
387 {
388         struct sockaddr_in  srvaddr;
389         int                 rc;
390
391         rc = lnet_sock_create(sockp, fatal, local_ip, local_port, ns);
392         if (rc != 0)
393                 return rc;
394
395         memset(&srvaddr, 0, sizeof(srvaddr));
396         srvaddr.sin_family = AF_INET;
397         srvaddr.sin_port = htons(peer_port);
398         srvaddr.sin_addr.s_addr = htonl(peer_ip);
399
400         rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
401                             sizeof(srvaddr), 0);
402         if (rc == 0)
403                 return 0;
404
405         /* EADDRNOTAVAIL probably means we're already connected to the same
406          * peer/port on the same local port on a differently typed
407          * connection.  Let our caller retry with a different local
408          * port... */
409         *fatal = !(rc == -EADDRNOTAVAIL);
410
411         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
412                "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
413                &local_ip, local_port, &peer_ip, peer_port);
414
415         sock_release(*sockp);
416         return rc;
417 }