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