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