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