Whamcloud - gitweb
merge b_multinet into HEAD
[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 <stdarg.h>
37 #include <asm/byteorder.h>
38
39 #include <portals/api-support.h>
40 #include <portals/ptlctl.h>
41 #include <portals/list.h>
42 #include <portals/lib-types.h>
43 #include "parser.h"
44
45 unsigned int portal_debug;
46 unsigned int portal_printk;
47 unsigned int portal_stack;
48
49
50 static unsigned int g_nal = 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 static struct hostent *
110 ptl_gethostbyname(char * hname) {
111         struct hostent *he;
112         he = gethostbyname(hname);
113         if (!he) {
114                 switch(h_errno) {
115                 case HOST_NOT_FOUND:
116                 case NO_ADDRESS:
117                         fprintf(stderr, "Unable to resolve hostname: %s\n",
118                                 hname);
119                         break;
120                 default:
121                         fprintf(stderr, "gethostbyname error: %s\n",
122                                 strerror(errno));
123                         break;
124                 }
125                 return NULL;
126         }
127         return he;
128 }
129
130 int
131 ptl_parse_ipaddr (__u32 *ipaddrp, char *str)
132 {
133         struct hostent *he;
134         int             a;
135         int             b;
136         int             c;
137         int             d;
138
139         if (!strcmp (str, "_all_")) 
140         {
141                 *ipaddrp = 0;
142                 return (0);
143         }
144
145         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
146             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
147             (c & ~0xff) == 0 && (d & ~0xff) == 0)
148         {
149                 *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
150                 return (0);
151         }
152         
153         if ((('a' <= str[0] && str[0] <= 'z') ||
154              ('A' <= str[0] && str[0] <= 'Z')) &&
155              (he = ptl_gethostbyname (str)) != NULL)
156         {
157                 __u32 addr = *(__u32 *)he->h_addr;
158
159                 *ipaddrp = ntohl(addr);         /* HOST byte order */
160                 return (0);
161         }
162
163         return (-1);
164 }
165
166 char *
167 ptl_ipaddr_2_str (__u32 ipaddr, char *str)
168 {
169         __u32           net_ip;
170         struct hostent *he;
171         
172         net_ip = htonl (ipaddr);
173         he = gethostbyaddr (&net_ip, sizeof (net_ip), AF_INET);
174         if (he != NULL)
175                 return (he->h_name);
176         
177         sprintf (str, "%d.%d.%d.%d",
178                  (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
179                  (ipaddr >> 8) & 0xff, ipaddr & 0xff);
180         return (str);
181 }
182
183 int
184 ptl_parse_nid (ptl_nid_t *nidp, char *str)
185 {
186         __u32 ipaddr;
187         long  lval;
188         
189         if (!strcmp (str, "_all_")) {
190                 *nidp = PTL_NID_ANY;
191                 return (0);
192         }
193
194         if (ptl_parse_ipaddr (&ipaddr, str) == 0) {
195                 *nidp = (ptl_nid_t)ipaddr;
196                 return (0);
197         }
198
199         if (sscanf (str, "%li", &lval) == 1)
200         {
201                 *nidp = (ptl_nid_t)lval;
202                 return (0);
203         }
204
205         if (sscanf (str, "%lx", &lval) == 1)
206         {
207                 *nidp = (ptl_nid_t)lval;
208                 return (0);
209         }
210
211         return (-1);
212 }
213
214 char *
215 ptl_nid2str (char *buffer, ptl_nid_t nid)
216 {
217         __u32           addr = htonl((__u32)nid); /* back to NETWORK byte order */
218         struct hostent *he = gethostbyaddr ((const char *)&addr, sizeof (addr), AF_INET);
219
220         if (he != NULL)
221                 strcpy (buffer, he->h_name);
222         else
223                 sprintf (buffer, "0x"LPX64, nid);
224         
225         return (buffer);
226 }
227
228 int g_nal_is_compatible (char *cmd, ...)
229 {
230         va_list       ap;
231         int           nal;
232         
233         if (g_nal == 0) {
234                 fprintf (stderr, "Error: you must run the 'network' command first.\n");
235                 return (0);
236         }
237         
238         va_start (ap, cmd);
239
240         do {
241                 nal = va_arg (ap, int);
242         } while (nal != 0 && nal != g_nal);
243         
244         va_end (ap);
245         
246         if (g_nal == nal)
247                 return (1);
248         
249         fprintf (stderr, "Command %s not compatible with nal %s\n",
250                  cmd, nal2name (g_nal));
251         return (0);
252 }
253
254 int
255 sock_write (int cfd, void *buffer, int nob)
256 {
257         while (nob > 0)
258         {
259                 int rc = write (cfd, buffer, nob);
260
261                 if (rc < 0)
262                 {
263                         if (errno == EINTR)
264                                 continue;
265                         
266                         return (rc);
267                 }
268
269                 if (rc == 0)
270                 {
271                         fprintf (stderr, "Unexpected zero sock_write\n");
272                         abort();
273                 }
274
275                 nob -= rc;
276                 buffer = (char *)buffer + nob;
277         }
278         
279         return (0);
280 }
281
282 int
283 sock_read (int cfd, void *buffer, int nob)
284 {
285         while (nob > 0)
286         {
287                 int rc = read (cfd, buffer, nob);
288                 
289                 if (rc < 0)
290                 {
291                         if (errno == EINTR)
292                                 continue;
293                         
294                         return (rc);
295                 }
296                 
297                 if (rc == 0)                    /* EOF */
298                 {
299                         errno = ECONNABORTED;
300                         return (-1);
301                 }
302                 
303                 nob -= rc;
304                 buffer = (char *)buffer + nob;
305         }
306         
307         return (0);
308 }
309
310 int ptl_initialize(int argc, char **argv) 
311 {
312         register_ioc_dev(PORTALS_DEV_ID, PORTALS_DEV_PATH);
313         return 0;
314 }
315
316
317 int jt_ptl_network(int argc, char **argv)
318 {
319         name2num_t *entry;
320         int         nal;
321         
322         if (argc == 2 &&
323             (nal = ptl_name2nal (argv[1])) != 0) {
324                 g_nal = nal;
325                 return (0);
326         }
327                 
328         fprintf(stderr, "usage: %s \n", argv[0]);
329         for (entry = nalnames; entry->name != NULL; entry++)
330                 fprintf (stderr, "%s%s", entry == nalnames ? "<" : "|", entry->name);
331         fprintf(stderr, ">\n");
332         return (-1);
333 }
334
335 int 
336 jt_ptl_print_autoconnects (int argc, char **argv)
337 {
338         struct portal_ioctl_data data;
339         char                     buffer[64];
340         int                      index;
341         int                      rc;
342
343         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
344                 return -1;
345
346         for (index = 0;;index++) {
347                 PORTAL_IOC_INIT (data);
348                 data.ioc_nal     = g_nal;
349                 data.ioc_nal_cmd = NAL_CMD_GET_AUTOCONN;
350                 data.ioc_count   = index;
351                 
352                 rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
353                 if (rc != 0)
354                         break;
355
356                 printf (LPX64"@%s:%d #%d buffer %d nonagle %s xchg %s affinity %s share %d\n",
357                         data.ioc_nid, ptl_ipaddr_2_str (data.ioc_id, buffer),
358                         data.ioc_misc, data.ioc_count, data.ioc_size, 
359                         (data.ioc_flags & 1) ? "on" : "off",
360                         (data.ioc_flags & 2) ? "on" : "off",
361                         (data.ioc_flags & 4) ? "on" : "off",
362                         data.ioc_wait);
363         }
364
365         if (index == 0)
366                 printf ("<no autoconnect routes>\n");
367         return 0;
368 }
369
370 int 
371 jt_ptl_add_autoconnect (int argc, char **argv)
372 {
373         struct portal_ioctl_data data;
374         ptl_nid_t                nid;
375         __u32                    ip;
376         int                      port;
377         int                      xchange_nids = 0;
378         int                      irq_affinity = 0;
379         int                      share = 0;
380         int                      rc;
381
382         if (argc < 4 || argc > 5) {
383                 fprintf (stderr, "usage: %s nid ipaddr port [ixs]\n", argv[0]);
384                 return 0;
385         }
386
387         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
388                 return -1;
389
390         if (ptl_parse_nid (&nid, argv[1]) != 0 ||
391                 nid == PTL_NID_ANY) {
392                 fprintf (stderr, "Can't parse NID: %s\n", argv[1]);
393                 return -1;
394         }
395
396         if (ptl_parse_ipaddr (&ip, argv[2]) != 0) {
397                 fprintf (stderr, "Can't parse ip addr: %s\n", argv[2]);
398                 return -1;
399         }
400
401         port = atol (argv[3]);
402         
403         if (argc > 4) {
404                 char *opts = argv[4];
405                 
406                 while (*opts != 0)
407                         switch (*opts++) {
408                         case 'x':
409                                 xchange_nids = 1;
410                                 break;
411                         case 'i':
412                                 irq_affinity = 1;
413                                 break;
414                         case 's':
415                                 share = 1;
416                                 break;
417                         default:
418                                 fprintf (stderr, "Can't parse options: %s\n",
419                                          argv[4]);
420                                 return -1;
421                         }
422         }
423
424         PORTAL_IOC_INIT (data);
425         data.ioc_nal     = g_nal;
426         data.ioc_nal_cmd = NAL_CMD_ADD_AUTOCONN;
427         data.ioc_nid     = nid;
428         data.ioc_id      = ip;
429         data.ioc_misc    = port;
430         /* only passing one buffer size! */
431         data.ioc_size    = MAX (g_socket_rxmem, g_socket_txmem);
432         data.ioc_flags   = (g_socket_nonagle ? 1 : 0) |
433                            (xchange_nids     ? 2 : 0) |
434                            (irq_affinity     ? 4 : 0) |
435                            (share            ? 8 : 0);
436
437         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
438         if (rc != 0) {
439                 fprintf (stderr, "failed to enable autoconnect: %s\n",
440                          strerror (errno));
441                 return -1;
442         }
443         
444         return 0;
445 }
446
447 int 
448 jt_ptl_del_autoconnect (int argc, char **argv)
449 {
450         struct portal_ioctl_data data;
451         ptl_nid_t                nid = PTL_NID_ANY;
452         __u32                    ip  = 0;
453         int                      share = 0;
454         int                      keep_conn = 0;
455         int                      rc;
456
457         if (argc > 4) {
458                 fprintf (stderr, "usage: %s [nid] [ipaddr] [sk]\n",
459                          argv[0]);
460                 return 0;
461         }
462
463         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
464                 return -1;
465
466         if (argc > 1 &&
467             ptl_parse_nid (&nid, argv[1]) != 0) {
468                 fprintf (stderr, "Can't parse nid: %s\n", argv[1]);
469                 return -1;
470         }
471
472         if (argc > 2 &&
473             ptl_parse_ipaddr (&ip, argv[2]) != 0) {
474                 fprintf (stderr, "Can't parse ip addr: %s\n", argv[2]);
475                 return -1;
476         }
477
478         if (argc > 3) {
479                 char *opts = argv[3];
480                 
481                 while (*opts != 0)
482                         switch (*opts++) {
483                         case 's':
484                                 share = 1;
485                                 break;
486                         case 'k':
487                                 keep_conn = 1;
488                                 break;
489                         default:
490                                 fprintf (stderr, "Can't parse flags: %s\n", 
491                                          argv[3]);
492                                 return -1;
493                         }
494         }
495
496         PORTAL_IOC_INIT (data);
497         data.ioc_nal     = g_nal;
498         data.ioc_nal_cmd = NAL_CMD_DEL_AUTOCONN;
499         data.ioc_nid     = nid;
500         data.ioc_id      = ip;
501         data.ioc_flags   = (share     ? 1 : 0) |
502                            (keep_conn ? 2 : 0);
503         
504         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
505         if (rc != 0) {
506                 fprintf (stderr, "failed to remove autoconnect route: %s\n",
507                          strerror (errno));
508                 return -1;
509         }
510         
511         return 0;
512 }
513
514 int 
515 jt_ptl_print_connections (int argc, char **argv)
516 {
517         struct portal_ioctl_data data;
518         char                     buffer[64];
519         int                      index;
520         int                      rc;
521
522         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
523                 return -1;
524
525         for (index = 0;;index++) {
526                 PORTAL_IOC_INIT (data);
527                 data.ioc_nal     = g_nal;
528                 data.ioc_nal_cmd = NAL_CMD_GET_CONN;
529                 data.ioc_count   = index;
530                 
531                 rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
532                 if (rc != 0)
533                         break;
534
535                 printf (LPD64"@%s:%d\n",
536                         data.ioc_nid, 
537                         ptl_ipaddr_2_str (data.ioc_id, buffer),
538                         data.ioc_misc);
539         }
540
541         if (index == 0)
542                 printf ("<no connections>\n");
543         return 0;
544 }
545
546 int
547 exchange_nids (int cfd, ptl_nid_t my_nid, ptl_nid_t *peer_nid)
548 {
549         int                      rc;
550         ptl_hdr_t                hdr;
551         ptl_magicversion_t      *hmv = (ptl_magicversion_t *)&hdr.dest_nid;
552
553         LASSERT (sizeof (*hmv) == sizeof (hdr.dest_nid));
554
555         memset (&hdr, 0, sizeof (hdr));
556         
557         hmv->magic          = __cpu_to_le32 (PORTALS_PROTO_MAGIC);
558         hmv->version_major  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR);
559         hmv->version_minor  = __cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR);
560
561         hdr.src_nid = __cpu_to_le64 (my_nid);
562         hdr.type = __cpu_to_le32 (PTL_MSG_HELLO);
563         
564         /* Assume there's sufficient socket buffering for a portals HELLO header */
565         rc = sock_write (cfd, &hdr, sizeof (hdr));
566         if (rc != 0) {
567                 perror ("Can't send initial HELLO");
568                 return (-1);
569         }
570
571         /* First few bytes down the wire are the portals protocol magic and
572          * version, no matter what protocol version we're running. */
573
574         rc = sock_read (cfd, hmv, sizeof (*hmv));
575         if (rc != 0) {
576                 perror ("Can't read from peer");
577                 return (-1);
578         }
579
580         if (hmv->magic != __cpu_to_le32 (PORTALS_PROTO_MAGIC)) {
581                 fprintf (stderr, "Bad magic %#08x (%#08x expected)\n", 
582                          __le32_to_cpu (hmv->magic), PORTALS_PROTO_MAGIC);
583                 return (-1);
584         }
585
586         if (hmv->version_major != __cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR) ||
587             hmv->version_minor != __cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR)) {
588                 fprintf (stderr, "Incompatible protocol version %d.%d (%d.%d expected)\n",
589                          __le16_to_cpu (hmv->version_major),
590                          __le16_to_cpu (hmv->version_minor),
591                          PORTALS_PROTO_VERSION_MAJOR,
592                          PORTALS_PROTO_VERSION_MINOR);
593         }
594
595         /* version 0 sends magic/version as the dest_nid of a 'hello' header,
596          * so read the rest of it in now... */
597         LASSERT (PORTALS_PROTO_VERSION_MAJOR == 0);
598         rc = sock_read (cfd, hmv + 1, sizeof (hdr) - sizeof (*hmv));
599         if (rc != 0) {
600                 perror ("Can't read rest of HELLO hdr");
601                 return (-1);
602         }
603
604         /* ...and check we got what we expected */
605         if (hdr.type != __cpu_to_le32 (PTL_MSG_HELLO) ||
606             PTL_HDR_LENGTH (&hdr) != __cpu_to_le32 (0)) {
607                 fprintf (stderr, "Expecting a HELLO hdr with 0 payload,"
608                          " but got type %d with %d payload\n",
609                          __le32_to_cpu (hdr.type),
610                          __le32_to_cpu (PTL_HDR_LENGTH (&hdr)));
611                 return (-1);
612         }
613         
614         *peer_nid = __le64_to_cpu (hdr.src_nid);
615         return (0);
616 }
617
618 int jt_ptl_connect(int argc, char **argv)
619 {
620         ptl_nid_t peer_nid;
621         struct portal_ioctl_data data;
622         struct sockaddr_in srvaddr;
623         __u32 ipaddr;
624         char *flag;
625         int fd, rc;
626         int nonagle = 0;
627         int rxmem = 0;
628         int txmem = 0;
629         int bind_irq = 0;
630         int xchange_nids = 0;
631         int port;
632         int o;
633         int olen;
634
635         if (argc < 3) {
636                 fprintf(stderr, "usage: %s ip port [xi]\n", argv[0]);
637                 return 0;
638         }
639
640         if (!g_nal_is_compatible (argv[0], SOCKNAL, TOENAL, 0))
641                 return -1;
642         
643         rc = ptl_parse_ipaddr (&ipaddr, argv[1]);
644         if (rc != 0) {
645                 fprintf(stderr, "Can't parse hostname: %s\n", argv[1]);
646                 return -1;
647         }
648
649         port = atol(argv[2]);
650         if (argc > 3)
651                 for (flag = argv[3]; *flag != 0; flag++)
652                         switch (*flag)
653                         {
654                         case 'i':
655                                 bind_irq = 1;
656                                 break;
657                                 
658                         case 'x':
659                                 xchange_nids = 1;
660                                 break;
661                                 
662                         default:
663                                 fprintf (stderr, "unrecognised flag '%c'\n",
664                                          *flag);
665                                 return (-1);
666                         }
667
668         memset(&srvaddr, 0, sizeof(srvaddr));
669         srvaddr.sin_family = AF_INET;
670         srvaddr.sin_port = htons(port);
671         srvaddr.sin_addr.s_addr = htonl(ipaddr);
672
673         fd = socket(PF_INET, SOCK_STREAM, 0);
674         if ( fd < 0 ) {
675                 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
676                 return -1;
677         }
678
679         if (g_socket_nonagle)
680         {
681                 o = 1;
682                 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &o, sizeof (o)) != 0) { 
683                         fprintf(stderr, "cannot disable nagle: %s\n", strerror(errno));
684                         return (-1);
685                 }
686         }
687
688         if (g_socket_rxmem != 0) {
689                 o = g_socket_rxmem;
690                 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &o, sizeof (o)) != 0) { 
691                         fprintf(stderr, "cannot set receive buffer size: %s\n", strerror(errno));
692                         return (-1);
693                 }
694         }
695
696         if (g_socket_txmem != 0) {
697                 o = g_socket_txmem;
698                 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &o, sizeof (o)) != 0) { 
699                         fprintf(stderr, "cannot set send buffer size: %s\n", strerror(errno));
700                         return (-1);
701                 }
702         }
703
704         rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
705         if ( rc == -1 ) { 
706                 fprintf(stderr, "connect() failed: %s\n", strerror(errno));
707                 return -1;
708         }
709
710         olen = sizeof (txmem);
711         if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &olen) != 0)
712                 fprintf (stderr, "Can't get send buffer size: %s\n", strerror (errno));
713         olen = sizeof (rxmem);
714         if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &olen) != 0)
715                 fprintf (stderr, "Can't get receive buffer size: %s\n", strerror (errno));
716         olen = sizeof (nonagle);
717         if (getsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nonagle, &olen) != 0)
718                 fprintf (stderr, "Can't get nagle: %s\n", strerror (errno));
719
720         if (!xchange_nids) 
721                 peer_nid = ipaddr;
722         else {
723                 PORTAL_IOC_INIT (data);
724                 data.ioc_nal = g_nal;
725                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
726                 if (rc != 0) {
727                         fprintf (stderr, "failed to get my nid: %s\n",
728                                  strerror (errno));
729                         close (fd);
730                         return (-1);
731                 }
732
733                 rc = exchange_nids (fd, data.ioc_nid, &peer_nid);
734                 if (rc != 0) {
735                         close (fd);
736                         return (-1);
737                 }
738         } 
739         printf("Connected host: %s NID "LPX64" snd: %d rcv: %d nagle: %s\n", argv[1],
740                peer_nid, txmem, rxmem, nonagle ? "Disabled" : "Enabled");
741
742         PORTAL_IOC_INIT(data);
743         data.ioc_fd = fd;
744         data.ioc_nal = g_nal;
745         data.ioc_nal_cmd = NAL_CMD_REGISTER_PEER_FD;
746         data.ioc_nid = peer_nid;
747         data.ioc_flags = bind_irq;
748
749         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
750         if (rc) {
751                 fprintf(stderr, "failed to register fd with portals: %s\n", 
752                         strerror(errno));
753                 close (fd);
754                 return -1;
755         }
756
757         printf("Connection to "LPX64" registered with socknal\n", peer_nid);
758
759         rc = close(fd);
760         if (rc)
761                 fprintf(stderr, "close failed: %d\n", rc);
762
763         return 0;
764 }
765
766 int jt_ptl_disconnect(int argc, char **argv)
767 {
768         struct portal_ioctl_data data;
769         ptl_nid_t                nid = PTL_NID_ANY;
770         __u32                    ipaddr = 0;
771         int                      rc;
772
773         if (argc > 3) {
774                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
775                 return 0;
776         }
777
778         if (!g_nal_is_compatible (argv[0], SOCKNAL, TOENAL, 0))
779                 return -1;
780
781         if (argc >= 2 &&
782             ptl_parse_nid (&nid, argv[1]) != 0) {
783                 fprintf (stderr, "Can't parse nid %s\n", argv[1]);
784                 return -1;
785         }
786
787         if (argc >= 3 &&
788             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
789                 fprintf (stderr, "Can't parse ip addr %s\n", argv[2]);
790                 return -1;
791         }
792
793         PORTAL_IOC_INIT(data);
794         data.ioc_nal     = g_nal;
795         data.ioc_nal_cmd = NAL_CMD_CLOSE_CONNECTION;
796         data.ioc_nid     = nid;
797         data.ioc_id      = ipaddr;
798         
799         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
800         if (rc) {
801                 fprintf(stderr, "failed to remove connection: %s\n",
802                         strerror(errno));
803                 return -1;
804         }
805
806         return 0;
807 }
808
809 int jt_ptl_push_connection (int argc, char **argv)
810 {
811         struct portal_ioctl_data data;
812         int                      rc;
813         ptl_nid_t                nid = PTL_NID_ANY;
814         __u32                    ipaddr = 0;
815
816         if (argc > 3) {
817                 fprintf(stderr, "usage: %s [nid] [ip]\n", argv[0]);
818                 return 0;
819         }
820
821         if (!g_nal_is_compatible (argv[0], SOCKNAL, TOENAL, 0))
822                 return -1;
823         
824         if (argc > 1 &&
825             ptl_parse_nid (&nid, argv[1]) != 0) {
826                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
827                 return -1;
828         }
829                         
830         if (argc > 2 &&
831             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
832                 fprintf(stderr, "Can't parse ipaddr: %s\n", argv[2]);
833         }
834
835         PORTAL_IOC_INIT(data);
836         data.ioc_nal     = g_nal;
837         data.ioc_nal_cmd = NAL_CMD_PUSH_CONNECTION;
838         data.ioc_nid     = nid;
839         data.ioc_id      = ipaddr;
840
841         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
842         if (rc) {
843                 fprintf(stderr, "failed to push connection: %s\n",
844                         strerror(errno));
845                 return -1;
846         }
847
848         return 0;
849 }
850
851 int jt_ptl_ping(int argc, char **argv)
852 {
853         int       rc;
854         ptl_nid_t nid;
855         long      count   = 1;
856         long      size    = 4;
857         long      timeout = 1;
858         struct portal_ioctl_data data;
859
860         if (argc < 2) {
861                 fprintf(stderr, "usage: %s nid [count] [size] [timeout (secs)]\n", argv[0]);
862                 return 0;
863         }
864
865         if (g_nal == 0) {
866                 fprintf(stderr, "Error: you must run the 'network' command "
867                         "first.\n");
868                 return -1;
869         }
870
871         if (ptl_parse_nid (&nid, argv[1]) != 0)
872         {
873                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
874                 return (-1);
875         }
876         
877         if (argc > 2)
878         {
879                 count = atol(argv[2]);
880
881                 if (count < 0 || count > 20000) 
882                 {
883                         fprintf(stderr, "are you insane?  %ld is a crazy count.\n", count);
884                         return -1;
885                 }
886         }
887         
888         if (argc > 3)
889                 size= atol(argv[3]);
890
891         if (argc > 4)
892                 timeout = atol (argv[4]);
893         
894         PORTAL_IOC_INIT (data);
895         data.ioc_count   = count;
896         data.ioc_size    = size;
897         data.ioc_nid     = nid;
898         data.ioc_nal     = g_nal;
899         data.ioc_timeout = timeout;
900         
901         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PING, &data);
902         if (rc) {
903                 fprintf(stderr, "failed to start pinger: %s\n",
904                         strerror(errno));
905                 return -1;
906         }
907         return 0;
908 }
909
910 int jt_ptl_shownid(int argc, char **argv)
911 {
912         struct portal_ioctl_data data;
913         int                      rc;
914         
915         if (argc > 1) {
916                 fprintf(stderr, "usage: %s\n", argv[0]);
917                 return 0;
918         }
919         
920         if (g_nal == 0) {
921                 fprintf(stderr, "Error: you must run the 'network' command first\n");
922                 return -1;
923         }
924         
925         PORTAL_IOC_INIT (data);
926         data.ioc_nal = g_nal;
927         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
928         if (rc < 0)
929                 fprintf(stderr, "getting my NID failed: %s\n",
930                         strerror (errno));
931         else
932                 printf(LPX64"\n", data.ioc_nid);
933         return 0;
934 }
935
936 int jt_ptl_mynid(int argc, char **argv)
937 {
938         int rc;
939         char hostname[1024];
940         char *nidstr;
941         struct portal_ioctl_data data;
942         ptl_nid_t mynid;
943         
944         if (argc > 2) {
945                 fprintf(stderr, "usage: %s [NID]\n", argv[0]);
946                 fprintf(stderr, "NID defaults to the primary IP address of the machine.\n");
947                 return 0;
948         }
949
950         if (g_nal == 0) {
951                 fprintf(stderr, "Error: you must run the 'network' command "
952                         "first.\n");
953                 return -1;
954         }
955
956         if (argc >= 2)
957                 nidstr = argv[1];
958         else if (gethostname(hostname, sizeof(hostname)) != 0) {
959                 fprintf(stderr, "gethostname failed: %s\n",
960                         strerror(errno));
961                 return -1;
962         }
963         else
964                 nidstr = hostname;
965
966         rc = ptl_parse_nid (&mynid, nidstr);
967         if (rc != 0) {
968                 fprintf (stderr, "Can't convert '%s' into a NID\n", nidstr);
969                 return -1;
970         }
971         
972         PORTAL_IOC_INIT(data);
973         data.ioc_nid = mynid;
974         data.ioc_nal = g_nal;
975         data.ioc_nal_cmd = NAL_CMD_REGISTER_MYNID;
976
977         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
978         if (rc < 0)
979                 fprintf(stderr, "setting my NID failed: %s\n",
980                        strerror(errno));
981         else
982                 printf("registered my nid "LPX64" (%s)\n", mynid, hostname);
983         return 0;
984 }
985
986 int
987 jt_ptl_fail_nid (int argc, char **argv)
988 {
989         int                      rc;
990         ptl_nid_t                nid;
991         unsigned int             threshold;
992         struct portal_ioctl_data data;
993
994         if (argc < 2 || argc > 3)
995         {
996                 fprintf (stderr, "usage: %s nid|\"_all_\" [count (0 == mend)]\n", argv[0]);
997                 return (0);
998         }
999         
1000         if (g_nal == 0) {
1001                 fprintf(stderr, "Error: you must run the 'network' command "
1002                         "first.\n");
1003                 return (-1);
1004         }
1005
1006         if (!strcmp (argv[1], "_all_"))
1007                 nid = PTL_NID_ANY;
1008         else if (ptl_parse_nid (&nid, argv[1]) != 0)
1009         {
1010                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1011                 return (-1);
1012         }
1013
1014         if (argc < 3)
1015                 threshold = PTL_MD_THRESH_INF;
1016         else if (sscanf (argv[2], "%i", &threshold) != 1) {
1017                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
1018                 return (-1);
1019         }
1020         
1021         PORTAL_IOC_INIT (data);
1022         data.ioc_nal = g_nal;
1023         data.ioc_nid = nid;
1024         data.ioc_count = threshold;
1025         
1026         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_FAIL_NID, &data);
1027         if (rc < 0)
1028                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
1029                          strerror (errno));
1030         else
1031                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1032         
1033         return (0);
1034 }
1035
1036 int
1037 jt_ptl_rxmem (int argc, char **argv)
1038 {
1039         int   size;
1040         
1041         if (argc > 1)
1042         {
1043                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
1044                 {
1045                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
1046                         return (0);
1047                 }
1048
1049                 g_socket_rxmem = size;
1050         }
1051         printf ("Socket rmem = %d\n", g_socket_rxmem);        
1052         return (0);
1053 }
1054
1055 int
1056 jt_ptl_txmem (int argc, char **argv)
1057 {
1058         int   size;
1059         
1060         if (argc > 1)
1061         {
1062                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
1063                 {
1064                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
1065                         return (0);
1066                 }
1067                 g_socket_txmem = size;
1068         }
1069         printf ("Socket txmem = %d\n", g_socket_txmem);
1070         return (0);
1071 }
1072
1073 int
1074 jt_ptl_nagle (int argc, char **argv)
1075 {
1076         int enable;
1077
1078         if (argc > 1)
1079         {
1080                 if (Parser_bool (&enable, argv[1]) != 0)
1081                 {
1082                         fprintf (stderr, "Can't parse boolean %s\n", argv[1]);
1083                         return (0);
1084                 }
1085                 g_socket_nonagle = !enable;
1086         }
1087         printf ("Nagle %s\n", g_socket_nonagle ? "disabled" : "enabled");
1088         return (0);
1089 }
1090
1091 int
1092 jt_ptl_add_route (int argc, char **argv)
1093 {
1094         struct portal_ioctl_data data;
1095         ptl_nid_t                nid1;
1096         ptl_nid_t                nid2;
1097         ptl_nid_t                gateway_nid;
1098         int                      rc;
1099         
1100         if (argc < 3)
1101         {
1102                 fprintf (stderr, "usage: %s gateway target [target]\n", argv[0]);
1103                 return (0);
1104         }
1105
1106         if (g_nal == 0) {
1107                 fprintf(stderr, "Error: you must run the 'network' command "
1108                         "first.\n");
1109                 return (-1);
1110         }
1111
1112         if (ptl_parse_nid (&gateway_nid, argv[1]) != 0)
1113         {
1114                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1115                 return (-1);
1116         }
1117
1118         if (ptl_parse_nid (&nid1, argv[2]) != 0)
1119         {
1120                 fprintf (stderr, "Can't parse first target NID \"%s\"\n", argv[2]);
1121                 return (-1);
1122         }
1123
1124         if (argc < 4)
1125                 nid2 = nid1;
1126         else if (ptl_parse_nid (&nid2, argv[3]) != 0)
1127         {
1128                 fprintf (stderr, "Can't parse second target NID \"%s\"\n", argv[4]);
1129                 return (-1);
1130         }
1131
1132         PORTAL_IOC_INIT(data);
1133         data.ioc_nid = gateway_nid;
1134         data.ioc_nal = g_nal;
1135         data.ioc_nid2 = MIN (nid1, nid2);
1136         data.ioc_nid3 = MAX (nid1, nid2);
1137
1138         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_ADD_ROUTE, &data);
1139         if (rc != 0) 
1140         {
1141                 fprintf (stderr, "IOC_PORTAL_ADD_ROUTE failed: %s\n", strerror (errno));
1142                 return (-1);
1143         }
1144         
1145         return (0);
1146 }
1147
1148 int
1149 jt_ptl_del_route (int argc, char **argv)
1150 {
1151         struct portal_ioctl_data data;
1152         ptl_nid_t                nid;
1153         int                      rc;
1154         
1155         if (argc < 2)
1156         {
1157                 fprintf (stderr, "usage: %s targetNID\n", argv[0]);
1158                 return (0);
1159         }
1160
1161         if (ptl_parse_nid (&nid, argv[1]) != 0)
1162         {
1163                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1164                 return (-1);
1165         }
1166
1167         PORTAL_IOC_INIT(data);
1168         data.ioc_nid = nid;
1169
1170         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_DEL_ROUTE, &data);
1171         if (rc != 0) 
1172         {
1173                 fprintf (stderr, "IOC_PORTAL_DEL_ROUTE ("LPX64") failed: %s\n", nid, strerror (errno));
1174                 return (-1);
1175         }
1176         
1177         return (0);
1178 }
1179
1180 int
1181 jt_ptl_print_routes (int argc, char **argv)
1182 {
1183         char                      buffer[3][128];
1184         struct portal_ioctl_data  data;
1185         int                       rc;
1186         int                       index;
1187         int                       gateway_nal;
1188         ptl_nid_t                 gateway_nid;
1189         ptl_nid_t                 nid1;
1190         ptl_nid_t                 nid2;
1191         
1192         
1193         for (index = 0;;index++)
1194         {
1195                 PORTAL_IOC_INIT(data);
1196                 data.ioc_count = index;
1197                 
1198                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_ROUTE, &data);
1199                 if (rc != 0)
1200                         break;
1201
1202                 gateway_nal = data.ioc_nal;
1203                 gateway_nid = data.ioc_nid;
1204                 nid1 = data.ioc_nid2;
1205                 nid2 = data.ioc_nid3;
1206                 
1207                 printf ("%8s %18s : %s - %s\n", 
1208                         nal2name (gateway_nal), 
1209                         ptl_nid2str (buffer[0], gateway_nid),
1210                         ptl_nid2str (buffer[1], nid1),
1211                         ptl_nid2str (buffer[2], nid2));
1212         }
1213         return (0);
1214 }
1215