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