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