Whamcloud - gitweb
c83843ccddc135247f687660e168e2b510bf1d0b
[fs/lustre-release.git] / lnet / lnet / acceptor.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2014, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #define DEBUG_SUBSYSTEM S_LNET
38 #include <lnet/lib-lnet.h>
39
40 #if defined(__KERNEL__) || defined(HAVE_LIBPTHREAD)
41
42 static int   accept_port    = 988;
43 static int   accept_backlog = 127;
44 static int   accept_timeout = 5;
45
46 struct {
47         int                     pta_shutdown;
48         cfs_socket_t            *pta_sock;
49         struct completion       pta_signal;
50 } lnet_acceptor_state;
51
52 int
53 lnet_acceptor_port(void)
54 {
55         return accept_port;
56 }
57
58 static inline int
59 lnet_accept_magic(__u32 magic, __u32 constant)
60 {
61         return (magic == constant ||
62                 magic == __swab32(constant));
63 }
64
65 #ifdef __KERNEL__
66
67 EXPORT_SYMBOL(lnet_acceptor_port);
68
69 static char *accept = "secure";
70
71 CFS_MODULE_PARM(accept, "s", charp, 0444,
72                 "Accept connections (secure|all|none)");
73 CFS_MODULE_PARM(accept_port, "i", int, 0444,
74                 "Acceptor's port (same on all nodes)");
75 CFS_MODULE_PARM(accept_backlog, "i", int, 0444,
76                 "Acceptor's listen backlog");
77 CFS_MODULE_PARM(accept_timeout, "i", int, 0644,
78                 "Acceptor's timeout (seconds)");
79
80 static char *accept_type = NULL;
81
82 int
83 lnet_acceptor_get_tunables(void)
84 {
85         /* Userland acceptor uses 'accept_type' instead of 'accept', due to
86          * conflict with 'accept(2)', but kernel acceptor still uses 'accept'
87          * for compatibility. Hence the trick. */
88         accept_type = accept;
89         return 0;
90 }
91
92 int
93 lnet_acceptor_timeout(void)
94 {
95         return accept_timeout;
96 }
97 EXPORT_SYMBOL(lnet_acceptor_timeout);
98
99 void
100 lnet_connect_console_error (int rc, lnet_nid_t peer_nid,
101                            __u32 peer_ip, int peer_port)
102 {
103         switch (rc) {
104         /* "normal" errors */
105         case -ECONNREFUSED:
106                 CNETERR("Connection to %s at host %u.%u.%u.%u on port %d was "
107                         "refused: check that Lustre is running on that node.\n",
108                         libcfs_nid2str(peer_nid),
109                         HIPQUAD(peer_ip), peer_port);
110                 break;
111         case -EHOSTUNREACH:
112         case -ENETUNREACH:
113                 CNETERR("Connection to %s at host %u.%u.%u.%u "
114                         "was unreachable: the network or that node may "
115                         "be down, or Lustre may be misconfigured.\n",
116                         libcfs_nid2str(peer_nid), HIPQUAD(peer_ip));
117                 break;
118         case -ETIMEDOUT:
119                 CNETERR("Connection to %s at host %u.%u.%u.%u on "
120                         "port %d took too long: that node may be hung "
121                         "or experiencing high load.\n",
122                         libcfs_nid2str(peer_nid),
123                         HIPQUAD(peer_ip), peer_port);
124                 break;
125         case -ECONNRESET:
126                 LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %u.%u.%u.%u"
127                                    " on port %d was reset: "
128                                    "is it running a compatible version of "
129                                    "Lustre and is %s one of its NIDs?\n",
130                                    libcfs_nid2str(peer_nid),
131                                    HIPQUAD(peer_ip), peer_port,
132                                    libcfs_nid2str(peer_nid));
133                 break;
134         case -EPROTO:
135                 LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at "
136                                    "host %u.%u.%u.%u on port %d: is it running "
137                                    "a compatible version of Lustre?\n",
138                                    libcfs_nid2str(peer_nid),
139                                    HIPQUAD(peer_ip), peer_port);
140                 break;
141         case -EADDRINUSE:
142                 LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to "
143                                    "connect to %s at host %u.%u.%u.%u on port "
144                                    "%d\n", libcfs_nid2str(peer_nid),
145                                    HIPQUAD(peer_ip), peer_port);
146                 break;
147         default:
148                 LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s"
149                                    " at host %u.%u.%u.%u on port %d\n", rc,
150                                    libcfs_nid2str(peer_nid),
151                                    HIPQUAD(peer_ip), peer_port);
152                 break;
153         }
154 }
155 EXPORT_SYMBOL(lnet_connect_console_error);
156
157 int
158 lnet_connect(cfs_socket_t **sockp, lnet_nid_t peer_nid,
159             __u32 local_ip, __u32 peer_ip, int peer_port)
160 {
161         lnet_acceptor_connreq_t cr;
162         cfs_socket_t           *sock;
163         int                     rc;
164         int                     port;
165         int                     fatal;
166
167         CLASSERT (sizeof(cr) <= 16);            /* not too big to be on the stack */
168
169         for (port = LNET_ACCEPTOR_MAX_RESERVED_PORT;
170              port >= LNET_ACCEPTOR_MIN_RESERVED_PORT;
171              --port) {
172                 /* Iterate through reserved ports. */
173
174                 rc = libcfs_sock_connect(&sock, &fatal,
175                                          local_ip, port,
176                                          peer_ip, peer_port);
177                 if (rc != 0) {
178                         if (fatal)
179                                 goto failed;
180                         continue;
181                 }
182
183                 CLASSERT (LNET_PROTO_ACCEPTOR_VERSION == 1);
184
185                 cr.acr_magic   = LNET_PROTO_ACCEPTOR_MAGIC;
186                 cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
187                 cr.acr_nid     = peer_nid;
188
189                 if (the_lnet.ln_testprotocompat != 0) {
190                         /* single-shot proto check */
191                         lnet_net_lock(LNET_LOCK_EX);
192                         if ((the_lnet.ln_testprotocompat & 4) != 0) {
193                                 cr.acr_version++;
194                                 the_lnet.ln_testprotocompat &= ~4;
195                         }
196                         if ((the_lnet.ln_testprotocompat & 8) != 0) {
197                                 cr.acr_magic = LNET_PROTO_MAGIC;
198                                 the_lnet.ln_testprotocompat &= ~8;
199                         }
200                         lnet_net_unlock(LNET_LOCK_EX);
201                 }
202
203                 rc = libcfs_sock_write(sock, &cr, sizeof(cr),
204                                        accept_timeout);
205                 if (rc != 0)
206                         goto failed_sock;
207
208                 *sockp = sock;
209                 return 0;
210         }
211
212         rc = -EADDRINUSE;
213         goto failed;
214
215  failed_sock:
216         libcfs_sock_release(sock);
217  failed:
218         lnet_connect_console_error(rc, peer_nid, peer_ip, peer_port);
219         return rc;
220 }
221 EXPORT_SYMBOL(lnet_connect);
222
223 #else /* below is multi-threaded user-space code */
224
225 static char *accept_type = "secure";
226
227 int
228 lnet_acceptor_get_tunables()
229 {
230         int   rc;
231         char *env = getenv("LNET_ACCEPT");
232
233         if (env != NULL)
234                 accept_type = env;
235
236         rc = lnet_parse_int_tunable(&accept_port, "LNET_ACCEPT_PORT");
237
238         if (rc != 0)
239                 return rc;
240
241         rc = lnet_parse_int_tunable(&accept_backlog, "LNET_ACCEPT_BACKLOG");
242
243         if (rc != 0)
244                 return rc;
245
246         rc = lnet_parse_int_tunable(&accept_timeout, "LNET_ACCEPT_TIMEOUT");
247
248         if (rc != 0)
249                 return rc;
250
251         CDEBUG(D_NET, "accept_type     = %s\n", accept_type);
252         CDEBUG(D_NET, "accept_port     = %d\n", accept_port);
253         CDEBUG(D_NET, "accept_backlog  = %d\n", accept_backlog);
254         CDEBUG(D_NET, "accept_timeout  = %d\n", accept_timeout);
255         return 0;
256 }
257
258 #endif /* __KERNEL__ */
259
260 /* Below is the code common for both kernel and MT user-space */
261
262 int
263 lnet_accept(cfs_socket_t *sock, __u32 magic)
264 {
265         lnet_acceptor_connreq_t cr;
266         __u32                   peer_ip;
267         int                     peer_port;
268         int                     rc;
269         int                     flip;
270         lnet_ni_t              *ni;
271         char                   *str;
272
273         LASSERT (sizeof(cr) <= 16);             /* not too big for the stack */
274
275         rc = libcfs_sock_getaddr(sock, 1, &peer_ip, &peer_port);
276         LASSERT (rc == 0);                      /* we succeeded before */
277
278         if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) {
279
280                 if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) {
281                         /* future version compatibility!
282                          * When LNET unifies protocols over all LNDs, the first
283                          * thing sent will be a version query.  I send back
284                          * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */
285
286                         memset (&cr, 0, sizeof(cr));
287                         cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
288                         cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
289                         rc = libcfs_sock_write(sock, &cr, sizeof(cr),
290                                                accept_timeout);
291
292                         if (rc != 0)
293                                 CERROR("Error sending magic+version in response"
294                                        "to LNET magic from %u.%u.%u.%u: %d\n",
295                                        HIPQUAD(peer_ip), rc);
296                         return -EPROTO;
297                 }
298
299                 if (magic == le32_to_cpu(LNET_PROTO_TCP_MAGIC))
300                         str = "'old' socknal/tcpnal";
301                 else if (lnet_accept_magic(magic, LNET_PROTO_RA_MAGIC))
302                         str = "'old' ranal";
303                 else
304                         str = "unrecognised";
305
306                 LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %u.%u.%u.%u"
307                                    " magic %08x: %s acceptor protocol\n",
308                                    HIPQUAD(peer_ip), magic, str);
309                 return -EPROTO;
310         }
311
312         flip = (magic != LNET_PROTO_ACCEPTOR_MAGIC);
313
314         rc = libcfs_sock_read(sock, &cr.acr_version,
315                               sizeof(cr.acr_version),
316                               accept_timeout);
317         if (rc != 0) {
318                 CERROR("Error %d reading connection request version from "
319                        "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
320                 return -EIO;
321         }
322
323         if (flip)
324                 __swab32s(&cr.acr_version);
325
326         if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION) {
327                 /* future version compatibility!
328                  * An acceptor-specific protocol rev will first send a version
329                  * query.  I send back my current version to tell her I'm
330                  * "old". */
331                 int peer_version = cr.acr_version;
332
333                 memset (&cr, 0, sizeof(cr));
334                 cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
335                 cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
336
337                 rc = libcfs_sock_write(sock, &cr, sizeof(cr),
338                                        accept_timeout);
339
340                 if (rc != 0)
341                         CERROR("Error sending magic+version in response"
342                                "to version %d from %u.%u.%u.%u: %d\n",
343                                peer_version, HIPQUAD(peer_ip), rc);
344                 return -EPROTO;
345         }
346
347         rc = libcfs_sock_read(sock, &cr.acr_nid,
348                               sizeof(cr) -
349                               offsetof(lnet_acceptor_connreq_t, acr_nid),
350                               accept_timeout);
351         if (rc != 0) {
352                 CERROR("Error %d reading connection request from "
353                        "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
354                 return -EIO;
355         }
356
357         if (flip)
358                 __swab64s(&cr.acr_nid);
359
360         ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid));
361         if (ni == NULL ||               /* no matching net */
362             ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */
363                 if (ni != NULL)
364                         lnet_ni_decref(ni);
365                 LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %u.%u.%u.%u"
366                                    " for %s: No matching NI\n",
367                                    HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
368                 return -EPERM;
369         }
370
371         if (ni->ni_lnd->lnd_accept == NULL) {
372                 /* This catches a request for the loopback LND */
373                 lnet_ni_decref(ni);
374                 LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %u.%u.%u.%u"
375                                   " for %s: NI doesn not accept IP connections\n",
376                                   HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid));
377                 return -EPERM;
378         }
379
380         CDEBUG(D_NET, "Accept %s from %u.%u.%u.%u\n",
381                libcfs_nid2str(cr.acr_nid), HIPQUAD(peer_ip));
382
383         rc = ni->ni_lnd->lnd_accept(ni, sock);
384
385         lnet_ni_decref(ni);
386         return rc;
387 }
388
389 int
390 lnet_acceptor(void *arg)
391 {
392         cfs_socket_t  *newsock;
393         int            rc;
394         __u32          magic;
395         __u32          peer_ip;
396         int            peer_port;
397         int            secure = (int)((long_ptr_t)arg);
398
399         LASSERT (lnet_acceptor_state.pta_sock == NULL);
400
401         cfs_block_allsigs();
402
403         rc = libcfs_sock_listen(&lnet_acceptor_state.pta_sock,
404                                 0, accept_port, accept_backlog);
405         if (rc != 0) {
406                 if (rc == -EADDRINUSE)
407                         LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port"
408                                            " %d: port already in use\n",
409                                            accept_port);
410                 else
411                         LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port "
412                                            "%d: unexpected error %d\n",
413                                            accept_port, rc);
414
415                 lnet_acceptor_state.pta_sock = NULL;
416         } else {
417                 LCONSOLE(0, "Accept %s, port %d\n", accept_type, accept_port);
418         }
419
420         /* set init status and unblock parent */
421         lnet_acceptor_state.pta_shutdown = rc;
422         complete(&lnet_acceptor_state.pta_signal);
423
424         if (rc != 0)
425                 return rc;
426
427         while (!lnet_acceptor_state.pta_shutdown) {
428
429                 rc = libcfs_sock_accept(&newsock, lnet_acceptor_state.pta_sock);
430                 if (rc != 0) {
431                         if (rc != -EAGAIN) {
432                                 CWARN("Accept error %d: pausing...\n", rc);
433                                 cfs_pause(cfs_time_seconds(1));
434                         }
435                         continue;
436                 }
437
438                 /* maybe we're waken up with libcfs_sock_abort_accept() */
439                 if (lnet_acceptor_state.pta_shutdown) {
440                         libcfs_sock_release(newsock);
441                         break;
442                 }
443
444                 rc = libcfs_sock_getaddr(newsock, 1, &peer_ip, &peer_port);
445                 if (rc != 0) {
446                         CERROR("Can't determine new connection's address\n");
447                         goto failed;
448                 }
449
450                 if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) {
451                         CERROR("Refusing connection from %u.%u.%u.%u: "
452                                "insecure port %d\n",
453                                HIPQUAD(peer_ip), peer_port);
454                         goto failed;
455                 }
456
457                 rc = libcfs_sock_read(newsock, &magic, sizeof(magic),
458                                       accept_timeout);
459                 if (rc != 0) {
460                         CERROR("Error %d reading connection request from "
461                                "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip));
462                         goto failed;
463                 }
464
465                 rc = lnet_accept(newsock, magic);
466                 if (rc != 0)
467                         goto failed;
468
469                 continue;
470
471         failed:
472                 libcfs_sock_release(newsock);
473         }
474
475         libcfs_sock_release(lnet_acceptor_state.pta_sock);
476         lnet_acceptor_state.pta_sock = NULL;
477
478         CDEBUG(D_NET, "Acceptor stopping\n");
479
480         /* unblock lnet_acceptor_stop() */
481         complete(&lnet_acceptor_state.pta_signal);
482         return 0;
483 }
484
485 static inline int
486 accept2secure(const char *acc, long *sec)
487 {
488         if (!strcmp(acc, "secure")) {
489                 *sec = 1;
490                 return 1;
491         } else if (!strcmp(acc, "all")) {
492                 *sec = 0;
493                 return 1;
494         } else if (!strcmp(acc, "none")) {
495                 return 0;
496         } else {
497                 LCONSOLE_ERROR_MSG(0x124, "Can't parse 'accept=\"%s\"'\n",
498                                    acc);
499                 return -EINVAL;
500         }
501 }
502
503 int
504 lnet_acceptor_start(void)
505 {
506         struct task_struct *task;
507         int  rc;
508         long rc2;
509         long secure;
510
511         LASSERT (lnet_acceptor_state.pta_sock == NULL);
512
513         rc = lnet_acceptor_get_tunables();
514         if (rc != 0)
515                 return rc;
516
517 #ifndef __KERNEL__
518         /* Do nothing if we're liblustre clients */
519         if ((the_lnet.ln_pid & LNET_PID_USERFLAG) != 0)
520                 return 0;
521 #endif
522
523         init_completion(&lnet_acceptor_state.pta_signal);
524         rc = accept2secure(accept_type, &secure);
525         if (rc <= 0) {
526                 fini_completion(&lnet_acceptor_state.pta_signal);
527                 return rc;
528         }
529
530         if (lnet_count_acceptor_nis() == 0)  /* not required */
531                 return 0;
532
533         task = kthread_run(lnet_acceptor, (void *)(ulong_ptr_t)secure,
534                            "acceptor_%03ld", secure);
535         if (IS_ERR(task)) {
536                 rc2 = PTR_ERR(task);
537                 CERROR("Can't start acceptor thread: %ld\n", rc2);
538                 fini_completion(&lnet_acceptor_state.pta_signal);
539
540                 return -ESRCH;
541         }
542
543         /* wait for acceptor to startup */
544         wait_for_completion(&lnet_acceptor_state.pta_signal);
545
546         if (!lnet_acceptor_state.pta_shutdown) {
547                 /* started OK */
548                 LASSERT(lnet_acceptor_state.pta_sock != NULL);
549                 return 0;
550         }
551
552         LASSERT(lnet_acceptor_state.pta_sock == NULL);
553         fini_completion(&lnet_acceptor_state.pta_signal);
554
555         return -ENETDOWN;
556 }
557
558 void
559 lnet_acceptor_stop(void)
560 {
561         if (lnet_acceptor_state.pta_sock == NULL) /* not running */
562                 return;
563
564         lnet_acceptor_state.pta_shutdown = 1;
565         libcfs_sock_abort_accept(lnet_acceptor_state.pta_sock);
566
567         /* block until acceptor signals exit */
568         wait_for_completion(&lnet_acceptor_state.pta_signal);
569
570         fini_completion(&lnet_acceptor_state.pta_signal);
571 }
572
573 #else /* single-threaded user-space */
574 int
575 lnet_acceptor_start(void)
576 {
577         return 0;
578 }
579
580 void
581 lnet_acceptor_stop(void)
582 {
583 }
584 #endif /* defined(__KERNEL__) || defined(HAVE_LIBPTHREAD) */