Whamcloud - gitweb
b=1820
[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 
852 jt_ptl_print_active_txs (int argc, char **argv)
853 {
854         struct portal_ioctl_data data;
855         int                      index;
856         int                      rc;
857
858         if (!g_nal_is_compatible (argv[0], QSWNAL, 0))
859                 return -1;
860
861         for (index = 0;;index++) {
862                 PORTAL_IOC_INIT (data);
863                 data.ioc_nal     = g_nal;
864                 data.ioc_nal_cmd = NAL_CMD_GET_TXDESC;
865                 data.ioc_count   = index;
866                 
867                 rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
868                 if (rc != 0)
869                         break;
870
871                 printf ("%p: %5s payload %6d bytes to "LPX64" via "LPX64" by pid %6d: %s,%s,%s\n",
872                         data.ioc_pbuf1,
873                         data.ioc_count == PTL_MSG_ACK ? "ACK" :
874                         data.ioc_count == PTL_MSG_PUT ? "PUT" :
875                         data.ioc_count == PTL_MSG_GET ? "GET" :
876                         data.ioc_count == PTL_MSG_REPLY ? "REPLY" : "<wierd message>",
877                         data.ioc_size,
878                         data.ioc_nid,
879                         data.ioc_nid2,
880                         data.ioc_misc,
881                         (data.ioc_flags & 1) ? "delayed" : "active",
882                         (data.ioc_flags & 2) ? "forwarding" : "sending",
883                         (data.ioc_flags & 4) ? "nblk" : "normal");
884         }
885
886         if (index == 0)
887                 printf ("<no active descs>\n");
888         return 0;
889 }
890
891 int jt_ptl_ping(int argc, char **argv)
892 {
893         int       rc;
894         ptl_nid_t nid;
895         long      count   = 1;
896         long      size    = 4;
897         long      timeout = 1;
898         struct portal_ioctl_data data;
899
900         if (argc < 2) {
901                 fprintf(stderr, "usage: %s nid [count] [size] [timeout (secs)]\n", argv[0]);
902                 return 0;
903         }
904
905         if (g_nal == 0) {
906                 fprintf(stderr, "Error: you must run the 'network' command "
907                         "first.\n");
908                 return -1;
909         }
910
911         if (ptl_parse_nid (&nid, argv[1]) != 0)
912         {
913                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
914                 return (-1);
915         }
916         
917         if (argc > 2)
918         {
919                 count = atol(argv[2]);
920
921                 if (count < 0 || count > 20000) 
922                 {
923                         fprintf(stderr, "are you insane?  %ld is a crazy count.\n", count);
924                         return -1;
925                 }
926         }
927         
928         if (argc > 3)
929                 size= atol(argv[3]);
930
931         if (argc > 4)
932                 timeout = atol (argv[4]);
933         
934         PORTAL_IOC_INIT (data);
935         data.ioc_count   = count;
936         data.ioc_size    = size;
937         data.ioc_nid     = nid;
938         data.ioc_nal     = g_nal;
939         data.ioc_timeout = timeout;
940         
941         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PING, &data);
942         if (rc) {
943                 fprintf(stderr, "failed to start pinger: %s\n",
944                         strerror(errno));
945                 return -1;
946         }
947         return 0;
948 }
949
950 int jt_ptl_shownid(int argc, char **argv)
951 {
952         struct portal_ioctl_data data;
953         int                      rc;
954         
955         if (argc > 1) {
956                 fprintf(stderr, "usage: %s\n", argv[0]);
957                 return 0;
958         }
959         
960         if (g_nal == 0) {
961                 fprintf(stderr, "Error: you must run the 'network' command first\n");
962                 return -1;
963         }
964         
965         PORTAL_IOC_INIT (data);
966         data.ioc_nal = g_nal;
967         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
968         if (rc < 0)
969                 fprintf(stderr, "getting my NID failed: %s\n",
970                         strerror (errno));
971         else
972                 printf(LPX64"\n", data.ioc_nid);
973         return 0;
974 }
975
976 int jt_ptl_mynid(int argc, char **argv)
977 {
978         int rc;
979         char hostname[1024];
980         char *nidstr;
981         struct portal_ioctl_data data;
982         ptl_nid_t mynid;
983         
984         if (argc > 2) {
985                 fprintf(stderr, "usage: %s [NID]\n", argv[0]);
986                 fprintf(stderr, "NID defaults to the primary IP address of the machine.\n");
987                 return 0;
988         }
989
990         if (g_nal == 0) {
991                 fprintf(stderr, "Error: you must run the 'network' command "
992                         "first.\n");
993                 return -1;
994         }
995
996         if (argc >= 2)
997                 nidstr = argv[1];
998         else if (gethostname(hostname, sizeof(hostname)) != 0) {
999                 fprintf(stderr, "gethostname failed: %s\n",
1000                         strerror(errno));
1001                 return -1;
1002         }
1003         else
1004                 nidstr = hostname;
1005
1006         rc = ptl_parse_nid (&mynid, nidstr);
1007         if (rc != 0) {
1008                 fprintf (stderr, "Can't convert '%s' into a NID\n", nidstr);
1009                 return -1;
1010         }
1011         
1012         PORTAL_IOC_INIT(data);
1013         data.ioc_nid = mynid;
1014         data.ioc_nal = g_nal;
1015         data.ioc_nal_cmd = NAL_CMD_REGISTER_MYNID;
1016
1017         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
1018         if (rc < 0)
1019                 fprintf(stderr, "setting my NID failed: %s\n",
1020                        strerror(errno));
1021         else
1022                 printf("registered my nid "LPX64" (%s)\n", mynid, hostname);
1023         return 0;
1024 }
1025
1026 int
1027 jt_ptl_fail_nid (int argc, char **argv)
1028 {
1029         int                      rc;
1030         ptl_nid_t                nid;
1031         unsigned int             threshold;
1032         struct portal_ioctl_data data;
1033
1034         if (argc < 2 || argc > 3)
1035         {
1036                 fprintf (stderr, "usage: %s nid|\"_all_\" [count (0 == mend)]\n", argv[0]);
1037                 return (0);
1038         }
1039         
1040         if (g_nal == 0) {
1041                 fprintf(stderr, "Error: you must run the 'network' command "
1042                         "first.\n");
1043                 return (-1);
1044         }
1045
1046         if (!strcmp (argv[1], "_all_"))
1047                 nid = PTL_NID_ANY;
1048         else if (ptl_parse_nid (&nid, argv[1]) != 0)
1049         {
1050                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1051                 return (-1);
1052         }
1053
1054         if (argc < 3)
1055                 threshold = PTL_MD_THRESH_INF;
1056         else if (sscanf (argv[2], "%i", &threshold) != 1) {
1057                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
1058                 return (-1);
1059         }
1060         
1061         PORTAL_IOC_INIT (data);
1062         data.ioc_nal = g_nal;
1063         data.ioc_nid = nid;
1064         data.ioc_count = threshold;
1065         
1066         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_FAIL_NID, &data);
1067         if (rc < 0)
1068                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
1069                          strerror (errno));
1070         else
1071                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1072         
1073         return (0);
1074 }
1075
1076 int
1077 jt_ptl_rxmem (int argc, char **argv)
1078 {
1079         int   size;
1080         
1081         if (argc > 1)
1082         {
1083                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
1084                 {
1085                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
1086                         return (0);
1087                 }
1088
1089                 g_socket_rxmem = size;
1090         }
1091         printf ("Socket rmem = %d\n", g_socket_rxmem);        
1092         return (0);
1093 }
1094
1095 int
1096 jt_ptl_txmem (int argc, char **argv)
1097 {
1098         int   size;
1099         
1100         if (argc > 1)
1101         {
1102                 if (Parser_size (&size, argv[1]) != 0 || size < 0)
1103                 {
1104                         fprintf (stderr, "Can't parse size %s\n", argv[1]);
1105                         return (0);
1106                 }
1107                 g_socket_txmem = size;
1108         }
1109         printf ("Socket txmem = %d\n", g_socket_txmem);
1110         return (0);
1111 }
1112
1113 int
1114 jt_ptl_nagle (int argc, char **argv)
1115 {
1116         int enable;
1117
1118         if (argc > 1)
1119         {
1120                 if (Parser_bool (&enable, argv[1]) != 0)
1121                 {
1122                         fprintf (stderr, "Can't parse boolean %s\n", argv[1]);
1123                         return (0);
1124                 }
1125                 g_socket_nonagle = !enable;
1126         }
1127         printf ("Nagle %s\n", g_socket_nonagle ? "disabled" : "enabled");
1128         return (0);
1129 }
1130
1131 int
1132 jt_ptl_add_route (int argc, char **argv)
1133 {
1134         struct portal_ioctl_data data;
1135         ptl_nid_t                nid1;
1136         ptl_nid_t                nid2;
1137         ptl_nid_t                gateway_nid;
1138         int                      rc;
1139         
1140         if (argc < 3)
1141         {
1142                 fprintf (stderr, "usage: %s gateway target [target]\n", argv[0]);
1143                 return (0);
1144         }
1145
1146         if (g_nal == 0) {
1147                 fprintf(stderr, "Error: you must run the 'network' command "
1148                         "first.\n");
1149                 return (-1);
1150         }
1151
1152         if (ptl_parse_nid (&gateway_nid, argv[1]) != 0)
1153         {
1154                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1155                 return (-1);
1156         }
1157
1158         if (ptl_parse_nid (&nid1, argv[2]) != 0)
1159         {
1160                 fprintf (stderr, "Can't parse first target NID \"%s\"\n", argv[2]);
1161                 return (-1);
1162         }
1163
1164         if (argc < 4)
1165                 nid2 = nid1;
1166         else if (ptl_parse_nid (&nid2, argv[3]) != 0)
1167         {
1168                 fprintf (stderr, "Can't parse second target NID \"%s\"\n", argv[4]);
1169                 return (-1);
1170         }
1171
1172         PORTAL_IOC_INIT(data);
1173         data.ioc_nid = gateway_nid;
1174         data.ioc_nal = g_nal;
1175         data.ioc_nid2 = MIN (nid1, nid2);
1176         data.ioc_nid3 = MAX (nid1, nid2);
1177
1178         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_ADD_ROUTE, &data);
1179         if (rc != 0) 
1180         {
1181                 fprintf (stderr, "IOC_PORTAL_ADD_ROUTE failed: %s\n", strerror (errno));
1182                 return (-1);
1183         }
1184         
1185         return (0);
1186 }
1187
1188 int
1189 jt_ptl_del_route (int argc, char **argv)
1190 {
1191         struct portal_ioctl_data data;
1192         ptl_nid_t                nid;
1193         int                      rc;
1194         
1195         if (argc < 2)
1196         {
1197                 fprintf (stderr, "usage: %s targetNID\n", argv[0]);
1198                 return (0);
1199         }
1200
1201         if (ptl_parse_nid (&nid, argv[1]) != 0)
1202         {
1203                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1204                 return (-1);
1205         }
1206
1207         PORTAL_IOC_INIT(data);
1208         data.ioc_nid = nid;
1209
1210         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_DEL_ROUTE, &data);
1211         if (rc != 0) 
1212         {
1213                 fprintf (stderr, "IOC_PORTAL_DEL_ROUTE ("LPX64") failed: %s\n", nid, strerror (errno));
1214                 return (-1);
1215         }
1216         
1217         return (0);
1218 }
1219
1220 int
1221 jt_ptl_print_routes (int argc, char **argv)
1222 {
1223         char                      buffer[3][128];
1224         struct portal_ioctl_data  data;
1225         int                       rc;
1226         int                       index;
1227         int                       gateway_nal;
1228         ptl_nid_t                 gateway_nid;
1229         ptl_nid_t                 nid1;
1230         ptl_nid_t                 nid2;
1231         
1232         
1233         for (index = 0;;index++)
1234         {
1235                 PORTAL_IOC_INIT(data);
1236                 data.ioc_count = index;
1237                 
1238                 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_ROUTE, &data);
1239                 if (rc != 0)
1240                         break;
1241
1242                 gateway_nal = data.ioc_nal;
1243                 gateway_nid = data.ioc_nid;
1244                 nid1 = data.ioc_nid2;
1245                 nid2 = data.ioc_nid3;
1246                 
1247                 printf ("%8s %18s : %s - %s\n", 
1248                         nal2name (gateway_nal), 
1249                         ptl_nid2str (buffer[0], gateway_nid),
1250                         ptl_nid2str (buffer[1], nid1),
1251                         ptl_nid2str (buffer[2], nid2));
1252         }
1253         return (0);
1254 }
1255