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