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