Whamcloud - gitweb
Fix problem with multiple connections to the same local device.
[fs/lustre-release.git] / lustre / utils / network.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *
6  *   This file is a modified version of the ptlctl tool which is
7  *   part of Portals, http://www.sf.net/projects/lustre/
8  *
9  *   Portals is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Portals is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Portals; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <netinet/tcp.h>
28 #include <netdb.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <sys/ioctl.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <time.h>
36 #include <portals/api-support.h>
37
38 #include "lctl.h"
39
40 static char rawbuf[8192];
41 static char *buf = rawbuf;
42 static int max = 8192;
43
44 static unsigned int g_nid = 0;
45 static unsigned int g_nal = 0;
46 static unsigned short g_port = 0;
47 static int g_pfd = -1;
48
49 static int g_socket_txmem = 0;
50 static int g_socket_rxmem = 0;
51 static int g_socket_nonagle = 1;
52
53 static name2num_t nalnames[] = {
54         {"tcp",         SOCKNAL},
55         {"elan",        QSWNAL},
56         {"gm",          GMNAL},
57         {NULL,          -1}
58 };
59
60 int network_setup(int argc, char **argv) {
61         PORTALS_CONNECT;
62         return 0;
63 }
64
65 static name2num_t *name2num_lookup_name(name2num_t *table, char *str) {
66         while (table->name != NULL)
67                 if (!strcmp (str, table->name))
68                         return (table);
69                 else
70                         table++;
71         return (NULL);
72 }
73
74 static name2num_t *name2num_lookup_num(name2num_t *table, int num) {
75         while (table->name != NULL)
76                 if (num == table->num)
77                         return (table);
78                 else
79                         table++;
80         return (NULL);
81 }
82
83 static int name2nal(char *str) {
84         name2num_t *e = name2num_lookup_name (nalnames, str);
85
86         return ((e == NULL) ? 0 : e->num);
87 }
88
89 static char *nal2name (int nal) {
90         name2num_t *e = name2num_lookup_num (nalnames, nal);
91
92         return ((e == NULL) ? "???" : e->name);
93 }
94
95 static int nid2nal(ptl_nid_t nid) {
96         /* BIG pragmatic assumption */
97         return ((((__u32)nid) & 0xffff0000) != 0 ? SOCKNAL : QSWNAL);
98 }
99
100 static int parse_nid(ptl_nid_t *nidp, char *str) {
101         struct hostent *he;
102         int             a;
103         int             b;
104         int             c;
105         int             d;
106         
107         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
108             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
109             (c & ~0xff) == 0 && (d & ~0xff) == 0) {
110                 __u32 addr = (a<<24)|(b<<16)|(c<<8)|d;
111                 *nidp = (ptl_nid_t)addr;
112                 return (0);
113         }
114         
115         if ((('a' <= str[0] && str[0] <= 'z') ||
116              ('A' <= str[0] && str[0] <= 'Z')) &&
117              (he = gethostbyname (str)) != NULL) {
118                 __u32 addr = *(__u32 *)he->h_addr;
119                 *nidp = (ptl_nid_t)ntohl(addr);  /* HOST byte order */
120                 return (0);
121         }
122
123         if (sscanf (str, "%i", &a) == 1) {
124                 *nidp = (ptl_nid_t)a;
125                 return (0);
126         }
127
128         return (-1);
129 }
130
131 static char *nid2str (char *buffer, ptl_nid_t nid) {
132         switch (nid2nal(nid)) {
133         case QSWNAL:
134                 sprintf (buffer, "%Ld", nid);
135                 return (buffer);
136                 
137         case SOCKNAL: {
138                 __u32 addr = htonl((__u32)nid); /* back to NETWORK byte order*/
139                 struct hostent *he = gethostbyaddr ((const char *)&addr,
140                         sizeof(addr), AF_INET);
141                 
142                 if (he != NULL) {
143                         strcpy (buffer, he->h_name);
144                 } else {
145                         addr = (__u32)nid;
146                         sprintf(buffer, "%d.%d.%d.%d", (addr>>24)&0xff,
147                                 (addr>>16)&0xff, (addr>>8)&0xff, addr&0xff);
148                 }
149                 return (buffer);
150         }
151         
152         default:
153                 sprintf (buffer, "nid2nal broken");
154                 return (buffer);
155         }
156 }
157         
158 int jt_net_network(int argc, char **argv) {
159         int  nal;
160         
161         if (argc != 2 || (nal = name2nal (argv[1])) == 0)
162                 return CMD_HELP;
163
164         g_nal = nal;
165         return (0);
166 }
167
168 int jt_net_connect(int argc, char **argv) {
169         if (argc < 2)
170                 return CMD_HELP;
171
172         if (g_nal == 0) {
173                 fprintf(stderr, "Error: you must run the 'setup' command "
174                         "first.\n");
175                 return -1;
176         }
177
178         if (g_nal == SOCKNAL) {
179                 struct hostent *he;
180                 struct portal_ioctl_data data;
181                 struct sockaddr_in srvaddr;
182                 int fd, rc;
183                 int nonagle = 0;
184                 int rxmem = 0;
185                 int txmem = 0;
186                 int o;
187                 int olen;
188                 
189                 if (argc != 3)
190                         return CMD_HELP;
191
192                 he = gethostbyname(argv[1]);
193                 if (!he) {
194                         fprintf(stderr, "gethostbyname error: %s\n",
195                                 strerror(errno));
196                         return -1;
197                 }
198
199                 g_port = atol(argv[2]);
200
201                 memset(&srvaddr, 0, sizeof(srvaddr));
202                 srvaddr.sin_family = AF_INET;
203                 srvaddr.sin_port = htons(g_port);
204                 srvaddr.sin_addr.s_addr = *(__u32 *)he->h_addr;
205         
206                 fd = socket(PF_INET, SOCK_STREAM, 0);
207                 if ( fd < 0 ) {
208                         fprintf(stderr, "socket() failed: %s\n",
209                                 strerror(errno));
210                         return -1;
211                 }
212
213                 if (g_socket_nonagle) {
214                         o = 1;
215                         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
216                             &o, sizeof (o)) != 0) { 
217                                 fprintf(stderr, "cannot disable nagle: %s\n",
218                                         strerror(errno));
219                                 return (-1);
220                         }
221                 }
222
223                 if (g_socket_rxmem != 0) {
224                         o = g_socket_rxmem;
225                         if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
226                             &o, sizeof (o)) != 0) { 
227                                 fprintf(stderr, "cannot set receive buffer "
228                                         "size: %s\n", strerror(errno));
229                                 return (-1);
230                         }
231                 }
232
233                 if (g_socket_txmem != 0) {
234                         o = g_socket_txmem;
235                         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
236                             &o, sizeof (o)) != 0) { 
237                                 fprintf(stderr, "cannot set send buffer "
238                                         "size: %s\n", strerror(errno));
239                                 return (-1);
240                         }
241                 }
242
243                 rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
244                 if ( rc == -1 ) { 
245                         fprintf(stderr, "connect() failed: %s\n",
246                                 strerror(errno));
247                         return -1;
248                 }
249
250                 olen = sizeof (txmem);
251                 if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &olen) != 0)
252                         fprintf(stderr, "Can't get send buffer size: %s\n",
253                                 strerror(errno));
254                 olen = sizeof (rxmem);
255                 if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &olen) != 0)
256                         fprintf(stderr, "Can't get receive buffer size: %s\n",
257                                 strerror(errno));
258                 olen = sizeof (nonagle);
259                 if (getsockopt(fd,IPPROTO_TCP,TCP_NODELAY,&nonagle,&olen) != 0)
260                         fprintf(stderr, "Can't get nagle: %s\n",
261                                 strerror(errno));
262
263                 fprintf(stderr, "Connected to %s (snd %d, rcv %d, nagle %s)\n",
264                         argv[1],txmem,rxmem,nonagle ? "Disabled" : "Enabled");
265
266                 PORTAL_IOC_INIT(data);
267                 data.ioc_fd = fd;
268                 /* HOST byte order */
269                 data.ioc_nid = ntohl(srvaddr.sin_addr.s_addr);
270
271                 rc = ioctl(g_pfd, IOC_PORTAL_REGISTER_CLIENT_FD, &data);
272                 if (rc) {
273                         fprintf(stderr, "failed to register fd with portals: "
274                                 "%s\n", strerror(errno));
275                         return -1;
276                 }
277
278                 g_nid = ntohl (srvaddr.sin_addr.s_addr); /* HOST byte order */
279                 fprintf(stderr, "Connection to 0x%x registered with socknal\n",
280                         g_nid);
281
282                 rc = close(fd);
283                 if (rc) {
284                         fprintf(stderr, "close failed: %d\n", rc);
285                 }
286         } else if (g_nal == QSWNAL) {
287                 g_nid = atoi(argv[1]);
288         } else if (g_nal == GMNAL) {
289                 g_nid = atoi(argv[1]);
290         } else {
291                 fprintf(stderr, "This should never happen.  Also it is very "
292                         "bad.\n");
293         }
294
295         return 0;
296 }
297
298 int jt_net_disconnect(int argc, char **argv) {
299         if (argc > 2)
300                 return CMD_HELP;
301         
302         if (g_nal == 0) {
303                 fprintf(stderr, "Error: you must run the 'setup' command "
304                         "first.\n");
305                 return -1;
306         }
307
308         if (g_nal == SOCKNAL) {
309                 struct hostent *he;
310                 struct portal_ioctl_data data;
311                 int rc;
312
313                 PORTAL_IOC_INIT(data);
314                 if (argc == 2) {
315                         he = gethostbyname(argv[1]);
316                         if (!he) {
317                                 fprintf(stderr, "gethostbyname error: %s\n",
318                                         strerror(errno));
319                                 return -1;
320                         }
321                         
322                         /* HOST byte order */
323                         data.ioc_nid = ntohl (*(__u32 *)he->h_addr);
324
325                 } else {
326                         fprintf(stderr, "Disconnecting ALL connections.\n");
327                         /* leave ioc_nid zeroed == disconnect all */
328                 }
329                 rc = ioctl(g_pfd, IOC_PORTAL_CLOSE_CONNECTION, &data);
330                 if (rc) {
331                         fprintf(stderr, "failed to remove connection: %s\n",
332                                 strerror(errno));
333                         return -1;
334                 }
335         } else if (g_nal == QSWNAL) {
336                 fprintf(stderr, "'disconnect' doesn't make any sense for "
337                         "elan.\n");
338         } else if (g_nal == GMNAL) {
339                 fprintf(stderr, "'disconnect' doesn't make any sense for "
340                         "GM.\n");
341         } else {
342                 fprintf(stderr, "This should never happen.  Also it is very "
343                         "bad.\n");
344         }
345
346         return 0;
347 }
348
349 /*
350 int jt_net_ping(int argc, char **argv) {
351         int       rc;
352         ptl_nid_t nid;
353         long      count   = 1;
354         long      size    = 4;
355         long      timeout = 1;
356         struct portal_ioctl_data data;
357
358         if (argc < 2) {
359                 fprintf(stderr, "usage: %s nid [count] [size] [timeout "
360                         (secs)]\n", argv[0]);
361                 return 0;
362         }
363
364         if (g_nal == 0) {
365                 fprintf(stderr, "Error: you must run the 'setup' command "
366                         "first.\n");
367                 return -1;
368         }
369
370         if (parse_nid (&nid, argv[1]) != 0) {
371                 fprintf (stderr, "Can\'t parse nid \"%s\"\n", argv[1]);
372                 return (-1);
373         }
374         
375         if (argc > 2) {
376                 count = atol(argv[2]);
377
378                 if (count < 0 || count > 20000) {
379                         fprintf(stderr, "are you insane? "
380                                 "%ld is a crazy count.\n", count);
381                         return -1;
382                 }
383         }
384         
385         if (argc > 3)
386                 size= atol(argv[3]);
387
388         if (argc > 4)
389                 timeout = atol (argv[4]);
390         
391         PORTAL_IOC_INIT (data);
392         data.ioc_count   = count;
393         data.ioc_size    = size;
394         data.ioc_nid     = (__u32)nid;
395         data.ioc_nal     = g_nal;
396         data.ioc_timeout = timeout;
397         
398         rc = ioctl(g_pfd, IOC_PORTAL_PING, &data);
399         if (rc) {
400                 fprintf(stderr, "failed to start pinger: %s\n",
401                         strerror(errno));
402                 return -1;
403         }
404         fprintf(stderr, "Pinger started, take cover...\n");
405         return 0;
406 }
407 */
408
409 int jt_net_mynid(int argc, char **argv) {
410         int rc;
411         struct hostent *h;
412         char buf[1024], *hostname;
413         struct portal_ioctl_data data;
414         ptl_nid_t mynid;
415         
416         if (argc > 2)
417                 return CMD_HELP;
418
419         if (g_nal == 0) {
420                 fprintf(stderr, "Error: you must run the 'setup' command "
421                         "first.\n");
422                 return -1;
423         }
424
425         if (g_nal == QSWNAL) {
426                 fprintf(stderr, "'mynid' doesn't make any sense for elan.\n");
427                 return -1;
428         } else  if (g_nal == GMNAL) {
429                 fprintf(stderr, "'mynid' doesn't make any sense for GM.\n");
430                 return -1;
431         } 
432         
433         if (g_nal != SOCKNAL) {
434                 fprintf(stderr, "This should never happen.  Also it is very "
435                         "bad.\n");
436                 return -1;
437         }
438
439         if (argc == 1) {
440                 if (gethostname(buf, sizeof(buf)) != 0) {
441                         fprintf(stderr, "gethostname failed: %s\n",
442                                 strerror(errno));
443                         return -1;
444                 }
445                 hostname = buf;
446         } else {
447                 hostname = argv[1];
448         }
449
450         h = gethostbyname(hostname);
451
452         if (!h) {
453                 fprintf(stderr, "cannot get address for host '%s': %d\n",
454                         hostname, h_errno);
455                 return -1;
456         }
457         mynid = (ptl_nid_t)ntohl (*(__u32 *)h->h_addr); /* HOST byte order */
458         
459         PORTAL_IOC_INIT(data);
460         data.ioc_nid = (__u32)mynid;
461
462         rc = ioctl(g_pfd, IOC_PORTAL_REGISTER_MYNID, &data);
463         if (rc < 0)
464                 fprintf(stderr, "IOC_PORTAL_REGISTER_MYNID failed: %s\n",
465                        strerror(errno));
466         else
467                 fprintf(stderr, "registered my nid 0x%Lx (%s)\n",
468                         mynid, hostname);
469         return 0;
470 }
471
472 int jt_net_add_uuid(int argc, char **argv) {
473         char tmp[64];
474         int rc;
475         struct portal_ioctl_data data;
476         ptl_nid_t nid = g_nid;
477         
478         if (argc != 3)
479                 return CMD_HELP;
480
481         if (parse_nid(&nid, argv[2]) != 0) {
482                 fprintf (stderr, "Can't parse NID %s\n", argv[2]);
483                 return (-1);
484         }
485
486         if (g_nal == 0) {
487                 fprintf(stderr, "Error: you must run the 'setup' command "
488                         "first.\n");
489                 return -1;
490         }
491
492         memset(&data, 0, sizeof(data));
493         data.ioc_nid = nid;
494         data.ioc_inllen1 = strlen(argv[1]) + 1;
495         data.ioc_inlbuf1 = argv[1];
496         data.ioc_nal = g_nal;
497         if (portal_ioctl_pack(&data, &buf, max) != 0) {
498                 fprintf(stderr, "portal_ioctl_pack failed.\n");
499                 return -1;
500         }
501
502         rc = ioctl(g_pfd, IOC_PORTAL_ADD_UUID, buf);
503         if (rc) {
504                 fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n",
505                         strerror(errno));
506                 return -1;
507         }
508
509         fprintf (stderr, "Added uuid %s: %s\n", argv[1], nid2str (tmp, nid));
510         return 0;
511 }
512
513 #if 0
514 static int jt_close_uuid(int argc, char **argv)
515 {
516         int rc;
517         struct portal_ioctl_data data;
518
519         if (argc != 2) {
520                 fprintf(stderr, "usage: %s <uuid>\n", argv[0]);
521                 return 0;
522         }
523
524         if (g_nal == 0) {
525                 fprintf(stderr, "Error: you must run the 'setup' command "
526                         "first.\n");
527                 return -1;
528         }
529
530         memset(&data, 0, sizeof(data));
531         data.ioc_inllen1 = strlen(argv[1]) + 1;
532         data.ioc_inlbuf1 = argv[1];
533         data.ioc_nal = g_nal;
534         if (portal_ioctl_pack(&data, &buf, max) != 0) {
535                 fprintf(stderr, "portal_ioctl_pack failed.\n");
536                 return -1;
537         }
538
539         rc = ioctl(g_pfd, IOC_PORTAL_CLOSE_UUID, buf);
540         if (rc) {
541                 fprintf(stderr, "IOC_PORTAL_CLOSE_UUID failed: %s\n",
542                         strerror(errno));
543                 return -1;
544         }
545         return 0;
546 }
547 #endif
548
549 int jt_net_del_uuid(int argc, char **argv) {
550         int rc;
551         struct portal_ioctl_data data;
552
553         if (argc != 2)
554                 return CMD_HELP;
555
556         if (g_nal == 0) {
557                 fprintf(stderr, "Error: you must run the 'setup' command "
558                         "first.\n");
559                 return -1;
560         }
561
562         memset(&data, 0, sizeof(data));
563         data.ioc_inllen1 = strlen(argv[1]) + 1;
564         data.ioc_inlbuf1 = argv[1];
565         data.ioc_nal = g_nal;
566         if (portal_ioctl_pack(&data, &buf, max) != 0) {
567                 fprintf(stderr, "portal_ioctl_pack failed.\n");
568                 return -1;
569         }
570
571         rc = ioctl(g_pfd, IOC_PORTAL_DEL_UUID, buf);
572         if (rc) {
573                 fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n",
574                         strerror(errno));
575                 return -1;
576         }
577         return 0;
578 }
579
580 int jt_net_add_route (int argc, char **argv) {
581         struct portal_ioctl_data data;
582         ptl_nid_t                nid1;
583         ptl_nid_t                nid2;
584         ptl_nid_t                gateway_nid;
585         int                      gateway_nal;
586         int                      rc;
587         
588         if (argc < 3)
589                 return CMD_HELP;
590
591         if (parse_nid (&gateway_nid, argv[1]) != 0) {
592                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
593                 return (-1);
594         }
595
596         gateway_nal = nid2nal (gateway_nid);
597         if (parse_nid (&nid1, argv[2]) != 0) {
598                 fprintf(stderr, "Can't parse first target NID \"%s\"\n",
599                         argv[2]);
600                 return (-1);
601         }
602
603         if (argc < 4) {
604                 nid2 = nid1;
605         } else if (parse_nid (&nid2, argv[3]) != 0) {
606                 fprintf(stderr, "Can't parse second target NID \"%s\"\n",
607                         argv[4]);
608                 return (-1);
609         }
610
611         PORTAL_IOC_INIT(data);
612         data.ioc_nid = gateway_nid;
613         data.ioc_nal = gateway_nal;
614         data.ioc_nid2 = MIN (nid1, nid2);
615         data.ioc_nid3 = MAX (nid1, nid2);
616
617         rc = ioctl (g_pfd, IOC_PORTAL_ADD_ROUTE, &data);
618         if (rc != 0) {
619                 fprintf(stderr, "IOC_PORTAL_ADD_ROUTE failed: %s\n",
620                         strerror (errno));
621                 return (-1);
622         }
623         
624         return (0);
625 }
626
627 int jt_net_del_route(int argc, char **argv) {
628         struct portal_ioctl_data data;
629         ptl_nid_t                nid;
630         int                      rc;
631         
632         if (argc < 2)
633                 return CMD_HELP;
634
635         if (parse_nid (&nid, argv[1]) != 0) {
636                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
637                 return (-1);
638         }
639
640         PORTAL_IOC_INIT(data);
641         data.ioc_nid = nid;
642
643         rc = ioctl (g_pfd, IOC_PORTAL_DEL_ROUTE, &data);
644         if (rc != 0) {
645                 fprintf(stderr, "IOC_PORTAL_DEL_ROUTE (0x%Lx) failed: %s\n",
646                         nid, strerror (errno));
647                 return (-1);
648         }
649         
650         return (0);
651 }
652
653 int jt_net_route_list(int argc, char **argv) {
654         char                      buffer[3][128];
655         struct portal_ioctl_data  data;
656         int                       rc;
657         int                       index;
658         int                       gateway_nal;
659         ptl_nid_t                 gateway_nid;
660         ptl_nid_t                 nid1;
661         ptl_nid_t                 nid2;
662         
663         for (index = 0;;index++) {
664                 PORTAL_IOC_INIT(data);
665                 data.ioc_count = index;
666                 
667                 rc = ioctl (g_pfd, IOC_PORTAL_GET_ROUTE, &data);
668                 if (rc != 0)
669                         break;
670
671                 gateway_nal = data.ioc_nal;
672                 gateway_nid = data.ioc_nid;
673                 nid1 = data.ioc_nid2;
674                 nid2 = data.ioc_nid3;
675                 
676                 printf ("%8s %18s : %s - %s\n", 
677                         nal2name (gateway_nal), 
678                         nid2str (buffer[0], gateway_nid),
679                         nid2str (buffer[1], nid1),
680                         nid2str (buffer[2], nid2));
681         }
682         return (0);
683 }
684
685 int jt_net_recv_mem(int argc, char **argv) {
686         int size;
687         
688         if (argc > 1) {
689                 if (Parser_size (&size, argv[1]) != 0 || size < 0) {
690                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
691                         return (0);
692                 }
693
694                 g_socket_rxmem = size;
695         }
696
697         printf ("Socket rxmem = %d\n", g_socket_rxmem);        
698         return (0);
699 }
700
701 int jt_net_send_mem(int argc, char **argv) {
702         int size;
703         
704         if (argc > 1) {
705                 if (Parser_size (&size, argv[1]) != 0 || size < 0) {
706                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
707                         return (0);
708                 }
709                 g_socket_txmem = size;
710         }
711
712         printf ("Socket txmem = %d\n", g_socket_txmem);
713         return (0);
714 }
715
716 int jt_net_nagle(int argc, char **argv) {
717         int enable;
718
719         if (argc > 1) {
720                 if (Parser_bool (&enable, argv[1]) != 0) {
721                         fprintf (stderr, "Can't parse boolean %s\n", argv[1]);
722                         return (0);
723                 }
724                 g_socket_nonagle = !enable;
725         }
726
727         printf ("Nagle %s\n", g_socket_nonagle ? "disabled" : "enabled");
728         return (0);
729 }