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