Whamcloud - gitweb
Branch: b_cray
[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 #ifdef HAVE_NETDB_H
26 #include <netdb.h>
27 #endif
28 #include <sys/socket.h>
29 #ifdef HAVE_NETINET_TCP_H
30 #include <netinet/tcp.h>
31 #endif
32 #include <stdlib.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <time.h>
39 #include <stdarg.h>
40 #ifdef HAVE_ENDIAN_H
41 #include <endian.h>
42 #endif
43 #if CRAY_PORTALS
44 #ifdef REDSTORM
45 #define __QK__
46 #endif
47 #include <portals/ipmap.h>
48 #endif
49
50 #include <libcfs/portals_utils.h>
51 #include <portals/api-support.h>
52 #include <portals/ptlctl.h>
53 #include <portals/lib-types.h>
54 #include <portals/socknal.h>
55 #include "parser.h"
56
57 unsigned int portal_debug;
58 unsigned int portal_printk;
59
60 static unsigned int g_nal = 0;
61
62 typedef struct
63 {
64         char *name;
65         int   num;
66 } name2num_t;
67
68 static name2num_t nalnames[] = {
69         {"any",         0},
70 #if !CRAY_PORTALS
71         {"tcp",         SOCKNAL},
72         {"elan",        QSWNAL},
73         {"gm",          GMNAL},
74         {"openib",      OPENIBNAL},
75         {"iib",         IIBNAL},
76         {"vib",         VIBNAL},
77         {"lo",          LONAL},
78         {"ra",          RANAL},
79 #else
80         {"cray_kern_nal", CRAY_KERN_NAL},
81         {"cray_user_nal", CRAY_USER_NAL},
82         {"cray_qk_nal",   CRAY_QK_NAL},
83 #endif
84         {NULL,          -1}
85 };
86
87 static cfg_record_cb_t g_record_cb;
88
89 /* Convert a string boolean to an int; "enable" -> 1 */
90 int ptl_parse_bool (int *b, char *str) {
91         if (!strcasecmp (str, "no") ||
92             !strcasecmp (str, "n") ||
93             !strcasecmp (str, "off") ||
94             !strcasecmp (str, "down") ||
95             !strcasecmp (str, "disable"))
96         {
97                 *b = 0;
98                 return (0);
99         }
100         
101         if (!strcasecmp (str, "yes") ||
102             !strcasecmp (str, "y") ||
103             !strcasecmp (str, "on") ||
104             !strcasecmp (str, "up") ||
105             !strcasecmp (str, "enable"))
106         {
107                 *b = 1;
108                 return (0);
109         }
110         
111         return (-1);
112 }
113
114 /* Convert human readable size string to and int; "1k" -> 1000 */
115 int ptl_parse_size (int *sizep, char *str) {
116         int size;
117         char mod[32];
118
119         switch (sscanf (str, "%d%1[gGmMkK]", &size, mod)) {
120         default:
121                 return (-1);
122
123         case 1:
124                 *sizep = size;
125                 return (0);
126
127         case 2:
128                 switch (*mod) {
129                 case 'g':
130                 case 'G':
131                         *sizep = size << 30;
132                         return (0);
133
134                 case 'm':
135                 case 'M':
136                         *sizep = size << 20;
137                         return (0);
138
139                 case 'k':
140                 case 'K':
141                         *sizep = size << 10;
142                         return (0);
143
144                 default:
145                         *sizep = size;
146                         return (0);
147                 }
148         }
149 }
150
151 int 
152 ptl_set_cfg_record_cb(cfg_record_cb_t cb)
153 {
154         g_record_cb = cb;
155         return 0;
156 }
157
158 int 
159 pcfg_ioctl(struct portals_cfg *pcfg) 
160 {
161         int rc;
162
163         if (pcfg->pcfg_nal ==0)
164                 pcfg->pcfg_nal    = g_nal;
165
166         if (g_record_cb) {
167                 rc = g_record_cb(PORTALS_CFG_TYPE, sizeof(*pcfg), pcfg);
168         } else {
169                 struct portal_ioctl_data data;
170                 PORTAL_IOC_INIT (data);
171                 data.ioc_pbuf1   = (char*)pcfg;
172                 data.ioc_plen1   = sizeof(*pcfg);
173                 /* XXX liblustre hack XXX */
174                 data.ioc_nal_cmd = pcfg->pcfg_command;
175                 data.ioc_nid = pcfg->pcfg_nid;
176
177                 rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
178         }
179
180         return (rc);
181 }
182
183
184
185 static name2num_t *
186 name2num_lookup_name (name2num_t *table, char *str)
187 {
188         while (table->name != NULL)
189                 if (!strcmp (str, table->name))
190                         return (table);
191                 else
192                         table++;
193         return (NULL);
194 }
195
196 static name2num_t *
197 name2num_lookup_num (name2num_t *table, int num)
198 {
199         while (table->name != NULL)
200                 if (num == table->num)
201                         return (table);
202                 else
203                         table++;
204         return (NULL);
205 }
206
207 int
208 ptl_name2nal (char *str)
209 {
210         name2num_t *e = name2num_lookup_name (nalnames, str);
211
212         return ((e == NULL) ? -1 : e->num);
213 }
214
215 static char *
216 nal2name (int nal)
217 {
218         name2num_t *e = name2num_lookup_num (nalnames, nal);
219
220         return ((e == NULL) ? "???" : e->name);
221 }
222
223 #ifdef HAVE_GETHOSTBYNAME
224 static struct hostent *
225 ptl_gethostbyname(char * hname) {
226         struct hostent *he;
227         he = gethostbyname(hname);
228         if (!he) {
229                 switch(h_errno) {
230                 case HOST_NOT_FOUND:
231                 case NO_ADDRESS:
232                         fprintf(stderr, "Unable to resolve hostname: %s\n",
233                                 hname);
234                         break;
235                 default:
236                         fprintf(stderr, "gethostbyname error for %s: %s\n",
237                                 hname, strerror(h_errno));
238                         break;
239                 }
240                 return NULL;
241         }
242         return he;
243 }
244 #endif
245
246 int
247 ptl_parse_port (int *port, char *str)
248 {
249         char      *end;
250         
251         *port = strtol (str, &end, 0);
252
253         if (*end == 0 &&                        /* parsed whole string */
254             *port > 0 && *port < 65536)         /* minimal sanity check */
255                 return (0);
256         
257         return (-1);
258 }
259
260 int
261 ptl_parse_time (time_t *t, char *str) 
262 {
263         char          *end;
264         int            n;
265         struct tm      tm;
266         
267         *t = strtol (str, &end, 0);
268         if (*end == 0) /* parsed whole string */
269                 return (0);
270         
271         memset (&tm, 0, sizeof (tm));
272         n = sscanf (str, "%d-%d-%d-%d:%d:%d",
273                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
274                     &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
275         if (n != 6)
276                 return (-1);
277         
278         tm.tm_mon--;                    /* convert to 0 == Jan */
279         tm.tm_year -= 1900;             /* y2k quirk */
280         tm.tm_isdst = -1;               /* dunno if it's daylight savings... */
281         
282         *t = mktime (&tm);
283         if (*t == (time_t)-1)
284                 return (-1);
285                         
286         return (0);
287 }
288
289 int
290 ptl_parse_ipquad (__u32 *ipaddrp, char *str)
291 {
292         int             a;
293         int             b;
294         int             c;
295         int             d;
296
297         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
298             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
299             (c & ~0xff) == 0 && (d & ~0xff) == 0)
300         {
301                 *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
302                 return (0);
303         }
304
305         return (-1);
306 }
307
308 int
309 ptl_parse_ipaddr (__u32 *ipaddrp, char *str)
310 {
311 #ifdef HAVE_GETHOSTBYNAME
312         struct hostent *he;
313 #endif
314
315         if (!strcmp (str, "_all_")) {
316                 *ipaddrp = 0;
317                 return (0);
318         }
319
320         if (ptl_parse_ipquad(ipaddrp, str) == 0)
321                 return (0);
322
323 #ifdef HAVE_GETHOSTBYNAME
324         if ((('a' <= str[0] && str[0] <= 'z') ||
325              ('A' <= str[0] && str[0] <= 'Z')) &&
326              (he = ptl_gethostbyname (str)) != NULL) {
327                 __u32 addr = *(__u32 *)he->h_addr;
328
329                 *ipaddrp = ntohl(addr);         /* HOST byte order */
330                 return (0);
331         }
332 #endif
333
334         return (-1);
335 }
336
337 char *
338 ptl_ipaddr_2_str (__u32 ipaddr, char *str, int lookup)
339 {
340 #ifdef HAVE_GETHOSTBYNAME
341         __u32           net_ip;
342         struct hostent *he;
343
344         if (lookup) {
345                 net_ip = htonl (ipaddr);
346                 he = gethostbyaddr (&net_ip, sizeof (net_ip), AF_INET);
347                 if (he != NULL) {
348                         strcpy(str, he->h_name);
349                         return (str);
350                 }
351         }
352 #endif
353
354         sprintf (str, "%d.%d.%d.%d",
355                  (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
356                  (ipaddr >> 8) & 0xff, ipaddr & 0xff);
357         return (str);
358 }
359
360 int
361 ptl_parse_nid (ptl_nid_t *nidp, char *str)
362 {
363         __u32               ipaddr;
364         char               *end;
365         unsigned long long  ullval;
366         
367         if (ptl_parse_ipaddr (&ipaddr, str) == 0) {
368 #if !CRAY_PORTALS
369                 *nidp = (ptl_nid_t)ipaddr;
370 #else
371                 *nidp = (((ptl_nid_t)ipaddr & PNAL_HOSTID_MASK) << PNAL_VNODE_SHIFT);
372 #endif
373                 return (0);
374         }
375
376         ullval = strtoull(str, &end, 0);
377         if (end != str && *end == 0) {
378                 /* parsed whole non-empty string */
379                 *nidp = (ptl_nid_t)ullval;
380                 return (0);
381         }
382
383         return (-1);
384 }
385
386 int
387 ptl_parse_anynid (ptl_nid_t *nidp, char *str)
388 {
389         if (!strcmp (str, "_all_")) {
390                 *nidp = PTL_NID_ANY;
391                 return 0;
392         }
393
394         return ptl_parse_nid(nidp, str);
395 }
396
397 __u64 ptl_nid2u64(ptl_nid_t nid)
398 {
399         switch (sizeof (nid)) {
400         case 8:
401                 return (nid);
402         case 4:
403                 return ((__u32)nid);
404         default:
405                 fprintf(stderr, "Unexpected sizeof(ptl_nid_t) == %u\n", sizeof(nid));
406                 abort();
407                 /* notreached */
408                 return (-1);
409         }
410 }
411
412 char *
413 ptl_nid2str (char *buffer, ptl_nid_t nid)
414 {
415         __u64           nid64 = ptl_nid2u64(nid);
416 #ifdef HAVE_GETHOSTBYNAME
417         struct hostent *he = 0;
418
419         /* Don't try to resolve NIDs that are e.g. Elan host IDs.  Assume
420          * TCP addresses in the 0.x.x.x subnet are not in use.  This can
421          * happen on routers and slows things down a _lot_.  Bug 3442. */
422         if (nid & 0xff000000) {
423                 __u32 addr = htonl((__u32)nid); /* back to NETWORK byte order */
424
425                 he = gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET);
426         }
427
428         if (he != NULL)
429                 sprintf(buffer, "%#x:%s", (int)(nid64 >> 32), he->h_name);
430         else
431 #endif /* HAVE_GETHOSTBYNAME */
432                 sprintf(buffer, LPX64, nid64);
433
434         return (buffer);
435 }
436
437 int g_nal_is_set () 
438 {
439         if (g_nal == 0) {
440                 fprintf (stderr, "Error: you must run the 'network' command first.\n");
441                 return (0);
442         }
443
444         return (1);
445 }
446
447 int g_nal_is_compatible (char *cmd, ...)
448 {
449         va_list       ap;
450         int           nal;
451
452         if (!g_nal_is_set ())
453                 return (0);
454
455         va_start (ap, cmd);
456
457         do {
458                 nal = va_arg (ap, int);
459         } while (nal != 0 && nal != g_nal);
460         
461         va_end (ap);
462         
463         if (g_nal == nal)
464                 return (1);
465
466         if (cmd != NULL) {
467                 /* Don't complain verbosely if we've not been passed a command
468                  * name to complain about! */
469                 fprintf (stderr, "Command %s not compatible with nal %s\n",
470                          cmd, nal2name (g_nal));
471         }
472         return (0);
473 }
474
475 int
476 sock_write (int cfd, void *buffer, int nob)
477 {
478         while (nob > 0)
479         {
480                 int rc = write (cfd, buffer, nob);
481
482                 if (rc < 0)
483                 {
484                         if (errno == EINTR)
485                                 continue;
486                         
487                         return (rc);
488                 }
489
490                 if (rc == 0)
491                 {
492                         fprintf (stderr, "Unexpected zero sock_write\n");
493                         abort();
494                 }
495
496                 nob -= rc;
497                 buffer = (char *)buffer + nob;
498         }
499         
500         return (0);
501 }
502
503 int
504 sock_read (int cfd, void *buffer, int nob)
505 {
506         while (nob > 0)
507         {
508                 int rc = read (cfd, buffer, nob);
509                 
510                 if (rc < 0)
511                 {
512                         if (errno == EINTR)
513                                 continue;
514                         
515                         return (rc);
516                 }
517                 
518                 if (rc == 0)                    /* EOF */
519                 {
520                         errno = ECONNABORTED;
521                         return (-1);
522                 }
523                 
524                 nob -= rc;
525                 buffer = (char *)buffer + nob;
526         }
527         
528         return (0);
529 }
530
531 int ptl_initialize(int argc, char **argv) 
532 {
533         register_ioc_dev(PORTALS_DEV_ID, PORTALS_DEV_PATH);
534         return 0;
535 }
536
537
538 int jt_ptl_network(int argc, char **argv)
539 {
540         name2num_t *entry;
541         int         nal;
542         
543         if (argc == 2 &&
544             (nal = ptl_name2nal (argv[1])) >= 0) {
545                 g_nal = nal;
546                 return (0);
547         }
548                 
549         fprintf(stderr, "usage: %s \n", argv[0]);
550         for (entry = nalnames; entry->name != NULL; entry++)
551                 fprintf (stderr, "%s%s", entry == nalnames ? "<" : "|", entry->name);
552         fprintf(stderr, ">\n");
553         return (-1);
554 }
555
556 int
557 jt_ptl_print_interfaces (int argc, char **argv)
558 {
559         struct portals_cfg       pcfg;
560         char                     buffer[3][64];
561         int                      index;
562         int                      rc;
563
564         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
565                 return -1;
566
567         for (index = 0;;index++) {
568                 PCFG_INIT (pcfg, NAL_CMD_GET_INTERFACE);
569                 pcfg.pcfg_count = index;
570
571                 rc = pcfg_ioctl (&pcfg);
572                 if (rc != 0)
573                         break;
574
575                 printf ("%s: (%s/%s) npeer %d nroute %d\n",
576                         ptl_ipaddr_2_str(pcfg.pcfg_id, buffer[2], 1),
577                         ptl_ipaddr_2_str(pcfg.pcfg_id, buffer[0], 0),
578                         ptl_ipaddr_2_str(pcfg.pcfg_misc, buffer[1], 0),
579                         pcfg.pcfg_fd, pcfg.pcfg_count);
580         }
581
582         if (index == 0)
583                 printf ("<no interfaces>\n");
584         return 0;
585 }
586
587 int
588 jt_ptl_add_interface (int argc, char **argv)
589 {
590         struct portals_cfg       pcfg;
591         __u32                    ipaddr;
592         int                      rc;
593         __u32                    netmask = 0xffffff00;
594         int                      i;
595         int                      count;
596         char                    *end;
597
598         if (argc < 2 || argc > 3) {
599                 fprintf (stderr, "usage: %s ipaddr [netmask]\n", argv[0]);
600                 return 0;
601         }
602
603         if (!g_nal_is_compatible(argv[0], SOCKNAL, 0))
604                 return -1;
605
606         if (ptl_parse_ipaddr(&ipaddr, argv[1]) != 0) {
607                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
608                 return -1;
609         }
610
611         if (argc > 2 ) {
612                 count = strtol(argv[2], &end, 0);
613                 if (count > 0 && count < 32 && *end == 0) {
614                         netmask = 0;
615                         for (i = count; i > 0; i--)
616                                 netmask = netmask|(1<<(32-i));
617                 } else if (ptl_parse_ipquad(&netmask, argv[2]) != 0) {
618                         fprintf (stderr, "Can't parse netmask: %s\n", argv[2]);
619                         return -1;
620                 }
621         }
622
623         PCFG_INIT(pcfg, NAL_CMD_ADD_INTERFACE);
624         pcfg.pcfg_id     = ipaddr;
625         pcfg.pcfg_misc   = netmask;
626
627         rc = pcfg_ioctl (&pcfg);
628         if (rc != 0) {
629                 fprintf (stderr, "failed to add interface: %s\n",
630                          strerror (errno));
631                 return -1;
632         }
633
634         return 0;
635 }
636
637 int
638 jt_ptl_del_interface (int argc, char **argv)
639 {
640         struct portals_cfg       pcfg;
641         int                      rc;
642         __u32                    ipaddr = 0;
643
644         if (argc > 2) {
645                 fprintf (stderr, "usage: %s [ipaddr]\n", argv[0]);
646                 return 0;
647         }
648
649         if (!g_nal_is_compatible(argv[0], SOCKNAL, 0))
650                 return -1;
651
652         if (argc == 2 &&
653             ptl_parse_ipaddr(&ipaddr, argv[1]) != 0) {
654                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
655                 return -1;
656         }
657         
658         PCFG_INIT(pcfg, NAL_CMD_DEL_INTERFACE);
659         pcfg.pcfg_id = ipaddr;
660
661         rc = pcfg_ioctl (&pcfg);
662         if (rc != 0) {
663                 fprintf (stderr, "failed to delete interface: %s\n",
664                          strerror (errno));
665                 return -1;
666         }
667
668         return 0;
669 }
670
671 int
672 jt_ptl_print_peers (int argc, char **argv)
673 {
674         struct portals_cfg       pcfg;
675         char                     buffer[2][64];
676         int                      index;
677         int                      rc;
678
679         if (!g_nal_is_compatible (argv[0], SOCKNAL, RANAL, 
680                                   OPENIBNAL, IIBNAL, VIBNAL, 0))
681                 return -1;
682
683         for (index = 0;;index++) {
684                 PCFG_INIT (pcfg, NAL_CMD_GET_PEER);
685                 pcfg.pcfg_count   = index;
686
687                 rc = pcfg_ioctl (&pcfg);
688                 if (rc != 0)
689                         break;
690
691                 if (g_nal_is_compatible(NULL, SOCKNAL, 0))
692                         printf (LPX64"[%d]%s@%s:%d #%d\n",
693                                 pcfg.pcfg_nid, pcfg.pcfg_wait,
694                                 ptl_ipaddr_2_str (pcfg.pcfg_size, buffer[0], 1),
695                                 ptl_ipaddr_2_str (pcfg.pcfg_id, buffer[1], 1),
696                                 pcfg.pcfg_misc, pcfg.pcfg_count);
697                 else if (g_nal_is_compatible(NULL, RANAL, OPENIBNAL, VIBNAL, 0))
698                         printf (LPX64"[%d]@%s:%d\n",
699                                 pcfg.pcfg_nid, pcfg.pcfg_wait,
700                                 ptl_ipaddr_2_str (pcfg.pcfg_id, buffer[1], 1),
701                                 pcfg.pcfg_misc);
702                 else
703                         printf (LPX64"[%d]\n",
704                                 pcfg.pcfg_nid, pcfg.pcfg_wait);
705         }
706
707         if (index == 0)
708                 printf ("<no peers>\n");
709         return 0;
710 }
711
712 int 
713 jt_ptl_add_peer (int argc, char **argv)
714 {
715         struct portals_cfg       pcfg;
716         ptl_nid_t                nid;
717         __u32                    ip = 0;
718         int                      port = 0;
719         int                      rc;
720
721         if (!g_nal_is_compatible (argv[0], SOCKNAL, RANAL, 
722                                   OPENIBNAL, IIBNAL, VIBNAL, 0))
723                 return -1;
724
725         if (g_nal_is_compatible(NULL, SOCKNAL, OPENIBNAL, RANAL, 0)) {
726                 if (argc != 4) {
727                         fprintf (stderr, "usage(tcp,openib,ra): %s nid ipaddr port\n", 
728                                  argv[0]);
729                         return 0;
730                 }
731         } else if (g_nal_is_compatible(NULL, VIBNAL, 0)) {
732                 if (argc != 3) {
733                         fprintf (stderr, "usage(vib): %s nid ipaddr\n", 
734                                  argv[0]);
735                         return 0;
736                 }
737         } else if (argc != 2) {
738                 fprintf (stderr, "usage(iib): %s nid\n", argv[0]);
739                 return 0;
740         }
741
742         if (ptl_parse_nid (&nid, argv[1]) != 0 ||
743                 nid == PTL_NID_ANY) {
744                 fprintf (stderr, "Can't parse NID: %s\n", argv[1]);
745                 return -1;
746         }
747
748         if (g_nal_is_compatible (NULL, SOCKNAL, OPENIBNAL, VIBNAL, RANAL, 0) &&
749             ptl_parse_ipaddr (&ip, argv[2]) != 0) {
750                 fprintf (stderr, "Can't parse ip addr: %s\n", argv[2]);
751                 return -1;
752         }
753
754         if (g_nal_is_compatible (NULL, SOCKNAL, OPENIBNAL, RANAL, 0) &&
755             ptl_parse_port (&port, argv[3]) != 0) {
756                 fprintf (stderr, "Can't parse port: %s\n", argv[3]);
757                 return -1;
758         }
759
760         PCFG_INIT(pcfg, NAL_CMD_ADD_PEER);
761         pcfg.pcfg_nid     = nid;
762         pcfg.pcfg_id      = ip;
763         pcfg.pcfg_misc    = port;
764
765         rc = pcfg_ioctl (&pcfg);
766         if (rc != 0) {
767                 fprintf (stderr, "failed to add peer: %s\n",
768                          strerror (errno));
769                 return -1;
770         }
771         
772         return 0;
773 }
774
775 int 
776 jt_ptl_del_peer (int argc, char **argv)
777 {
778         struct portals_cfg       pcfg;
779         ptl_nid_t                nid = PTL_NID_ANY;
780         __u32                    ip = 0;
781         int                      single_share = 0;
782         int                      argidx;
783         int                      rc;
784
785         if (!g_nal_is_compatible (argv[0], SOCKNAL, RANAL, 
786                                   OPENIBNAL, IIBNAL, VIBNAL, 0))
787                 return -1;
788
789         if (g_nal_is_compatible(NULL, SOCKNAL, 0)) {
790                 if (argc > 4) {
791                         fprintf (stderr, "usage: %s [nid] [ipaddr] [single_share]\n",
792                                  argv[0]);
793                         return 0;
794                 }
795         } else if (argc > 3) {
796                 fprintf (stderr, "usage: %s [nid] [single_share]\n", argv[0]);
797                 return 0;
798         }
799                 
800         if (argc > 1 &&
801             ptl_parse_anynid (&nid, argv[1]) != 0) {
802                 fprintf (stderr, "Can't parse nid: %s\n", argv[1]);
803                 return -1;
804         }
805
806         argidx = 2;
807         if (g_nal_is_compatible(NULL, SOCKNAL, 0)) {
808                 if (argc > argidx &&
809                     ptl_parse_ipaddr (&ip, argv[argidx]) != 0) {
810                         fprintf (stderr, "Can't parse ip addr: %s\n",
811                                  argv[argidx]);
812                         return -1;
813                 }
814                 argidx++;
815         }
816         
817         if (argc > argidx) {
818                 if (!strcmp (argv[argidx], "single_share")) {
819                         single_share = 1;
820                 } else {
821                         fprintf (stderr, "Unrecognised arg %s'\n", argv[3]);
822                         return -1;
823                 }
824         }
825
826         PCFG_INIT(pcfg, NAL_CMD_DEL_PEER);
827         pcfg.pcfg_nid = nid;
828         pcfg.pcfg_id = ip;
829         pcfg.pcfg_flags = single_share;
830
831         rc = pcfg_ioctl (&pcfg);
832         if (rc != 0) {
833                 fprintf (stderr, "failed to remove peer: %s\n",
834                          strerror (errno));
835                 return -1;
836         }
837         
838         return 0;
839 }
840
841 int 
842 jt_ptl_print_connections (int argc, char **argv)
843 {
844         struct portals_cfg       pcfg;
845         char                     buffer[2][64];
846         int                      index;
847         int                      rc;
848
849         if (!g_nal_is_compatible (argv[0], SOCKNAL, RANAL, 
850                                   OPENIBNAL, IIBNAL, VIBNAL, 0))
851                 return -1;
852
853         for (index = 0;;index++) {
854                 PCFG_INIT (pcfg,  NAL_CMD_GET_CONN);
855                 pcfg.pcfg_count   = index;
856                 
857                 rc = pcfg_ioctl (&pcfg);
858                 if (rc != 0)
859                         break;
860
861                 if (g_nal_is_compatible (NULL, SOCKNAL, 0))
862                         printf ("[%d]%s:"LPX64"@%s:%d:%s %d/%d %s\n",
863                                 pcfg.pcfg_gw_nal,       /* scheduler */
864                                 ptl_ipaddr_2_str (pcfg.pcfg_fd, buffer[0], 1), /* local IP addr */
865                                 pcfg.pcfg_nid, 
866                                 ptl_ipaddr_2_str (pcfg.pcfg_id, buffer[1], 1), /* remote IP addr */
867                                 pcfg.pcfg_misc,         /* remote port */
868                                 (pcfg.pcfg_flags == SOCKNAL_CONN_ANY) ? "A" :
869                                 (pcfg.pcfg_flags == SOCKNAL_CONN_CONTROL) ? "C" :
870                                 (pcfg.pcfg_flags == SOCKNAL_CONN_BULK_IN) ? "I" :
871                                 (pcfg.pcfg_flags == SOCKNAL_CONN_BULK_OUT) ? "O" : "?",
872                                 pcfg.pcfg_count,        /* tx buffer size */
873                                 pcfg.pcfg_size,         /* rx buffer size */
874                                 pcfg.pcfg_wait ? "nagle" : "nonagle");
875                 else if (g_nal_is_compatible (NULL, RANAL, 0))
876                         printf ("[%d]"LPX64"\n",
877                                 pcfg.pcfg_id,       /* device id */
878                                 pcfg.pcfg_nid);
879                 else
880                         printf (LPX64"\n",
881                                 pcfg.pcfg_nid);
882         }
883
884         if (index == 0)
885                 printf ("<no connections>\n");
886         return 0;
887 }
888
889 int jt_ptl_connect(int argc, char **argv)
890 {
891 #ifndef HAVE_CONNECT
892         /* no connect() support */
893         return -1;
894 #else /* HAVE_CONNECT */
895         struct portals_cfg pcfg;
896         struct sockaddr_in srvaddr;
897         struct sockaddr_in locaddr;
898         __u32 ipaddr;
899         char *flag;
900         int fd, rc;
901         int type = SOCKNAL_CONN_ANY;
902         int port, rport;
903         int o;
904
905         if (argc < 3) {
906                 fprintf(stderr, "usage: %s ip port [type]\n", argv[0]);
907                 return 0;
908         }
909
910         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
911                 return -1;
912         
913         rc = ptl_parse_ipaddr (&ipaddr, argv[1]);
914         if (rc != 0) {
915                 fprintf(stderr, "Can't parse hostname: %s\n", argv[1]);
916                 return -1;
917         }
918
919         if (ptl_parse_port (&port, argv[2]) != 0) {
920                 fprintf (stderr, "Can't parse port: %s\n", argv[2]);
921                 return -1;
922         }
923
924         if (argc > 3)
925                 for (flag = argv[3]; *flag != 0; flag++)
926                         switch (*flag)
927                         {
928                         case 'I':
929                                 if (type != SOCKNAL_CONN_ANY) {
930                                         fprintf(stderr, "Can't flag type twice\n");
931                                         return -1;
932                                 }
933                                 type = SOCKNAL_CONN_BULK_IN;
934                                 break;
935
936                         case 'O':
937                                 if (type != SOCKNAL_CONN_ANY) {
938                                         fprintf(stderr, "Can't flag type twice\n");
939                                         return -1;
940                                 }
941                                 type = SOCKNAL_CONN_BULK_OUT;
942                                 break;
943
944                         case 'C':
945                                 if (type != SOCKNAL_CONN_ANY) {
946                                         fprintf(stderr, "Can't flag type twice\n");
947                                         return -1;
948                                 }
949                                 type = SOCKNAL_CONN_CONTROL;
950                                 break;
951                                 
952                         default:
953                                 fprintf (stderr, "unrecognised flag '%c'\n",
954                                          *flag);
955                                 return (-1);
956                         }
957
958         memset(&locaddr, 0, sizeof(locaddr)); 
959         locaddr.sin_family = AF_INET; 
960         locaddr.sin_addr.s_addr = INADDR_ANY;
961
962         memset(&srvaddr, 0, sizeof(srvaddr));
963         srvaddr.sin_family = AF_INET;
964         srvaddr.sin_port = htons(port);
965         srvaddr.sin_addr.s_addr = htonl(ipaddr);
966
967
968         for (rport = IPPORT_RESERVED - 1; rport > IPPORT_RESERVED / 2; --rport) {
969                 fd = socket(PF_INET, SOCK_STREAM, 0); 
970                 if ( fd < 0 ) { 
971                         fprintf(stderr, "socket() failed: %s\n", strerror(errno)); 
972                         return -1; 
973                 }
974
975                 o = 1;
976                 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
977                                 &o, sizeof(o));
978                 
979                 locaddr.sin_port = htons(rport);
980                 rc = bind(fd, (struct sockaddr *)&locaddr, sizeof(locaddr)); 
981                 if (rc == 0 || errno == EACCES) {
982                         rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
983                         if (rc == 0) {
984                                 break;
985                         } else if (errno != EADDRINUSE) {
986                                 fprintf(stderr, "Error connecting to host: %s\n", strerror(errno));
987                                 close(fd);
988                                 return -1;
989                         }
990                 } else if (errno != EADDRINUSE) {
991                         fprintf(stderr, "Error binding to port %d: %d: %s\n", port, errno, strerror(errno));
992                         close(fd);
993                         return -1;
994                 }
995         }
996
997         if (rport == IPPORT_RESERVED / 2) {
998                 fprintf(stderr,
999                         "Warning: all privileged ports are in use.\n"); 
1000                 return -1;
1001         }
1002
1003         printf("Connected host: %s type: %s\n", 
1004                argv[1],
1005                (type == SOCKNAL_CONN_ANY) ? "A" :
1006                (type == SOCKNAL_CONN_CONTROL) ? "C" :
1007                (type == SOCKNAL_CONN_BULK_IN) ? "I" :
1008                (type == SOCKNAL_CONN_BULK_OUT) ? "O" : "?");
1009
1010         PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
1011         pcfg.pcfg_nal = g_nal;
1012         pcfg.pcfg_fd = fd;
1013         pcfg.pcfg_misc = type;
1014         
1015         rc = pcfg_ioctl(&pcfg);
1016         if (rc) {
1017                 fprintf(stderr, "failed to register fd with portals: %s\n", 
1018                         strerror(errno));
1019                 close (fd);
1020                 return -1;
1021         }
1022
1023         printf("Connection to %s registered with socknal\n", argv[1]);
1024
1025         rc = close(fd);
1026         if (rc)
1027                 fprintf(stderr, "close failed: %d\n", rc);
1028
1029         return 0;
1030 #endif /* HAVE_CONNECT */
1031 }
1032
1033 int jt_ptl_disconnect(int argc, char **argv)
1034 {
1035         struct portals_cfg       pcfg;
1036         ptl_nid_t                nid = PTL_NID_ANY;
1037         __u32                    ipaddr = 0;
1038         int                      rc;
1039
1040         if (argc > 3) {
1041                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
1042                 return 0;
1043         }
1044
1045         if (!g_nal_is_compatible (NULL, SOCKNAL, RANAL, 
1046                                   OPENIBNAL, IIBNAL, VIBNAL, 0))
1047                 return 0;
1048
1049         if (argc >= 2 &&
1050             ptl_parse_anynid (&nid, argv[1]) != 0) {
1051                 fprintf (stderr, "Can't parse nid %s\n", argv[1]);
1052                 return -1;
1053         }
1054
1055         if (g_nal_is_compatible (NULL, SOCKNAL, 0) &&
1056             argc >= 3 &&
1057             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
1058                 fprintf (stderr, "Can't parse ip addr %s\n", argv[2]);
1059                 return -1;
1060         }
1061
1062         PCFG_INIT(pcfg, NAL_CMD_CLOSE_CONNECTION);
1063         pcfg.pcfg_nid     = nid;
1064         pcfg.pcfg_id      = ipaddr;
1065         
1066         rc = pcfg_ioctl(&pcfg);
1067         if (rc) {
1068                 fprintf(stderr, "failed to remove connection: %s\n",
1069                         strerror(errno));
1070                 return -1;
1071         }
1072
1073         return 0;
1074 }
1075
1076 int jt_ptl_push_connection (int argc, char **argv)
1077 {
1078         struct portals_cfg       pcfg;
1079         int                      rc;
1080         ptl_nid_t                nid = PTL_NID_ANY;
1081         __u32                    ipaddr = 0;
1082
1083         if (argc > 3) {
1084                 fprintf(stderr, "usage: %s [nid] [ip]\n", argv[0]);
1085                 return 0;
1086         }
1087
1088         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
1089                 return -1;
1090         
1091         if (argc > 1 &&
1092             ptl_parse_anynid (&nid, argv[1]) != 0) {
1093                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
1094                 return -1;
1095         }
1096                         
1097         if (argc > 2 &&
1098             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
1099                 fprintf(stderr, "Can't parse ipaddr: %s\n", argv[2]);
1100         }
1101
1102         PCFG_INIT(pcfg, NAL_CMD_PUSH_CONNECTION);
1103         pcfg.pcfg_nid     = nid;
1104         pcfg.pcfg_id      = ipaddr;
1105         
1106         rc = pcfg_ioctl(&pcfg);
1107         if (rc) {
1108                 fprintf(stderr, "failed to push connection: %s\n",
1109                         strerror(errno));
1110                 return -1;
1111         }
1112
1113         return 0;
1114 }
1115
1116 int 
1117 jt_ptl_print_active_txs (int argc, char **argv)
1118 {
1119         struct portals_cfg       pcfg;
1120         int                      index;
1121         int                      rc;
1122
1123         if (!g_nal_is_compatible (argv[0], QSWNAL, 0))
1124                 return -1;
1125
1126         for (index = 0;;index++) {
1127                 PCFG_INIT(pcfg, NAL_CMD_GET_TXDESC);
1128                 pcfg.pcfg_count   = index;
1129         
1130                 rc = pcfg_ioctl(&pcfg);
1131                 if (rc != 0)
1132                         break;
1133
1134                 printf ("%p: %5s payload %6d bytes to "LPX64" via "LPX64" by pid %6d: %s, %s, state %d\n",
1135                         pcfg.pcfg_pbuf1,
1136                         pcfg.pcfg_count == PTL_MSG_ACK ? "ACK" :
1137                         pcfg.pcfg_count == PTL_MSG_PUT ? "PUT" :
1138                         pcfg.pcfg_count == PTL_MSG_GET ? "GET" :
1139                         pcfg.pcfg_count == PTL_MSG_REPLY ? "REPLY" : "<wierd message>",
1140                         pcfg.pcfg_size,
1141                         pcfg.pcfg_nid,
1142                         pcfg.pcfg_nid2,
1143                         pcfg.pcfg_misc,
1144                         (pcfg.pcfg_flags & 1) ? "delayed" : "immediate",
1145                         (pcfg.pcfg_flags & 2) ? "nblk"    : "normal",
1146                         pcfg.pcfg_flags >> 2);
1147         }
1148
1149         if (index == 0)
1150                 printf ("<no active descs>\n");
1151         return 0;
1152 }
1153
1154 int jt_ptl_ping(int argc, char **argv)
1155 {
1156         int       rc;
1157         ptl_nid_t nid;
1158         long      count   = 1;
1159         long      size    = 4;
1160         long      timeout = 1;
1161         struct portal_ioctl_data data;
1162
1163         if (argc < 2) {
1164                 fprintf(stderr, "usage: %s nid [count] [size] [timeout (secs)]\n", argv[0]);
1165                 return 0;
1166         }
1167
1168         if (!g_nal_is_set())
1169                 return -1;
1170
1171         if (ptl_parse_nid (&nid, argv[1]) != 0)
1172         {
1173                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1174                 return (-1);
1175         }
1176         
1177         if (argc > 2)
1178         {
1179                 count = atol(argv[2]);
1180
1181                 if (count < 0 || count > 20000) 
1182                 {
1183                         fprintf(stderr, "are you insane?  %ld is a crazy count.\n", count);
1184                         return -1;
1185                 }
1186         }
1187         
1188         if (argc > 3)
1189                 size= atol(argv[3]);
1190
1191         if (argc > 4)
1192                 timeout = atol (argv[4]);
1193         
1194         PORTAL_IOC_INIT (data);
1195         data.ioc_count   = count;
1196         data.ioc_size    = size;
1197         data.ioc_nid     = nid;
1198         data.ioc_nal     = g_nal;
1199         data.ioc_timeout = timeout;
1200         
1201         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PING, &data);
1202         if (rc) {
1203                 fprintf(stderr, "failed to start pinger: %s\n",
1204                         strerror(errno));
1205                 return -1;
1206         }
1207         return 0;
1208 }
1209
1210 int jt_ptl_shownid(int argc, char **argv)
1211 {
1212         struct portal_ioctl_data data;
1213         int                      rc;
1214         
1215         if (argc > 1) {
1216                 fprintf(stderr, "usage: %s\n", argv[0]);
1217                 return 0;
1218         }
1219         
1220         if (!g_nal_is_set())
1221                 return -1;
1222
1223         PORTAL_IOC_INIT (data);
1224         data.ioc_nal = g_nal;
1225         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
1226         if (rc < 0)
1227                 fprintf(stderr, "getting my NID failed: %s\n",
1228                         strerror (errno));
1229         else
1230                 printf(LPX64"\n", data.ioc_nid);
1231         return 0;
1232 }
1233
1234 int jt_ptl_mynid(int argc, char **argv)
1235 {
1236         int rc;
1237         char hostname[1024];
1238         char *nidstr;
1239         struct portals_cfg pcfg;
1240         ptl_nid_t mynid;
1241
1242         if (argc > 2) {
1243                 fprintf(stderr, "usage: %s [NID]\n", argv[0]);
1244                 fprintf(stderr, "NID defaults to the primary IP address of the machine.\n");
1245                 return 0;
1246         }
1247
1248         if (!g_nal_is_set())
1249                 return -1;
1250
1251         if (argc >= 2)
1252                 nidstr = argv[1];
1253         else if (gethostname(hostname, sizeof(hostname)) != 0) {
1254                 fprintf(stderr, "gethostname failed: %s\n",
1255                         strerror(errno));
1256                 return -1;
1257         }
1258         else
1259                 nidstr = hostname;
1260
1261         rc = ptl_parse_nid (&mynid, nidstr);
1262         if (rc != 0) {
1263                 fprintf (stderr, "Can't convert '%s' into a NID\n", nidstr);
1264                 return -1;
1265         }
1266         
1267         PCFG_INIT(pcfg, NAL_CMD_REGISTER_MYNID);
1268         pcfg.pcfg_nid = mynid;
1269
1270         rc = pcfg_ioctl(&pcfg);
1271         if (rc < 0)
1272                 fprintf(stderr, "setting my NID failed: %s\n",
1273                        strerror(errno));
1274         else
1275                 printf("registered my nid "LPX64" (%s)\n", 
1276                        ptl_nid2u64(mynid), hostname);
1277         return 0;
1278 }
1279
1280 int
1281 jt_ptl_fail_nid (int argc, char **argv)
1282 {
1283         int                      rc;
1284         ptl_nid_t                nid;
1285         unsigned int             threshold;
1286         struct portal_ioctl_data data;
1287
1288         if (argc < 2 || argc > 3)
1289         {
1290                 fprintf (stderr, "usage: %s nid|\"_all_\" [count (0 == mend)]\n", argv[0]);
1291                 return (0);
1292         }
1293         
1294         if (!g_nal_is_set())
1295                 return (-1);
1296
1297         if (!strcmp (argv[1], "_all_"))
1298                 nid = PTL_NID_ANY;
1299         else if (ptl_parse_anynid (&nid, argv[1]) != 0)
1300         {
1301                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1302                 return (-1);
1303         }
1304
1305         if (argc < 3)
1306                 threshold = PTL_MD_THRESH_INF;
1307         else if (sscanf (argv[2], "%i", &threshold) != 1) {
1308                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
1309                 return (-1);
1310         }
1311         
1312         PORTAL_IOC_INIT (data);
1313         data.ioc_nal = g_nal;
1314         data.ioc_nid = nid;
1315         data.ioc_count = threshold;
1316         
1317         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_FAIL_NID, &data);
1318         if (rc < 0)
1319                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
1320                          strerror (errno));
1321         else
1322                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1323         
1324         return (0);
1325 }
1326
1327 int
1328 jt_ptl_loopback (int argc, char **argv)
1329 {
1330         int                      rc;
1331         int                      set;
1332         int                      enable;
1333         struct portal_ioctl_data data;
1334
1335         if (argc > 2)
1336         {
1337                 fprintf (stderr, "usage: %s [on|off]\n", argv[0]);
1338                 return (0);
1339         }
1340         
1341         if (!g_nal_is_set())
1342                 return (-1);
1343
1344         set = argc > 1;
1345         if (set && ptl_parse_bool (&enable, argv[1]) != 0) {
1346                 fprintf (stderr, "Can't parse boolean %s\n", argv[1]);
1347                 return (-1);
1348         }
1349
1350         PORTAL_IOC_INIT (data);
1351         data.ioc_nal = g_nal;
1352         data.ioc_flags = enable;
1353         data.ioc_misc = set;
1354         
1355         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_LOOPBACK, &data);
1356         if (rc < 0)
1357                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
1358                          strerror (errno));
1359         else
1360                 printf ("loopback %s\n", data.ioc_flags ? "enabled" : "disabled");
1361         
1362         return (0);
1363 }
1364
1365 int
1366 jt_ptl_add_route (int argc, char **argv)
1367 {
1368         struct portals_cfg       pcfg;
1369         ptl_nid_t                nid1;
1370         ptl_nid_t                nid2;
1371         ptl_nid_t                gateway_nid;
1372         int                      rc;
1373         
1374         if (argc < 3)
1375         {
1376                 fprintf (stderr, "usage: %s gateway target [target]\n", argv[0]);
1377                 return (0);
1378         }
1379
1380         if (!g_nal_is_set())
1381                 return (-1);
1382
1383         if (ptl_parse_nid (&gateway_nid, argv[1]) != 0)
1384         {
1385                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1386                 return (-1);
1387         }
1388
1389         if (ptl_parse_nid (&nid1, argv[2]) != 0)
1390         {
1391                 fprintf (stderr, "Can't parse first target NID \"%s\"\n", argv[2]);
1392                 return (-1);
1393         }
1394
1395         if (argc < 4)
1396                 nid2 = nid1;
1397         else if (ptl_parse_nid (&nid2, argv[3]) != 0)
1398         {
1399                 fprintf (stderr, "Can't parse second target NID \"%s\"\n", argv[4]);
1400                 return (-1);
1401         }
1402
1403         PCFG_INIT(pcfg, NAL_CMD_ADD_ROUTE);
1404         pcfg.pcfg_nid = gateway_nid;
1405         pcfg.pcfg_nal = ROUTER;
1406         pcfg.pcfg_gw_nal = g_nal;
1407         pcfg.pcfg_nid2 = MIN (nid1, nid2);
1408         pcfg.pcfg_nid3 = MAX (nid1, nid2);
1409
1410         rc = pcfg_ioctl(&pcfg);
1411         if (rc != 0) 
1412         {
1413                 fprintf (stderr, "NAL_CMD_ADD_ROUTE failed: %s\n", strerror (errno));
1414                 return (-1);
1415         }
1416         
1417         return (0);
1418 }
1419
1420 int
1421 jt_ptl_del_route (int argc, char **argv)
1422 {
1423         struct portals_cfg       pcfg;
1424         ptl_nid_t                nid;
1425         ptl_nid_t                nid1 = PTL_NID_ANY;
1426         ptl_nid_t                nid2 = PTL_NID_ANY;
1427         int                      rc;
1428         
1429         if (argc < 2)
1430         {
1431                 fprintf (stderr, "usage: %s targetNID\n", argv[0]);
1432                 return (0);
1433         }
1434
1435         if (!g_nal_is_set())
1436                 return (-1);
1437
1438         if (ptl_parse_nid (&nid, argv[1]) != 0)
1439         {
1440                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1441                 return (-1);
1442         }
1443
1444         if (argc >= 3 &&
1445             ptl_parse_nid (&nid1, argv[2]) != 0)
1446         {
1447                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[2]);
1448                 return (-1);
1449         }
1450
1451         if (argc < 4) {
1452                 nid2 = nid1;
1453         } else {
1454                 if (ptl_parse_nid (&nid2, argv[3]) != 0) {
1455                         fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[3]);
1456                         return (-1);
1457                 }
1458
1459                 if (nid1 > nid2) {
1460                         ptl_nid_t tmp = nid1;
1461                         
1462                         nid1 = nid2;
1463                         nid2 = tmp;
1464                 }
1465         }
1466         
1467         PCFG_INIT(pcfg, NAL_CMD_DEL_ROUTE);
1468         pcfg.pcfg_nal = ROUTER;
1469         pcfg.pcfg_gw_nal = g_nal;
1470         pcfg.pcfg_nid = nid;
1471         pcfg.pcfg_nid2 = nid1;
1472         pcfg.pcfg_nid3 = nid2;
1473
1474         rc = pcfg_ioctl(&pcfg);
1475         if (rc != 0) 
1476         {
1477                 fprintf (stderr, "NAL_CMD_DEL_ROUTE ("LPX64") failed: %s\n", 
1478                          ptl_nid2u64(nid), strerror (errno));
1479                 return (-1);
1480         }
1481         
1482         return (0);
1483 }
1484
1485 int
1486 jt_ptl_notify_router (int argc, char **argv)
1487 {
1488         struct portals_cfg       pcfg;
1489         int                      enable;
1490         ptl_nid_t                nid;
1491         int                      rc;
1492         struct timeval           now;
1493         time_t                   when;
1494
1495         if (argc < 3)
1496         {
1497                 fprintf (stderr, "usage: %s targetNID <up/down> [<time>]\n", 
1498                          argv[0]);
1499                 return (0);
1500         }
1501
1502         if (ptl_parse_nid (&nid, argv[1]) != 0)
1503         {
1504                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1505                 return (-1);
1506         }
1507
1508         if (ptl_parse_bool (&enable, argv[2]) != 0) {
1509                 fprintf (stderr, "Can't parse boolean %s\n", argv[2]);
1510                 return (-1);
1511         }
1512
1513         gettimeofday(&now, NULL);
1514         
1515         if (argc < 4) {
1516                 when = now.tv_sec;
1517         } else if (ptl_parse_time (&when, argv[3]) != 0) {
1518                 fprintf(stderr, "Can't parse time %s\n"
1519                         "Please specify either 'YYYY-MM-DD-HH:MM:SS'\n"
1520                         "or an absolute unix time in seconds\n", argv[3]);
1521                 return (-1);
1522         } else if (when > now.tv_sec) {
1523                 fprintf (stderr, "%s specifies a time in the future\n",
1524                          argv[3]);
1525                 return (-1);
1526         }
1527
1528         PCFG_INIT(pcfg, NAL_CMD_NOTIFY_ROUTER);
1529         pcfg.pcfg_nal = ROUTER;
1530         pcfg.pcfg_gw_nal = g_nal;
1531         pcfg.pcfg_nid = nid;
1532         pcfg.pcfg_flags = enable;
1533         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
1534         pcfg.pcfg_nid3 = (__u64)when;
1535         
1536         rc = pcfg_ioctl(&pcfg);
1537         if (rc != 0) 
1538         {
1539                 fprintf (stderr, "NAL_CMD_NOTIFY_ROUTER ("LPX64") failed: %s\n",
1540                          ptl_nid2u64(nid), strerror (errno));
1541                 return (-1);
1542         }
1543         
1544         return (0);
1545 }
1546
1547 int
1548 jt_ptl_print_routes (int argc, char **argv)
1549 {
1550         char                      buffer[3][128];
1551         struct portals_cfg        pcfg;
1552         int                       rc;
1553         int                       index;
1554         int                       gateway_nal;
1555         ptl_nid_t                 gateway_nid;
1556         ptl_nid_t                 nid1;
1557         ptl_nid_t                 nid2;
1558         int                       alive;
1559
1560         for (index = 0;;index++)
1561         {
1562                 PCFG_INIT(pcfg, NAL_CMD_GET_ROUTE);
1563                 pcfg.pcfg_nal = ROUTER;
1564                 pcfg.pcfg_count = index;
1565                 
1566                 rc = pcfg_ioctl(&pcfg);
1567                 if (rc != 0)
1568                         break;
1569
1570                 gateway_nal = pcfg.pcfg_gw_nal;
1571                 gateway_nid = pcfg.pcfg_nid;
1572                 nid1 = pcfg.pcfg_nid2;
1573                 nid2 = pcfg.pcfg_nid3;
1574                 alive = pcfg.pcfg_flags;
1575
1576                 printf ("%8s %18s : %s - %s, %s\n", 
1577                         nal2name (gateway_nal), 
1578                         ptl_nid2str (buffer[0], gateway_nid),
1579                         ptl_nid2str (buffer[1], nid1),
1580                         ptl_nid2str (buffer[2], nid2),
1581                         alive ? "up" : "down");
1582         }
1583         return (0);
1584 }
1585
1586 static int
1587 lwt_control(int enable, int clear)
1588 {
1589         struct portal_ioctl_data data;
1590         int                      rc;
1591
1592         PORTAL_IOC_INIT(data);
1593         data.ioc_flags = enable;
1594         data.ioc_misc = clear;
1595
1596         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_CONTROL, &data);
1597         if (rc == 0)
1598                 return (0);
1599
1600         fprintf(stderr, "IOC_PORTAL_LWT_CONTROL failed: %s\n",
1601                 strerror(errno));
1602         return (-1);
1603 }
1604
1605 static int
1606 lwt_snapshot(cycles_t *now, int *ncpu, int *totalsize, 
1607              lwt_event_t *events, int size)
1608 {
1609         struct portal_ioctl_data data;
1610         int                      rc;
1611
1612         PORTAL_IOC_INIT(data);
1613         data.ioc_pbuf1 = (char *)events;
1614         data.ioc_plen1 = size;
1615
1616         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_SNAPSHOT, &data);
1617         if (rc != 0) {
1618                 fprintf(stderr, "IOC_PORTAL_LWT_SNAPSHOT failed: %s\n",
1619                         strerror(errno));
1620                 return (-1);
1621         }
1622
1623         /* crappy overloads */
1624         if (data.ioc_nid2 != sizeof(lwt_event_t) ||
1625             data.ioc_nid3 != offsetof(lwt_event_t, lwte_where)) {
1626                 fprintf(stderr,"kernel/user LWT event mismatch %d(%d),%d(%d)\n",
1627                         (int)data.ioc_nid2, sizeof(lwt_event_t),
1628                         (int)data.ioc_nid3,
1629                         (int)offsetof(lwt_event_t, lwte_where));
1630                 return (-1);
1631         }
1632
1633         LASSERT (data.ioc_count != 0);
1634         LASSERT (data.ioc_misc != 0);
1635
1636         if (now != NULL)
1637                 *now = data.ioc_nid;
1638
1639         if (ncpu != NULL)
1640                 *ncpu = data.ioc_count;
1641
1642         if (totalsize != NULL)
1643                 *totalsize = data.ioc_misc;
1644
1645         return (0);
1646 }
1647
1648 static char *
1649 lwt_get_string(char *kstr)
1650 {
1651         char                     *ustr;
1652         struct portal_ioctl_data  data;
1653         int                       size;
1654         int                       rc;
1655
1656         /* FIXME: this could maintain a symbol table since we expect to be
1657          * looking up the same strings all the time... */
1658
1659         PORTAL_IOC_INIT(data);
1660         data.ioc_pbuf1 = kstr;
1661         data.ioc_plen1 = 1;        /* non-zero just to fool portal_ioctl_is_invalid() */
1662         data.ioc_pbuf2 = NULL;
1663         data.ioc_plen2 = 0;
1664
1665         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_LOOKUP_STRING, &data);
1666         if (rc != 0) {
1667                 fprintf(stderr, "IOC_PORTAL_LWT_LOOKUP_STRING failed: %s\n",
1668                         strerror(errno));
1669                 return (NULL);
1670         }
1671
1672         size = data.ioc_count;
1673         ustr = (char *)malloc(size);
1674         if (ustr == NULL) {
1675                 fprintf(stderr, "Can't allocate string storage of size %d\n",
1676                         size);
1677                 return (NULL);
1678         }
1679
1680         PORTAL_IOC_INIT(data);
1681         data.ioc_pbuf1 = kstr;
1682         data.ioc_plen1 = 1;        /* non-zero just to fool portal_ioctl_is_invalid() */
1683         data.ioc_pbuf2 = ustr;
1684         data.ioc_plen2 = size;
1685
1686         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_LOOKUP_STRING, &data);
1687         if (rc != 0) {
1688                 fprintf(stderr, "IOC_PORTAL_LWT_LOOKUP_STRING failed: %s\n",
1689                         strerror(errno));
1690                 return (NULL);
1691         }
1692
1693         LASSERT(strlen(ustr) == size - 1);
1694         return (ustr);
1695 }
1696
1697 static void
1698 lwt_put_string(char *ustr)
1699 {
1700         free(ustr);
1701 }
1702
1703 static int
1704 lwt_print(FILE *f, cycles_t t0, cycles_t tlast, double mhz, int cpu, lwt_event_t *e)
1705 {
1706 #ifndef __WORDSIZE
1707 # error "__WORDSIZE not defined"
1708 #elif __WORDSIZE == 32
1709 # define XFMT "%#010lx"
1710 #elif __WORDSIZE== 64
1711 # define XFMT "%#018lx"
1712 #else
1713 # error "Unexpected __WORDSIZE"
1714 #endif
1715         char           *where = lwt_get_string(e->lwte_where);
1716
1717         if (where == NULL)
1718                 return (-1);
1719
1720         fprintf(f, XFMT" "XFMT" "XFMT" "XFMT": "XFMT" %2d %10.6f %10.2f %s\n",
1721                 e->lwte_p1, e->lwte_p2, e->lwte_p3, e->lwte_p4,
1722                 (long)e->lwte_task, cpu, (e->lwte_when - t0) / (mhz * 1000000.0),
1723                 (t0 == e->lwte_when) ? 0.0 : (e->lwte_when - tlast) / mhz,
1724                 where);
1725
1726         lwt_put_string(where);
1727
1728         return (0);
1729 #undef XFMT
1730 }
1731
1732 double
1733 get_cycles_per_usec ()
1734 {
1735         FILE      *f = fopen ("/proc/cpuinfo", "r");
1736         double     mhz;
1737         char      line[64];
1738         
1739         if (f != NULL) {
1740                 while (fgets (line, sizeof (line), f) != NULL)
1741                         if (sscanf (line, "cpu MHz : %lf", &mhz) == 1) {
1742                                 fclose (f);
1743                                 return (mhz);
1744                         }
1745                 fclose (f);
1746         }
1747
1748         fprintf (stderr, "Can't read/parse /proc/cpuinfo\n");
1749         return (1000.0);
1750 }
1751
1752 int
1753 jt_ptl_lwt(int argc, char **argv)
1754 {
1755         const int       lwt_max_cpus = 32;
1756         int             ncpus;
1757         int             totalspace;
1758         int             nevents_per_cpu;
1759         lwt_event_t    *events;
1760         lwt_event_t    *cpu_event[lwt_max_cpus + 1];
1761         lwt_event_t    *next_event[lwt_max_cpus];
1762         lwt_event_t    *first_event[lwt_max_cpus];
1763         int             cpu;
1764         lwt_event_t    *e;
1765         int             rc;
1766         int             i;
1767         double          mhz;
1768         cycles_t        t0;
1769         cycles_t        tlast;
1770         cycles_t        tnow;
1771         struct timeval  tvnow;
1772         int             printed_date = 0;
1773         int             nlines = 0;
1774         FILE           *f = stdout;
1775
1776         if (argc < 2 ||
1777             (strcmp(argv[1], "start") &&
1778              strcmp(argv[1], "stop"))) {
1779                 fprintf(stderr, 
1780                         "usage:  %s start\n"
1781                         "        %s stop [fname]\n", argv[0], argv[0]);
1782                 return (-1);
1783         }
1784         
1785         if (!strcmp(argv[1], "start")) {
1786                 /* disable */
1787                 if (lwt_control(0, 0) != 0)
1788                         return (-1);
1789
1790                 /* clear */
1791                 if (lwt_control(0, 1) != 0)
1792                         return (-1);
1793
1794                 /* enable */
1795                 if (lwt_control(1, 0) != 0)
1796                         return (-1);
1797
1798                 return (0);
1799         }
1800                 
1801         if (lwt_snapshot(NULL, &ncpus, &totalspace, NULL, 0) != 0)
1802                 return (-1);
1803
1804         if (ncpus > lwt_max_cpus) {
1805                 fprintf(stderr, "Too many cpus: %d (%d)\n", 
1806                         ncpus, lwt_max_cpus);
1807                 return (-1);
1808         }
1809
1810         events = (lwt_event_t *)malloc(totalspace);
1811         if (events == NULL) {
1812                 fprintf(stderr, "Can't allocate %d\n", totalspace);
1813                 return (-1);
1814         }
1815
1816         if (lwt_control(0, 0) != 0) {           /* disable */
1817                 free(events);
1818                 return (-1);
1819         }
1820
1821         if (lwt_snapshot(&tnow, NULL, NULL, events, totalspace)) {
1822                 free(events);
1823                 return (-1);
1824         }
1825
1826         /* we want this time to be sampled at snapshot time */
1827         gettimeofday(&tvnow, NULL);
1828
1829         if (argc > 2) {
1830                 f = fopen (argv[2], "w");
1831                 if (f == NULL) {
1832                         fprintf(stderr, "Can't open %s for writing: %s\n", argv[2], strerror (errno));
1833                         free(events);
1834                         return (-1);
1835                 }
1836         }
1837
1838         mhz = get_cycles_per_usec();
1839         
1840         /* carve events into per-cpu slices */
1841         nevents_per_cpu = totalspace / (ncpus * sizeof(lwt_event_t));
1842         for (cpu = 0; cpu <= ncpus; cpu++)
1843                 cpu_event[cpu] = &events[cpu * nevents_per_cpu];
1844
1845         /* find the earliest event on each cpu */
1846         for (cpu = 0; cpu < ncpus; cpu++) {
1847                 first_event[cpu] = NULL;
1848
1849                 for (e = cpu_event[cpu]; e < cpu_event[cpu + 1]; e++) {
1850
1851                         if (e->lwte_where == NULL) /* not an event */
1852                                 continue;
1853
1854                         if (first_event[cpu] == NULL ||
1855                             first_event[cpu]->lwte_when > e->lwte_when)
1856                                 first_event[cpu] = e;
1857                 }
1858
1859                 next_event[cpu] = first_event[cpu];
1860         }
1861
1862         t0 = tlast = 0;
1863         for (cpu = 0; cpu < ncpus; cpu++) {
1864                 e = first_event[cpu];
1865                 if (e == NULL)                  /* no events this cpu */
1866                         continue;
1867                 
1868                 if (e == cpu_event[cpu])
1869                         e = cpu_event[cpu + 1] - 1;
1870                 else 
1871                         e = e - 1;
1872                 
1873                 /* If there's an event immediately before the first one, this
1874                  * cpu wrapped its event buffer */
1875                 if (e->lwte_where == NULL)
1876                         continue;
1877          
1878                 /* We should only start outputting events from the most recent
1879                  * first event in any wrapped cpu.  Events before this time on
1880                  * other cpus won't have any events from this CPU to interleave
1881                  * with. */
1882                 if (t0 < first_event[cpu]->lwte_when)
1883                         t0 = first_event[cpu]->lwte_when;
1884         }
1885
1886         for (;;) {
1887                 /* find which cpu has the next event */
1888                 cpu = -1;
1889                 for (i = 0; i < ncpus; i++) {
1890
1891                         if (next_event[i] == NULL) /* this cpu exhausted */
1892                                 continue;
1893
1894                         if (cpu < 0 ||
1895                             next_event[i]->lwte_when < next_event[cpu]->lwte_when)
1896                                 cpu = i;
1897                 }
1898
1899                 if (cpu < 0)                    /* all cpus exhausted */
1900                         break;
1901
1902                 if (t0 == 0) {
1903                         /* no wrapped cpus and this is he first ever event */
1904                         t0 = next_event[cpu]->lwte_when;
1905                 }
1906                 
1907                 if (t0 <= next_event[cpu]->lwte_when) {
1908                         /* on or after the first event */
1909                         if (!printed_date) {
1910                                 cycles_t du = (tnow - t0) / mhz;
1911                                 time_t   then = tvnow.tv_sec - du/1000000;
1912                                 
1913                                 if (du % 1000000 > tvnow.tv_usec)
1914                                         then--;
1915
1916                                 fprintf(f, "%s", ctime(&then));
1917                                 printed_date = 1;
1918                         }
1919                         
1920                         rc = lwt_print(f, t0, tlast, mhz, cpu, next_event[cpu]);
1921                         if (rc != 0)
1922                                 break;
1923
1924                         if (++nlines % 10000 == 0 && f != stdout) {
1925                                 /* show some activity... */
1926                                 printf(".");
1927                                 fflush (stdout);
1928                         }
1929                 }
1930
1931                 tlast = next_event[cpu]->lwte_when;
1932                 
1933                 next_event[cpu]++;
1934                 if (next_event[cpu] == cpu_event[cpu + 1])
1935                         next_event[cpu] = cpu_event[cpu];
1936
1937                 if (next_event[cpu]->lwte_where == NULL ||
1938                     next_event[cpu] == first_event[cpu])
1939                         next_event[cpu] = NULL;
1940         }
1941
1942         if (f != stdout) {
1943                 printf("\n");
1944                 fclose(f);
1945         }
1946
1947         free(events);
1948         return (0);
1949 }
1950
1951 int jt_ptl_memhog(int argc, char **argv)
1952 {
1953         static int                gfp = 0;        /* sticky! */
1954
1955         struct portal_ioctl_data  data;
1956         int                       rc;
1957         int                       count;
1958         char                     *end;
1959         
1960         if (argc < 2)  {
1961                 fprintf(stderr, "usage: %s <npages> [<GFP flags>]\n", argv[0]);
1962                 return 0;
1963         }
1964
1965         count = strtol(argv[1], &end, 0);
1966         if (count < 0 || *end != 0) {
1967                 fprintf(stderr, "Can't parse page count '%s'\n", argv[1]);
1968                 return -1;
1969         }
1970
1971         if (argc >= 3) {
1972                 rc = strtol(argv[2], &end, 0);
1973                 if (*end != 0) {
1974                         fprintf(stderr, "Can't parse gfp flags '%s'\n", argv[2]);
1975                         return -1;
1976                 }
1977                 gfp = rc;
1978         }
1979         
1980         PORTAL_IOC_INIT(data);
1981         data.ioc_count = count;
1982         data.ioc_flags = gfp;
1983         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_MEMHOG, &data);
1984
1985         if (rc != 0) {
1986                 fprintf(stderr, "memhog %d failed: %s\n", count, strerror(errno));
1987                 return -1;
1988         }
1989         
1990         printf("memhog %d OK\n", count);
1991         return 0;
1992 }
1993