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