Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lnet / utils / portals.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 part of Portals, http://www.sf.net/projects/lustre/
7  *
8  *   Portals is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Portals is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Portals; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <netdb.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 <asm/byteorder.h>
37
38 #include <portals/api-support.h>
39 #include <portals/ptlctl.h>
40 #include <portals/list.h>
41 #include <portals/lib-types.h>
42 #include "parser.h"
43
44 unsigned int portal_debug;
45 unsigned int portal_printk;
46 unsigned int portal_stack;
47
48
49 static ptl_nid_t g_nid = 0;
50 static unsigned int g_nal = 0;
51 static unsigned short g_port = 0;
52
53 static int g_socket_txmem = 0;
54 static int g_socket_rxmem = 0;
55 static int g_socket_nonagle = 1;
56
57 typedef struct
58 {
59         char *name;
60         int   num;
61 } name2num_t;
62
63 static name2num_t nalnames[] = {
64         {"tcp",         SOCKNAL},
65         {"toe",         TOENAL},
66         {"elan",        QSWNAL},
67         {"gm",          GMNAL},
68         {"scimac",      SCIMACNAL},
69         {NULL,          -1}
70 };
71
72 static name2num_t *
73 name2num_lookup_name (name2num_t *table, char *str)
74 {
75         while (table->name != NULL)
76                 if (!strcmp (str, table->name))
77                         return (table);
78                 else
79                         table++;
80         return (NULL);
81 }
82
83 static name2num_t *
84 name2num_lookup_num (name2num_t *table, int num)
85 {
86         while (table->name != NULL)
87                 if (num == table->num)
88                         return (table);
89                 else
90                         table++;
91         return (NULL);
92 }
93
94 int
95 ptl_name2nal (char *str)
96 {
97         name2num_t *e = name2num_lookup_name (nalnames, str);
98
99         return ((e == NULL) ? 0 : e->num);
100 }
101
102 static char *
103 nal2name (int nal)
104 {
105         name2num_t *e = name2num_lookup_num (nalnames, nal);
106
107         return ((e == NULL) ? "???" : e->name);
108 }
109
110 static struct hostent *
111 ptl_gethostbyname(char * hname) {
112         struct hostent *he;
113         he = gethostbyname(hname);
114         if (!he) {
115                 switch(h_errno) {
116                 case HOST_NOT_FOUND:
117                 case NO_ADDRESS:
118                         fprintf(stderr, "Unable to resolve hostname: %s\n",
119                                 hname);
120                         break;
121                 default:
122                         fprintf(stderr, "gethostbyname error: %s\n",
123                                 strerror(errno));
124                         break;
125                 }
126                 return NULL;
127         }
128         return he;
129 }
130
131 int
132 ptl_parse_nid (ptl_nid_t *nidp, char *str)
133 {
134         struct hostent *he;
135         int             a;
136         int             b;
137         int             c;
138         int             d;
139         
140         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
141             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
142             (c & ~0xff) == 0 && (d & ~0xff) == 0)
143         {
144                 __u32 addr = (a<<24)|(b<<16)|(c<<8)|d;
145
146                 *nidp = (ptl_nid_t)addr;
147                 return (0);
148         }
149         
150         if ((('a' <= str[0] && str[0] <= 'z') ||
151              ('A' <= str[0] && str[0] <= 'Z')) &&
152              (he = ptl_gethostbyname (str)) != NULL)
153         {
154                 __u32 addr = *(__u32 *)he->h_addr;
155
156                 *nidp = (ptl_nid_t)ntohl(addr);  /* HOST byte order */
157                 return (0);
158         }
159
160         if (sscanf (str, "%i", &a) == 1)
161         {
162                 *nidp = (ptl_nid_t)a;
163                 return (0);
164         }
165
166         if (sscanf (str, "%x", &a) == 1)
167         {
168                 *nidp = (ptl_nid_t) a;
169                 return (0);
170         }
171
172         return (-1);
173 }
174
175 char *
176 ptl_nid2str (char *buffer, ptl_nid_t nid)
177 {
178         __u32           addr = htonl((__u32)nid); /* back to NETWORK byte order */
179         struct hostent *he = gethostbyaddr ((const char *)&addr, sizeof (addr), AF_INET);
180
181         if (he != NULL)
182                 strcpy (buffer, he->h_name);
183         else
184                 sprintf (buffer, "0x"LPX64, nid);
185         
186         return (buffer);
187 }
188
189 int
190 sock_write (int cfd, void *buffer, int nob)
191 {
192         while (nob > 0)
193         {
194                 int rc = write (cfd, buffer, nob);
195
196                 if (rc < 0)
197                 {
198                         if (errno == EINTR)
199                                 continue;
200                         
201                         return (rc);
202                 }
203
204                 if (rc == 0)
205                 {
206                         fprintf (stderr, "Unexpected zero sock_write\n");
207                         abort();
208                 }
209
210                 nob -= rc;
211                 buffer = (char *)buffer + nob;
212         }
213         
214         return (0);
215 }
216
217 int
218 sock_read (int cfd, void *buffer, int nob)
219 {
220         while (nob > 0)
221         {
222                 int rc = read (cfd, buffer, nob);
223                 
224                 if (rc < 0)
225                 {
226                         if (errno == EINTR)
227                                 continue;
228                         
229                         return (rc);
230                 }
231                 
232                 if (rc == 0)                    /* EOF */
233                 {
234                         errno = ECONNABORTED;
235                         return (-1);
236                 }
237                 
238                 nob -= rc;
239                 buffer = (char *)buffer + nob;
240         }
241         
242         return (0);
243 }
244
245 int ptl_initialize(int argc, char **argv) 
246 {
247         register_ioc_dev(PORTALS_DEV_ID, PORTALS_DEV_PATH);
248         return 0;
249 }
250
251
252 int jt_ptl_network(int argc, char **argv)
253 {
254         int  nal;
255         
256         if (argc != 2 ||
257             (nal = ptl_name2nal (argv[1])) == 0)
258         {
259                 name2num_t *entry;
260                 
261                 fprintf(stderr, "usage: %s \n", argv[0]);
262                 for (entry = nalnames; entry->name != NULL; entry++)
263                         fprintf (stderr, "%s%s", entry == nalnames ? "<" : "|", entry->name);
264                 fprintf(stderr, ">\n");
265         }
266         else
267                 g_nal = nal;
268
269         return (0);
270 }
271
272 int
273 exchange_nids (int cfd, ptl_nid_t my_nid, ptl_nid_t *peer_nid)
274 {
275         int                      rc;
276         ptl_hdr_t                hdr;
277         ptl_magicversion_t      *hmv = (ptl_magicversion_t *)&hdr.dest_nid;
278
279         LASSERT (sizeof (*hmv) == sizeof (hdr.dest_nid));
280
281         memset (&hdr, 0, sizeof (hdr));
282         
283         hmv->magic          = __cpu_to_le32 (PORTALS_PROTO_MAGIC);
284         hmv->version_major  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR);
285         hmv->version_minor  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR);
286
287         hdr.src_nid = __cpu_to_le64 (my_nid);
288         hdr.type = __cpu_to_le32 (PTL_MSG_HELLO);
289         
290         /* Assume there's sufficient socket buffering for a portals HELLO header */
291         rc = sock_write (cfd, &hdr, sizeof (hdr));
292         if (rc != 0) {
293                 perror ("Can't send initial HELLO");
294                 return (-1);
295         }
296
297         /* First few bytes down the wire are the portals protocol magic and
298          * version, no matter what protocol version we're running. */
299
300         rc = sock_read (cfd, hmv, sizeof (*hmv));
301         if (rc != 0) {
302                 perror ("Can't read from peer");
303                 return (-1);
304         }
305
306         if (__cpu_to_le32 (hmv->magic) != PORTALS_PROTO_MAGIC) {
307                 fprintf (stderr, "Bad magic %#08x (%#08x expected)\n", 
308                          __cpu_to_le32 (hmv->magic), PORTALS_PROTO_MAGIC);
309                 return (-1);
310         }
311
312         if (__cpu_to_le16 (hmv->version_major) != PORTALS_PROTO_VERSION_MAJOR ||
313             __cpu_to_le16 (hmv->version_minor) != PORTALS_PROTO_VERSION_MINOR) {
314                 fprintf (stderr, "Incompatible protocol version %d.%d (%d.%d expected)\n",
315                          __cpu_to_le16 (hmv->version_major),
316                          __cpu_to_le16 (hmv->version_minor),
317                          PORTALS_PROTO_VERSION_MAJOR,
318                          PORTALS_PROTO_VERSION_MINOR);
319         }
320
321         /* version 0 sends magic/version as the dest_nid of a 'hello' header,
322          * so read the rest of it in now... */
323         LASSERT (PORTALS_PROTO_VERSION_MAJOR == 0);
324         rc = sock_read (cfd, hmv + 1, sizeof (hdr) - sizeof (*hmv));
325         if (rc != 0) {
326                 perror ("Can't read rest of HELLO hdr");
327                 return (-1);
328         }
329
330         /* ...and check we got what we expected */
331         if (__cpu_to_le32 (hdr.type) != PTL_MSG_HELLO ||
332             __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)) != 0) {
333                 fprintf (stderr, "Expecting a HELLO hdr with 0 payload,"
334                          " but got type %d with %d payload\n",
335                          __cpu_to_le32 (hdr.type),
336                          __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)));
337                 return (-1);
338         }
339         
340         *peer_nid = __le64_to_cpu (hdr.src_nid);
341         return (0);
342 }
343
344 int jt_ptl_connect(int argc, char **argv)
345 {
346         if (argc < 2) {
347         usage:
348                 fprintf(stderr, "usage: %s <hostname port [xi]> or <elan ID>\n",
349                         argv[0]);
350                 return 0;
351         }
352         if (g_nal == 0) {
353                 fprintf(stderr, "Error: you must run the 'network' command "
354                         "first.\n");
355                 return -1;
356         }
357         if (g_nal == SOCKNAL || g_nal == TOENAL) {
358                 ptl_nid_t peer_nid;
359                 struct hostent *he;
360                 struct portal_ioctl_data data;
361                 struct sockaddr_in srvaddr;
362                 char *flag;
363                 int fd, rc;
364                 int nonagle = 0;
365                 int rxmem = 0;
366                 int txmem = 0;
367                 int bind_irq = 0;
368                 int xchange_nids = 0;
369                 int o;
370                 int olen;
371                 
372                 if (argc < 3) {
373                         goto usage;
374                 }
375
376                 he = ptl_gethostbyname(argv[1]);
377                 if (!he)
378                         return -1;
379
380                 g_port = atol(argv[2]);
381
382                 if (argc > 3)
383                         for (flag = argv[3]; *flag != 0; flag++)
384                                 switch (*flag)
385                                 {
386                                 case 'i':
387                                         bind_irq = 1;
388                                         break;
389                                         
390                                 case 'x':
391                                         xchange_nids = 1;
392                                         break;
393
394                                 default:
395                                         fprintf (stderr, "unrecognised flag '%c'\n",
396                                                  *flag);
397                                         return (-1);
398                                 }
399                 
400                 memset(&srvaddr, 0, sizeof(srvaddr));
401                 srvaddr.sin_family = AF_INET;
402                 srvaddr.sin_port = htons(g_port);
403                 srvaddr.sin_addr.s_addr = *(__u32 *)he->h_addr;
404         
405                 fd = socket(PF_INET, SOCK_STREAM, 0);
406                 if ( fd < 0 ) {
407                         fprintf(stderr, "socket() failed: %s\n",
408                                 strerror(errno));
409                         return -1;
410                 }
411
412                 if (g_socket_nonagle)
413                 {
414                         o = 1;
415                         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &o, sizeof (o)) != 0)
416                         { 
417                                 fprintf(stderr, "cannot disable nagle: %s\n", strerror(errno));
418                                 return (-1);
419                         }
420                 }
421
422                 if (g_socket_rxmem != 0)
423                 {
424                         o = g_socket_rxmem;
425                         if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &o, sizeof (o)) != 0)
426                         { 
427                                 fprintf(stderr, "cannot set receive buffer size: %s\n", strerror(errno));
428                                 return (-1);
429                         }
430                 }
431
432                 if (g_socket_txmem != 0)
433                 {
434                         o = g_socket_txmem;
435                         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &o, sizeof (o)) != 0)
436                         { 
437                                 fprintf(stderr, "cannot set send buffer size: %s\n", strerror(errno));
438                                 return (-1);
439                         }
440                 }
441
442                 rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
443                 if ( rc == -1 ) { 
444                         fprintf(stderr, "connect() failed: %s\n",
445                                 strerror(errno));
446                         return -1;
447                 }
448
449                 olen = sizeof (txmem);
450                 if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &olen) != 0)
451                         fprintf (stderr, "Can't get send buffer size: %s\n", strerror (errno));
452                 olen = sizeof (rxmem);
453                 if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &olen) != 0)
454                         fprintf (stderr, "Can't get receive buffer size: %s\n", strerror (errno));
455                 olen = sizeof (nonagle);
456                 if (getsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nonagle, &olen) != 0)
457                         fprintf (stderr, "Can't get nagle: %s\n", strerror (errno));
458
459                 if (xchange_nids) {
460                         
461                         PORTAL_IOC_INIT (data);
462                         data.ioc_nal = g_nal;
463                         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
464                         if (rc != 0)
465                         {
466                                 fprintf (stderr, "failed to get my nid: %s\n",
467                                          strerror (errno));
468                                 close (fd);
469                                 return (-1);
470                         }
471                         
472                         rc = exchange_nids (fd, data.ioc_nid, &peer_nid);
473                         if (rc != 0)
474                         {
475                                 close (fd);
476                                 return (-1);
477                         }
478                 }
479                 else
480                         peer_nid = ntohl (srvaddr.sin_addr.s_addr); /* HOST byte order */
481
482                 printf("Connected host: %s NID "LPX64" snd: %d rcv: %d nagle: %s\n", argv[1],
483                        peer_nid, txmem, rxmem, nonagle ? "Disabled" : "Enabled");
484
485                 PORTAL_IOC_INIT(data);
486                 data.ioc_fd = fd;
487                 data.ioc_nal = g_nal;
488                 data.ioc_nal_cmd = NAL_CMD_REGISTER_PEER_FD;
489                 data.ioc_nid = peer_nid;
490                 data.ioc_flags = bind_irq;
491                 
492                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
493                 if (rc) {
494                         fprintf(stderr, "failed to register fd with portals: "
495                                 "%s\n", strerror(errno));
496                         close (fd);
497                         return -1;
498                 }
499
500                 g_nid = peer_nid;
501                 printf("Connection to "LPX64" registered with socknal\n", g_nid);
502
503                 rc = close(fd);
504                 if (rc) {
505                         fprintf(stderr, "close failed: %d\n", rc);
506                 }
507         } else if (g_nal == QSWNAL) {
508                 g_nid = atoi(argv[1]);
509         } else if (g_nal == GMNAL) {
510                 g_nid = atoi(argv[1]);
511         } else if (g_nal == SCIMACNAL) {
512                 unsigned int    tmpnid;
513                 if(sscanf(argv[1], "%x", &tmpnid) == 1) {
514                         g_nid=tmpnid;
515                 }
516                 else {
517                         fprintf(stderr, "nid %s invalid for SCI nal\n", argv[1]);
518                 }
519
520
521         } else {
522                 fprintf(stderr, "This should never happen.  Also it is very "
523                         "bad.\n");
524         }
525
526         return 0;
527 }
528
529 int jt_ptl_disconnect(int argc, char **argv)
530 {
531         if (argc > 2) {
532                 fprintf(stderr, "usage: %s [hostname]\n", argv[0]);
533                 return 0;
534         }
535         if (g_nal == 0) {
536                 fprintf(stderr, "Error: you must run the 'network' command "
537                         "first.\n");
538                 return -1;
539         }
540         if (g_nal == SOCKNAL || g_nal == TOENAL) {
541                 struct hostent *he;
542                 struct portal_ioctl_data data;
543                 int rc;
544
545                 PORTAL_IOC_INIT(data);
546                 if (argc == 2) {
547                         he = ptl_gethostbyname(argv[1]);
548                         if (!he) 
549                                 return -1;
550                         
551                         data.ioc_nid = ntohl (*(__u32 *)he->h_addr); /* HOST byte order */
552
553                 } else {
554                         printf("Disconnecting ALL connections.\n");
555                         /* leave ioc_nid zeroed == disconnect all */
556                 }
557                 data.ioc_nal = g_nal;
558                 data.ioc_nal_cmd = NAL_CMD_CLOSE_CONNECTION;
559                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
560                 if (rc) {
561                         fprintf(stderr, "failed to remove connection: %s\n",
562                                 strerror(errno));
563                         return -1;
564                 }
565         } else if (g_nal == QSWNAL) {
566                 printf("'disconnect' doesn't make any sense for "
567                         "elan.\n");
568         } else if (g_nal == GMNAL) {
569                 printf("'disconnect' doesn't make any sense for "
570                         "GM.\n");
571         } else if (g_nal == SCIMACNAL) {
572                 printf("'disconnect' doesn't make any sense for "
573                         "SCI.\n");
574         } else {
575                 fprintf(stderr, "This should never happen.  Also it is very "
576                         "bad.\n");
577                 return -1;
578         }
579
580         return 0;
581 }
582
583 int jt_ptl_push_connection (int argc, char **argv)
584 {
585         if (argc > 2) {
586                 fprintf(stderr, "usage: %s [hostname]\n", argv[0]);
587                 return 0;
588         }
589         if (g_nal == 0) {
590                 fprintf(stderr, "Error: you must run the 'network' command "
591                         "first.\n");
592                 return -1;
593         }
594         if (g_nal == SOCKNAL || g_nal == TOENAL) {
595                 struct hostent *he;
596                 struct portal_ioctl_data data;
597                 int rc;
598
599                 PORTAL_IOC_INIT(data);
600                 if (argc == 2) {
601                         he = ptl_gethostbyname(argv[1]);
602                         if (!he)
603                                 return -1;
604                         
605                         data.ioc_nid = ntohl (*(__u32 *)he->h_addr); /* HOST byte order */
606
607                 } else {
608                         printf("Pushing ALL connections.\n");
609                         /* leave ioc_nid zeroed == disconnect all */
610                 }
611                 data.ioc_nal = g_nal;
612                 data.ioc_nal_cmd = NAL_CMD_PUSH_CONNECTION;
613                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
614                 if (rc) {
615                         fprintf(stderr, "failed to push connection: %s\n",
616                                 strerror(errno));
617                         return -1;
618                 }
619         } else if (g_nal == QSWNAL) {
620                 printf("'push' doesn't make any sense for elan.\n");
621         } else if (g_nal == GMNAL) {
622                 printf("'push' doesn't make any sense for GM.\n");
623         } else if (g_nal == SCIMACNAL) {
624                 printf("'push' doesn't make any sense for SCI.\n");
625         } else {
626                 fprintf(stderr, "This should never happen.  Also it is very "
627                         "bad.\n");
628                 return -1;
629         }
630
631         return 0;
632 }
633
634 int jt_ptl_ping(int argc, char **argv)
635 {
636         int       rc;
637         ptl_nid_t nid;
638         long      count   = 1;
639         long      size    = 4;
640         long      timeout = 1;
641         struct portal_ioctl_data data;
642
643         if (argc < 2) {
644                 fprintf(stderr, "usage: %s nid [count] [size] [timeout (secs)]\n", argv[0]);
645                 return 0;
646         }
647
648         if (g_nal == 0) {
649                 fprintf(stderr, "Error: you must run the 'network' command "
650                         "first.\n");
651                 return -1;
652         }
653
654         if (ptl_parse_nid (&nid, argv[1]) != 0)
655         {
656                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
657                 return (-1);
658         }
659         
660         if (argc > 2)
661         {
662                 count = atol(argv[2]);
663
664                 if (count < 0 || count > 20000) 
665                 {
666                         fprintf(stderr, "are you insane?  %ld is a crazy count.\n", count);
667                         return -1;
668                 }
669         }
670         
671         if (argc > 3)
672                 size= atol(argv[3]);
673
674         if (argc > 4)
675                 timeout = atol (argv[4]);
676         
677         PORTAL_IOC_INIT (data);
678         data.ioc_count   = count;
679         data.ioc_size    = size;
680         data.ioc_nid     = nid;
681         data.ioc_nal     = g_nal;
682         data.ioc_timeout = timeout;
683         
684         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PING, &data);
685         if (rc) {
686                 fprintf(stderr, "failed to start pinger: %s\n",
687                         strerror(errno));
688                 return -1;
689         }
690         return 0;
691 }
692
693 int jt_ptl_shownid(int argc, char **argv)
694 {
695         struct portal_ioctl_data data;
696         int                      rc;
697         
698         if (argc > 1) {
699                 fprintf(stderr, "usage: %s\n", argv[0]);
700                 return 0;
701         }
702         
703         if (g_nal == 0) {
704                 fprintf(stderr, "Error: you must run the 'network' command first\n");
705                 return -1;
706         }
707         
708         PORTAL_IOC_INIT (data);
709         data.ioc_nal = g_nal;
710         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
711         if (rc < 0)
712                 fprintf(stderr, "getting my NID failed: %s\n",
713                         strerror (errno));
714         else
715                 printf(LPX64"\n", data.ioc_nid);
716         return 0;
717 }
718
719 int jt_ptl_mynid(int argc, char **argv)
720 {
721         int rc;
722         char hostname[1024];
723         char *nidstr;
724         struct portal_ioctl_data data;
725         ptl_nid_t mynid;
726         
727         if (argc > 2) {
728                 fprintf(stderr, "usage: %s [NID]\n", argv[0]);
729                 fprintf(stderr, "NID defaults to the primary IP address of the machine.\n");
730                 return 0;
731         }
732
733         if (g_nal == 0) {
734                 fprintf(stderr, "Error: you must run the 'network' command "
735                         "first.\n");
736                 return -1;
737         }
738
739         if (argc >= 2)
740                 nidstr = argv[1];
741         else if (gethostname(hostname, sizeof(hostname)) != 0) {
742                 fprintf(stderr, "gethostname failed: %s\n",
743                         strerror(errno));
744                 return -1;
745         }
746         else
747                 nidstr = hostname;
748
749         rc = ptl_parse_nid (&mynid, nidstr);
750         if (rc != 0) {
751                 fprintf (stderr, "Can't convert '%s' into a NID\n", nidstr);
752                 return -1;
753         }
754         
755         PORTAL_IOC_INIT(data);
756         data.ioc_nid = mynid;
757         data.ioc_nal = g_nal;
758         data.ioc_nal_cmd = NAL_CMD_REGISTER_MYNID;
759
760         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
761         if (rc < 0)
762                 fprintf(stderr, "setting my NID failed: %s\n",
763                        strerror(errno));
764         else
765                 printf("registered my nid "LPX64" (%s)\n", mynid, hostname);
766         return 0;
767 }
768
769 int
770 jt_ptl_fail_nid (int argc, char **argv)
771 {
772         int                      rc;
773         ptl_nid_t                nid;
774         unsigned int             threshold;
775         struct portal_ioctl_data data;
776
777         if (argc < 2 || argc > 3)
778         {
779                 fprintf (stderr, "usage: %s nid|\"_all_\" [count (0 == mend)]\n", argv[0]);
780                 return (0);
781         }
782         
783         if (g_nal == 0) {
784                 fprintf(stderr, "Error: you must run the 'network' command "
785                         "first.\n");
786                 return (-1);
787         }
788
789         if (!strcmp (argv[1], "_all_"))
790                 nid = PTL_NID_ANY;
791         else if (ptl_parse_nid (&nid, argv[1]) != 0)
792         {
793                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
794                 return (-1);
795         }
796
797         if (argc < 3)
798                 threshold = PTL_MD_THRESH_INF;
799         else if (sscanf (argv[2], "%i", &threshold) != 1) {
800                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
801                 return (-1);
802         }
803         
804         PORTAL_IOC_INIT (data);
805         data.ioc_nal = g_nal;
806         data.ioc_nid = nid;
807         data.ioc_count = threshold;
808         
809         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_FAIL_NID, &data);
810         if (rc < 0)
811                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
812                          strerror (errno));
813         else
814                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
815         
816         return (0);
817 }
818
819 int
820 jt_ptl_rxmem (int argc, char **argv)
821 {
822         int   size;
823         
824         if (argc > 1)
825         {
826                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
827                 {
828                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
829                         return (0);
830                 }
831
832                 g_socket_rxmem = size;
833         }
834         printf ("Socket rmem = %d\n", g_socket_rxmem);        
835         return (0);
836 }
837
838 int
839 jt_ptl_txmem (int argc, char **argv)
840 {
841         int   size;
842         
843         if (argc > 1)
844         {
845                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
846                 {
847                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
848                         return (0);
849                 }
850                 g_socket_txmem = size;
851         }
852         printf ("Socket txmem = %d\n", g_socket_txmem);
853         return (0);
854 }
855
856 int
857 jt_ptl_nagle (int argc, char **argv)
858 {
859         int enable;
860
861         if (argc > 1)
862         {
863                 if (Parser_bool (&enable, argv[1]) != 0)
864                 {
865                         fprintf (stderr, "Can't parse boolean %s\n", argv[1]);
866                         return (0);
867                 }
868                 g_socket_nonagle = !enable;
869         }
870         printf ("Nagle %s\n", g_socket_nonagle ? "disabled" : "enabled");
871         return (0);
872 }
873
874 int
875 jt_ptl_add_route (int argc, char **argv)
876 {
877         struct portal_ioctl_data data;
878         ptl_nid_t                nid1;
879         ptl_nid_t                nid2;
880         ptl_nid_t                gateway_nid;
881         int                      rc;
882         
883         if (argc < 3)
884         {
885                 fprintf (stderr, "usage: %s gateway target [target]\n", argv[0]);
886                 return (0);
887         }
888
889         if (g_nal == 0) {
890                 fprintf(stderr, "Error: you must run the 'network' command "
891                         "first.\n");
892                 return (-1);
893         }
894
895         if (ptl_parse_nid (&gateway_nid, argv[1]) != 0)
896         {
897                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
898                 return (-1);
899         }
900
901         if (ptl_parse_nid (&nid1, argv[2]) != 0)
902         {
903                 fprintf (stderr, "Can't parse first target NID \"%s\"\n", argv[2]);
904                 return (-1);
905         }
906
907         if (argc < 4)
908                 nid2 = nid1;
909         else if (ptl_parse_nid (&nid2, argv[3]) != 0)
910         {
911                 fprintf (stderr, "Can't parse second target NID \"%s\"\n", argv[4]);
912                 return (-1);
913         }
914
915         PORTAL_IOC_INIT(data);
916         data.ioc_nid = gateway_nid;
917         data.ioc_nal = g_nal;
918         data.ioc_nid2 = MIN (nid1, nid2);
919         data.ioc_nid3 = MAX (nid1, nid2);
920
921         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_ADD_ROUTE, &data);
922         if (rc != 0) 
923         {
924                 fprintf (stderr, "IOC_PORTAL_ADD_ROUTE failed: %s\n", strerror (errno));
925                 return (-1);
926         }
927         
928         return (0);
929 }
930
931 int
932 jt_ptl_del_route (int argc, char **argv)
933 {
934         struct portal_ioctl_data data;
935         ptl_nid_t                nid;
936         int                      rc;
937         
938         if (argc < 2)
939         {
940                 fprintf (stderr, "usage: %s targetNID\n", argv[0]);
941                 return (0);
942         }
943
944         if (ptl_parse_nid (&nid, argv[1]) != 0)
945         {
946                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
947                 return (-1);
948         }
949
950         PORTAL_IOC_INIT(data);
951         data.ioc_nid = nid;
952
953         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_DEL_ROUTE, &data);
954         if (rc != 0) 
955         {
956                 fprintf (stderr, "IOC_PORTAL_DEL_ROUTE ("LPX64") failed: %s\n", nid, strerror (errno));
957                 return (-1);
958         }
959         
960         return (0);
961 }
962
963 int
964 jt_ptl_print_routes (int argc, char **argv)
965 {
966         char                      buffer[3][128];
967         struct portal_ioctl_data  data;
968         int                       rc;
969         int                       index;
970         int                       gateway_nal;
971         ptl_nid_t                 gateway_nid;
972         ptl_nid_t                 nid1;
973         ptl_nid_t                 nid2;
974         
975         
976         for (index = 0;;index++)
977         {
978                 PORTAL_IOC_INIT(data);
979                 data.ioc_count = index;
980                 
981                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_ROUTE, &data);
982                 if (rc != 0)
983                         break;
984
985                 gateway_nal = data.ioc_nal;
986                 gateway_nid = data.ioc_nid;
987                 nid1 = data.ioc_nid2;
988                 nid2 = data.ioc_nid3;
989                 
990                 printf ("%8s %18s : %s - %s\n", 
991                         nal2name (gateway_nal), 
992                         ptl_nid2str (buffer[0], gateway_nid),
993                         ptl_nid2str (buffer[1], nid1),
994                         ptl_nid2str (buffer[2], nid2));
995         }
996         return (0);
997 }
998