Whamcloud - gitweb
- landing of b_fid after merge with b_hd_cleanup_merge.
[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 #include <netinet/in.h>
41 #endif
42  
43 #include <portals/api-support.h>
44 #include <portals/ptlctl.h>
45 #include <portals/list.h>
46 #include <portals/lib-types.h>
47 #include <portals/socknal.h>
48 #include "parser.h"
49
50 unsigned int portal_debug;
51 unsigned int portal_printk;
52
53 static unsigned int g_nal = 0;
54
55 typedef struct {
56         char *name;
57         int   num;
58 } name2num_t;
59
60 static name2num_t nalnames[] = {
61         {"any",         0},
62         {"tcp",         SOCKNAL},
63         {"elan",        QSWNAL},
64         {"gm",          GMNAL},
65         {"openib",      OPENIBNAL},
66         {NULL,          -1}
67 };
68
69 static cfg_record_cb_t g_record_cb;
70
71 /* Convert a string boolean to an int; "enable" -> 1 */
72 int ptl_parse_bool (int *b, char *str) {
73         if (!strcasecmp (str, "no") ||
74             !strcasecmp (str, "n") ||
75             !strcasecmp (str, "off") ||
76             !strcasecmp (str, "down") ||
77             !strcasecmp (str, "disable"))
78         {
79                 *b = 0;
80                 return (0);
81         }
82         
83         if (!strcasecmp (str, "yes") ||
84             !strcasecmp (str, "y") ||
85             !strcasecmp (str, "on") ||
86             !strcasecmp (str, "up") ||
87             !strcasecmp (str, "enable"))
88         {
89                 *b = 1;
90                 return (0);
91         }
92         
93         return (-1);
94 }
95
96 /* Convert human readable size string to and int; "1k" -> 1000 */
97 int ptl_parse_size (int *sizep, char *str) {
98         int size;
99         char mod[32];
100
101         switch (sscanf (str, "%d%1[gGmMkK]", &size, mod)) {
102         default:
103                 return (-1);
104
105         case 1:
106                 *sizep = size;
107                 return (0);
108
109         case 2:
110                 switch (*mod) {
111                 case 'g':
112                 case 'G':
113                         *sizep = size << 30;
114                         return (0);
115
116                 case 'm':
117                 case 'M':
118                         *sizep = size << 20;
119                         return (0);
120
121                 case 'k':
122                 case 'K':
123                         *sizep = size << 10;
124                         return (0);
125
126                 default:
127                         *sizep = size;
128                         return (0);
129                 }
130         }
131 }
132
133 int 
134 ptl_set_cfg_record_cb(cfg_record_cb_t cb)
135 {
136         g_record_cb = cb;
137         return 0;
138 }
139
140 int 
141 pcfg_ioctl(struct portals_cfg *pcfg) 
142 {
143         int rc;
144
145         if (pcfg->pcfg_nal ==0)
146                 pcfg->pcfg_nal    = g_nal;
147
148         if (g_record_cb) {
149                 rc = g_record_cb(PORTALS_CFG_TYPE, sizeof(*pcfg), pcfg);
150         } else {
151                 struct portal_ioctl_data data;
152                 PORTAL_IOC_INIT (data);
153                 data.ioc_pbuf1   = (char*)pcfg;
154                 data.ioc_plen1   = sizeof(*pcfg);
155                 /* XXX liblustre hack XXX */
156                 data.ioc_nal_cmd = pcfg->pcfg_command;
157                 data.ioc_nid = pcfg->pcfg_nid;
158
159                 rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
160         }
161
162         return (rc);
163 }
164
165
166
167 static name2num_t *
168 name2num_lookup_name (name2num_t *table, char *str)
169 {
170         while (table->name != NULL)
171                 if (!strcmp (str, table->name))
172                         return (table);
173                 else
174                         table++;
175         return (NULL);
176 }
177
178 static name2num_t *
179 name2num_lookup_num (name2num_t *table, int num)
180 {
181         while (table->name != NULL)
182                 if (num == table->num)
183                         return (table);
184                 else
185                         table++;
186         return (NULL);
187 }
188
189 int
190 ptl_name2nal (char *str)
191 {
192         name2num_t *e = name2num_lookup_name (nalnames, str);
193
194         return ((e == NULL) ? -1 : e->num);
195 }
196
197 static char *
198 nal2name (int nal)
199 {
200         name2num_t *e = name2num_lookup_num (nalnames, nal);
201
202         return ((e == NULL) ? "???" : e->name);
203 }
204
205 static struct hostent *
206 ptl_gethostbyname(char * hname) {
207         struct hostent *he;
208         he = gethostbyname(hname);
209         if (!he) {
210                 switch(h_errno) {
211                 case HOST_NOT_FOUND:
212                 case NO_ADDRESS:
213                         fprintf(stderr, "Unable to resolve hostname: %s\n",
214                                 hname);
215                         break;
216                 default:
217                         fprintf(stderr, "gethostbyname error: %s\n",
218                                 strerror(errno));
219                         break;
220                 }
221                 return NULL;
222         }
223         return he;
224 }
225
226 int
227 ptl_parse_port (int *port, char *str)
228 {
229         char      *end;
230         
231         *port = strtol (str, &end, 0);
232
233         if (*end == 0 &&                        /* parsed whole string */
234             *port > 0 && *port < 65536)         /* minimal sanity check */
235                 return (0);
236         
237         return (-1);
238 }
239
240 int
241 ptl_parse_time (time_t *t, char *str) 
242 {
243         char          *end;
244         int            n;
245         struct tm      tm;
246         
247         *t = strtol (str, &end, 0);
248         if (*end == 0) /* parsed whole string */
249                 return (0);
250         
251         memset (&tm, 0, sizeof (tm));
252         n = sscanf (str, "%d-%d-%d-%d:%d:%d",
253                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
254                     &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
255         if (n != 6)
256                 return (-1);
257         
258         tm.tm_mon--;                    /* convert to 0 == Jan */
259         tm.tm_year -= 1900;             /* y2k quirk */
260         tm.tm_isdst = -1;               /* dunno if it's daylight savings... */
261         
262         *t = mktime (&tm);
263         if (*t == (time_t)-1)
264                 return (-1);
265                         
266         return (0);
267 }
268
269 int
270 ptl_parse_ipquad (__u32 *ipaddrp, char *str)
271 {
272         int             a;
273         int             b;
274         int             c;
275         int             d;
276
277         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
278             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
279             (c & ~0xff) == 0 && (d & ~0xff) == 0)
280         {
281                 *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
282                 return (0);
283         }
284
285         return (-1);
286 }
287
288 int
289 ptl_parse_ipaddr (__u32 *ipaddrp, char *str)
290 {
291         struct hostent *he;
292
293         if (!strcmp (str, "_all_")) 
294         {
295                 *ipaddrp = 0;
296                 return (0);
297         }
298
299         if (ptl_parse_ipquad(ipaddrp, str) == 0)
300                 return (0);
301         
302         if ((('a' <= str[0] && str[0] <= 'z') ||
303              ('A' <= str[0] && str[0] <= 'Z')) &&
304              (he = ptl_gethostbyname (str)) != NULL)
305         {
306                 __u32 addr = *(__u32 *)he->h_addr;
307
308                 *ipaddrp = ntohl(addr);         /* HOST byte order */
309                 return (0);
310         }
311
312         return (-1);
313 }
314
315 char *
316 ptl_ipaddr_2_str (__u32 ipaddr, char *str, int lookup)
317 {
318         __u32           net_ip;
319         struct hostent *he;
320
321         if (lookup) {
322                 net_ip = htonl (ipaddr);
323                 he = gethostbyaddr (&net_ip, sizeof (net_ip), AF_INET);
324                 if (he != NULL) {
325                         strcpy(str, he->h_name);
326                         return (str);
327                 }
328         }
329         
330         sprintf (str, "%d.%d.%d.%d",
331                  (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
332                  (ipaddr >> 8) & 0xff, ipaddr & 0xff);
333         return (str);
334 }
335
336 int
337 ptl_parse_nid (ptl_nid_t *nidp, char *str)
338 {
339         __u32               ipaddr;
340         char               *end;
341         unsigned long long  ullval;
342         
343         if (!strcmp (str, "_all_")) {
344                 *nidp = PTL_NID_ANY;
345                 return (0);
346         }
347
348         if (ptl_parse_ipaddr (&ipaddr, str) == 0) {
349                 *nidp = (ptl_nid_t)ipaddr;
350                 return (0);
351         }
352
353         ullval = strtoull(str, &end, 0);
354         if (*end == 0) {
355                 /* parsed whole string */
356                 *nidp = (ptl_nid_t)ullval;
357                 return (0);
358         }
359
360         return (-1);
361 }
362
363 __u64 ptl_nid2u64(ptl_nid_t nid)
364 {
365         switch (sizeof (nid)) {
366         case 8:
367                 return (nid);
368         case 4:
369                 return ((__u32)nid);
370         default:
371                 fprintf(stderr, "Unexpected sizeof(ptl_nid_t) == %u\n", sizeof(nid));
372                 abort();
373                 /* notreached */
374                 return (-1);
375         }
376 }
377
378 char *
379 ptl_nid2str (char *buffer, ptl_nid_t nid)
380 {
381         __u64           nid64 = ptl_nid2u64(nid);
382         struct hostent *he = 0;
383
384         /* Don't try to resolve NIDs that are e.g. Elan host IDs.  Assume
385          * TCP addresses in the 0.x.x.x subnet are not in use.  This can
386          * happen on routers and slows things down a _lot_.  Bug 3442. */
387         if (nid & 0xff000000) {
388                 __u32 addr = htonl((__u32)nid); /* back to NETWORK byte order */
389
390                 he = gethostbyaddr ((const char *)&addr, sizeof (addr), AF_INET);
391         }
392
393         if (he != NULL)
394                 sprintf(buffer, "%#x:%s", (int)(nid64 >> 32), he->h_name);
395         else
396                 sprintf(buffer, LPX64, nid64);
397
398         return (buffer);
399 }
400
401 int g_nal_is_set () 
402 {
403         if (g_nal == 0) {
404                 fprintf (stderr, "Error: you must run the 'network' command first.\n");
405                 return (0);
406         }
407
408         return (1);
409 }
410
411 int g_nal_is_compatible (char *cmd, ...)
412 {
413         va_list       ap;
414         int           nal;
415
416         if (!g_nal_is_set ())
417                 return (0);
418
419         va_start (ap, cmd);
420
421         do {
422                 nal = va_arg (ap, int);
423         } while (nal != 0 && nal != g_nal);
424         
425         va_end (ap);
426         
427         if (g_nal == nal)
428                 return (1);
429
430         if (cmd != NULL) {
431                 /* Don't complain verbosely if we've not been passed a command
432                  * name to complain about! */
433                 fprintf (stderr, "Command %s not compatible with nal %s\n",
434                          cmd, nal2name (g_nal));
435         }
436         return (0);
437 }
438
439 int
440 sock_write (int cfd, void *buffer, int nob)
441 {
442         while (nob > 0)
443         {
444                 int rc = write (cfd, buffer, nob);
445
446                 if (rc < 0)
447                 {
448                         if (errno == EINTR)
449                                 continue;
450                         
451                         return (rc);
452                 }
453
454                 if (rc == 0)
455                 {
456                         fprintf (stderr, "Unexpected zero sock_write\n");
457                         abort();
458                 }
459
460                 nob -= rc;
461                 buffer = (char *)buffer + nob;
462         }
463         
464         return (0);
465 }
466
467 int
468 sock_read (int cfd, void *buffer, int nob)
469 {
470         while (nob > 0)
471         {
472                 int rc = read (cfd, buffer, nob);
473                 
474                 if (rc < 0)
475                 {
476                         if (errno == EINTR)
477                                 continue;
478                         
479                         return (rc);
480                 }
481                 
482                 if (rc == 0)                    /* EOF */
483                 {
484                         errno = ECONNABORTED;
485                         return (-1);
486                 }
487                 
488                 nob -= rc;
489                 buffer = (char *)buffer + nob;
490         }
491         
492         return (0);
493 }
494
495 int ptl_initialize(int argc, char **argv) 
496 {
497         register_ioc_dev(PORTALS_DEV_ID, PORTALS_DEV_PATH);
498         return 0;
499 }
500
501
502 int jt_ptl_network(int argc, char **argv)
503 {
504         name2num_t *entry;
505         int         nal;
506         
507         if (argc == 2 &&
508             (nal = ptl_name2nal (argv[1])) >= 0) {
509                 g_nal = nal;
510                 return (0);
511         }
512                 
513         fprintf(stderr, "usage: %s \n", argv[0]);
514         for (entry = nalnames; entry->name != NULL; entry++)
515                 fprintf (stderr, "%s%s", entry == nalnames ? "<" : "|", entry->name);
516         fprintf(stderr, ">\n");
517         return (-1);
518 }
519
520
521 int
522 jt_ptl_print_interfaces (int argc, char **argv)
523 {
524         struct portals_cfg       pcfg;
525         char                     buffer[3][64];
526         int                      index;
527         int                      rc;
528
529         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
530                 return -1;
531
532         for (index = 0;;index++) {
533                 PCFG_INIT (pcfg, NAL_CMD_GET_INTERFACE);
534                 pcfg.pcfg_count = index;
535
536                 rc = pcfg_ioctl (&pcfg);
537                 if (rc != 0)
538                         break;
539
540                 printf ("%s: (%s/%s) npeer %d nroute %d\n",
541                         ptl_ipaddr_2_str(pcfg.pcfg_id, buffer[2], 1),
542                         ptl_ipaddr_2_str(pcfg.pcfg_id, buffer[0], 0),
543                         ptl_ipaddr_2_str(pcfg.pcfg_misc, buffer[1], 0),
544                         pcfg.pcfg_fd, pcfg.pcfg_count);
545         }
546
547         if (index == 0)
548                 printf ("<no interfaces>\n");
549         return 0;
550 }
551
552 int
553 jt_ptl_add_interface (int argc, char **argv)
554 {
555         struct portals_cfg       pcfg;
556         __u32                    ipaddr;
557         int                      rc;
558         __u32                    netmask = 0xffffff00;
559
560         if (argc < 2 || argc > 3) {
561                 fprintf (stderr, "usage: %s ipaddr [netmask]\n", argv[0]);
562                 return 0;
563         }
564
565         if (!g_nal_is_compatible(argv[0], SOCKNAL, 0))
566                 return -1;
567
568         if (ptl_parse_ipaddr(&ipaddr, argv[1]) != 0) {
569                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
570                 return -1;
571         }
572         
573         if (argc > 2 &&
574             ptl_parse_ipquad(&netmask, argv[2]) != 0) {
575                 fprintf (stderr, "Can't parse netmask: %s\n", argv[2]);
576                 return -1;
577         }
578         
579         PCFG_INIT(pcfg, NAL_CMD_ADD_INTERFACE);
580         pcfg.pcfg_id     = ipaddr;
581         pcfg.pcfg_misc   = netmask;
582
583         rc = pcfg_ioctl (&pcfg);
584         if (rc != 0) {
585                 fprintf (stderr, "failed to add interface: %s\n",
586                          strerror (errno));
587                 return -1;
588         }
589         
590         return 0;
591 }
592
593 int
594 jt_ptl_del_interface (int argc, char **argv)
595 {
596         struct portals_cfg       pcfg;
597         int                      rc;
598         __u32                    ipaddr = 0;
599
600         if (argc > 2) {
601                 fprintf (stderr, "usage: %s [ipaddr]\n", argv[0]);
602                 return 0;
603         }
604
605         if (!g_nal_is_compatible(argv[0], SOCKNAL, 0))
606                 return -1;
607
608         if (argc == 2 &&
609             ptl_parse_ipaddr(&ipaddr, argv[1]) != 0) {
610                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
611                 return -1;
612         }
613         
614         PCFG_INIT(pcfg, NAL_CMD_DEL_INTERFACE);
615         pcfg.pcfg_id = ipaddr;
616
617         rc = pcfg_ioctl (&pcfg);
618         if (rc != 0) {
619                 fprintf (stderr, "failed to delete interface: %s\n",
620                          strerror (errno));
621                 return -1;
622         }
623         
624         return 0;
625 }
626
627 int 
628 jt_ptl_print_peers (int argc, char **argv)
629 {
630         struct portals_cfg       pcfg;
631         char                     buffer[2][64];
632         int                      index;
633         int                      rc;
634
635         if (!g_nal_is_compatible (argv[0], SOCKNAL, OPENIBNAL, 0))
636                 return -1;
637
638         for (index = 0;;index++) {
639                 PCFG_INIT (pcfg, NAL_CMD_GET_PEER);
640                 pcfg.pcfg_count   = index;
641
642                 rc = pcfg_ioctl (&pcfg);
643                 if (rc != 0)
644                         break;
645
646                 if (g_nal_is_compatible(NULL, SOCKNAL, 0))
647                         printf (LPX64"[%d]%s@%s:%d #%d\n",
648                                 pcfg.pcfg_nid, pcfg.pcfg_wait,
649                                 ptl_ipaddr_2_str (pcfg.pcfg_size, buffer[0], 1),
650                                 ptl_ipaddr_2_str (pcfg.pcfg_id, buffer[1], 1),
651                                 pcfg.pcfg_misc, pcfg.pcfg_count);
652                 else
653                         printf (LPX64"[%d]\n",
654                                 pcfg.pcfg_nid, pcfg.pcfg_wait);
655         }
656
657         if (index == 0)
658                 printf ("<no peers>\n");
659         return 0;
660 }
661
662 int 
663 jt_ptl_add_peer (int argc, char **argv)
664 {
665         struct portals_cfg       pcfg;
666         ptl_nid_t                nid;
667         __u32                    ip = 0;
668         int                      port = 0;
669         int                      rc;
670
671         if (!g_nal_is_compatible (argv[0], SOCKNAL, OPENIBNAL, 0))
672                 return -1;
673
674         if (g_nal_is_compatible(NULL, SOCKNAL, 0)) {
675                 if (argc != 4) {
676                         fprintf (stderr, "usage(tcp): %s nid ipaddr port\n", 
677                                  argv[0]);
678                         return 0;
679                 }
680         } else if (argc != 2) {
681                 fprintf (stderr, "usage(openib): %s nid\n", argv[0]);
682                 return 0;
683         }
684
685         if (ptl_parse_nid (&nid, argv[1]) != 0 ||
686                 nid == PTL_NID_ANY) {
687                 fprintf (stderr, "Can't parse NID: %s\n", argv[1]);
688                 return -1;
689         }
690
691         if (g_nal_is_compatible (NULL, SOCKNAL, 0)) {
692                 if (ptl_parse_ipaddr (&ip, argv[2]) != 0) {
693                         fprintf (stderr, "Can't parse ip addr: %s\n", argv[2]);
694                         return -1;
695                 }
696
697                 if (ptl_parse_port (&port, argv[3]) != 0) {
698                         fprintf (stderr, "Can't parse port: %s\n", argv[3]);
699                         return -1;
700                 }
701         }
702
703         PCFG_INIT(pcfg, NAL_CMD_ADD_PEER);
704         pcfg.pcfg_nid     = nid;
705         pcfg.pcfg_id      = ip;
706         pcfg.pcfg_misc    = port;
707
708         rc = pcfg_ioctl (&pcfg);
709         if (rc != 0) {
710                 fprintf (stderr, "failed to add peer: %s\n",
711                          strerror (errno));
712                 return -1;
713         }
714         
715         return 0;
716 }
717
718 int 
719 jt_ptl_del_peer (int argc, char **argv)
720 {
721         struct portals_cfg       pcfg;
722         ptl_nid_t                nid = PTL_NID_ANY;
723         __u32                    ip = 0;
724         int                      single_share = 0;
725         int                      argidx;
726         int                      rc;
727
728         if (!g_nal_is_compatible (argv[0], SOCKNAL, OPENIBNAL, 0))
729                 return -1;
730
731         if (g_nal_is_compatible(NULL, SOCKNAL, 0)) {
732                 if (argc > 4) {
733                         fprintf (stderr, "usage: %s [nid] [ipaddr] [single_share]\n",
734                                  argv[0]);
735                         return 0;
736                 }
737         } else if (argc > 3) {
738                 fprintf (stderr, "usage: %s [nid] [single_share]\n", argv[0]);
739                 return 0;
740         }
741                 
742         if (argc > 1 &&
743             ptl_parse_nid (&nid, argv[1]) != 0) {
744                 fprintf (stderr, "Can't parse nid: %s\n", argv[1]);
745                 return -1;
746         }
747
748         argidx = 2;
749         if (g_nal_is_compatible(NULL, SOCKNAL, 0)) {
750                 if (argc > argidx &&
751                     ptl_parse_ipaddr (&ip, argv[argidx]) != 0) {
752                         fprintf (stderr, "Can't parse ip addr: %s\n",
753                                  argv[argidx]);
754                         return -1;
755                 }
756                 argidx++;
757         }
758         
759         if (argc > argidx) {
760                 if (!strcmp (argv[3], "single_share")) {
761                         single_share = 1;
762                 } else {
763                         fprintf (stderr, "Unrecognised arg %s'\n", argv[3]);
764                         return -1;
765                 }
766         }
767
768         PCFG_INIT(pcfg, NAL_CMD_DEL_PEER);
769         pcfg.pcfg_nid = nid;
770         pcfg.pcfg_id = ip;
771         pcfg.pcfg_flags = single_share;
772
773         rc = pcfg_ioctl (&pcfg);
774         if (rc != 0) {
775                 fprintf (stderr, "failed to remove peer: %s\n",
776                          strerror (errno));
777                 return -1;
778         }
779         
780         return 0;
781 }
782
783 int 
784 jt_ptl_print_connections (int argc, char **argv)
785 {
786         struct portals_cfg       pcfg;
787         char                     buffer[2][64];
788         int                      index;
789         int                      rc;
790
791         if (!g_nal_is_compatible (argv[0], SOCKNAL, OPENIBNAL, 0))
792                 return -1;
793
794         for (index = 0;;index++) {
795                 PCFG_INIT (pcfg,  NAL_CMD_GET_CONN);
796                 pcfg.pcfg_count   = index;
797                 
798                 rc = pcfg_ioctl (&pcfg);
799                 if (rc != 0)
800                         break;
801
802                 if (g_nal_is_compatible (NULL, SOCKNAL, 0))
803                         printf ("[%d]%s:"LPX64"@%s:%d:%s %d/%d %s\n",
804                                 pcfg.pcfg_gw_nal,       /* scheduler */
805                                 ptl_ipaddr_2_str (pcfg.pcfg_fd, buffer[0], 1), /* local IP addr */
806                                 pcfg.pcfg_nid, 
807                                 ptl_ipaddr_2_str (pcfg.pcfg_id, buffer[1], 1), /* remote IP addr */
808                                 pcfg.pcfg_misc,         /* remote port */
809                                 (pcfg.pcfg_flags == SOCKNAL_CONN_ANY) ? "A" :
810                                 (pcfg.pcfg_flags == SOCKNAL_CONN_CONTROL) ? "C" :
811                                 (pcfg.pcfg_flags == SOCKNAL_CONN_BULK_IN) ? "I" :
812                                 (pcfg.pcfg_flags == SOCKNAL_CONN_BULK_OUT) ? "O" : "?",
813                                 pcfg.pcfg_count,        /* tx buffer size */
814                                 pcfg.pcfg_size,         /* rx buffer size */
815                                 pcfg.pcfg_wait ? "nagle" : "nonagle");
816                 else
817                         printf (LPX64"\n",
818                                 pcfg.pcfg_nid);
819         }
820
821         if (index == 0)
822                 printf ("<no connections>\n");
823         return 0;
824 }
825
826 int jt_ptl_connect(int argc, char **argv)
827 {
828         struct portals_cfg pcfg;
829         struct sockaddr_in srvaddr;
830         __u32 ipaddr;
831         char *flag;
832         int fd, rc;
833         int type = SOCKNAL_CONN_ANY;
834         int port;
835
836         if (argc < 3) {
837                 fprintf(stderr, "usage: %s ip port [type]\n", argv[0]);
838                 return 0;
839         }
840
841         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
842                 return -1;
843         
844         rc = ptl_parse_ipaddr (&ipaddr, argv[1]);
845         if (rc != 0) {
846                 fprintf(stderr, "Can't parse hostname: %s\n", argv[1]);
847                 return -1;
848         }
849
850         if (ptl_parse_port (&port, argv[2]) != 0) {
851                 fprintf (stderr, "Can't parse port: %s\n", argv[2]);
852                 return -1;
853         }
854
855         if (argc > 3)
856                 for (flag = argv[3]; *flag != 0; flag++)
857                         switch (*flag)
858                         {
859                         case 'I':
860                                 if (type != SOCKNAL_CONN_ANY) {
861                                         fprintf(stderr, "Can't flag type twice\n");
862                                         return -1;
863                                 }
864                                 type = SOCKNAL_CONN_BULK_IN;
865                                 break;
866
867                         case 'O':
868                                 if (type != SOCKNAL_CONN_ANY) {
869                                         fprintf(stderr, "Can't flag type twice\n");
870                                         return -1;
871                                 }
872                                 type = SOCKNAL_CONN_BULK_OUT;
873                                 break;
874
875                         case 'C':
876                                 if (type != SOCKNAL_CONN_ANY) {
877                                         fprintf(stderr, "Can't flag type twice\n");
878                                         return -1;
879                                 }
880                                 type = SOCKNAL_CONN_CONTROL;
881                                 break;
882                                 
883                         default:
884                                 fprintf (stderr, "unrecognised flag '%c'\n",
885                                          *flag);
886                                 return (-1);
887                         }
888
889         memset(&srvaddr, 0, sizeof(srvaddr));
890         srvaddr.sin_family = AF_INET;
891         srvaddr.sin_port = htons(port);
892         srvaddr.sin_addr.s_addr = htonl(ipaddr);
893
894         fd = socket(PF_INET, SOCK_STREAM, 0);
895         if ( fd < 0 ) {
896                 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
897                 return -1;
898         }
899
900         rc = connect(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
901         if ( rc == -1 ) { 
902                 fprintf(stderr, "connect() failed: %s\n", strerror(errno));
903                 return -1;
904         }
905
906         printf("Connected host: %s type: %s\n", 
907                argv[1],
908                (type == SOCKNAL_CONN_ANY) ? "A" :
909                (type == SOCKNAL_CONN_CONTROL) ? "C" :
910                (type == SOCKNAL_CONN_BULK_IN) ? "I" :
911                (type == SOCKNAL_CONN_BULK_OUT) ? "O" : "?");
912
913         PCFG_INIT(pcfg, NAL_CMD_REGISTER_PEER_FD);
914         pcfg.pcfg_nal = g_nal;
915         pcfg.pcfg_fd = fd;
916         pcfg.pcfg_misc = type;
917         
918         rc = pcfg_ioctl(&pcfg);
919         if (rc) {
920                 fprintf(stderr, "failed to register fd with portals: %s\n", 
921                         strerror(errno));
922                 close (fd);
923                 return -1;
924         }
925
926         printf("Connection to %s registered with socknal\n", argv[1]);
927
928         rc = close(fd);
929         if (rc)
930                 fprintf(stderr, "close failed: %d\n", rc);
931
932         return 0;
933 }
934
935 int jt_ptl_disconnect(int argc, char **argv)
936 {
937         struct portals_cfg       pcfg;
938         ptl_nid_t                nid = PTL_NID_ANY;
939         __u32                    ipaddr = 0;
940         int                      rc;
941
942         if (argc > 3) {
943                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
944                 return 0;
945         }
946
947         if (!g_nal_is_compatible (NULL, SOCKNAL, OPENIBNAL, 0))
948                 return 0;
949
950         if (argc >= 2 &&
951             ptl_parse_nid (&nid, argv[1]) != 0) {
952                 fprintf (stderr, "Can't parse nid %s\n", argv[1]);
953                 return -1;
954         }
955
956         if (g_nal_is_compatible (NULL, SOCKNAL, 0) &&
957             argc >= 3 &&
958             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
959                 fprintf (stderr, "Can't parse ip addr %s\n", argv[2]);
960                 return -1;
961         }
962
963         PCFG_INIT(pcfg, NAL_CMD_CLOSE_CONNECTION);
964         pcfg.pcfg_nid     = nid;
965         pcfg.pcfg_id      = ipaddr;
966         
967         rc = pcfg_ioctl(&pcfg);
968         if (rc) {
969                 fprintf(stderr, "failed to remove connection: %s\n",
970                         strerror(errno));
971                 return -1;
972         }
973
974         return 0;
975 }
976
977 int jt_ptl_push_connection (int argc, char **argv)
978 {
979         struct portals_cfg       pcfg;
980         int                      rc;
981         ptl_nid_t                nid = PTL_NID_ANY;
982         __u32                    ipaddr = 0;
983
984         if (argc > 3) {
985                 fprintf(stderr, "usage: %s [nid] [ip]\n", argv[0]);
986                 return 0;
987         }
988
989         if (!g_nal_is_compatible (argv[0], SOCKNAL, 0))
990                 return -1;
991         
992         if (argc > 1 &&
993             ptl_parse_nid (&nid, argv[1]) != 0) {
994                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
995                 return -1;
996         }
997                         
998         if (argc > 2 &&
999             ptl_parse_ipaddr (&ipaddr, argv[2]) != 0) {
1000                 fprintf(stderr, "Can't parse ipaddr: %s\n", argv[2]);
1001         }
1002
1003         PCFG_INIT(pcfg, NAL_CMD_PUSH_CONNECTION);
1004         pcfg.pcfg_nid     = nid;
1005         pcfg.pcfg_id      = ipaddr;
1006         
1007         rc = pcfg_ioctl(&pcfg);
1008         if (rc) {
1009                 fprintf(stderr, "failed to push connection: %s\n",
1010                         strerror(errno));
1011                 return -1;
1012         }
1013
1014         return 0;
1015 }
1016
1017 int 
1018 jt_ptl_print_active_txs (int argc, char **argv)
1019 {
1020         struct portals_cfg       pcfg;
1021         int                      index;
1022         int                      rc;
1023
1024         if (!g_nal_is_compatible (argv[0], QSWNAL, 0))
1025                 return -1;
1026
1027         for (index = 0;;index++) {
1028                 PCFG_INIT(pcfg, NAL_CMD_GET_TXDESC);
1029                 pcfg.pcfg_count   = index;
1030         
1031                 rc = pcfg_ioctl(&pcfg);
1032                 if (rc != 0)
1033                         break;
1034
1035                 printf ("%p: %5s payload %6d bytes to "LPX64" via "LPX64" by pid %6d: %s, %s, state %d\n",
1036                         pcfg.pcfg_pbuf1,
1037                         pcfg.pcfg_count == PTL_MSG_ACK ? "ACK" :
1038                         pcfg.pcfg_count == PTL_MSG_PUT ? "PUT" :
1039                         pcfg.pcfg_count == PTL_MSG_GET ? "GET" :
1040                         pcfg.pcfg_count == PTL_MSG_REPLY ? "REPLY" : "<wierd message>",
1041                         pcfg.pcfg_size,
1042                         pcfg.pcfg_nid,
1043                         pcfg.pcfg_nid2,
1044                         pcfg.pcfg_misc,
1045                         (pcfg.pcfg_flags & 1) ? "delayed" : "immediate",
1046                         (pcfg.pcfg_flags & 2) ? "nblk"    : "normal",
1047                         pcfg.pcfg_flags >> 2);
1048         }
1049
1050         if (index == 0)
1051                 printf ("<no active descs>\n");
1052         return 0;
1053 }
1054
1055 int jt_ptl_ping(int argc, char **argv)
1056 {
1057         int       rc;
1058         ptl_nid_t nid;
1059         long      count   = 1;
1060         long      size    = 4;
1061         long      timeout = 1;
1062         struct portal_ioctl_data data;
1063
1064         if (argc < 2) {
1065                 fprintf(stderr, "usage: %s nid [count] [size] [timeout (secs)]\n", argv[0]);
1066                 return 0;
1067         }
1068
1069         if (!g_nal_is_set())
1070                 return -1;
1071
1072         if (ptl_parse_nid (&nid, argv[1]) != 0)
1073         {
1074                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1075                 return (-1);
1076         }
1077         
1078         if (argc > 2)
1079         {
1080                 count = atol(argv[2]);
1081
1082                 if (count < 0 || count > 20000) 
1083                 {
1084                         fprintf(stderr, "are you insane?  %ld is a crazy count.\n", count);
1085                         return -1;
1086                 }
1087         }
1088         
1089         if (argc > 3)
1090                 size= atol(argv[3]);
1091
1092         if (argc > 4)
1093                 timeout = atol (argv[4]);
1094         
1095         PORTAL_IOC_INIT (data);
1096         data.ioc_count   = count;
1097         data.ioc_size    = size;
1098         data.ioc_nid     = nid;
1099         data.ioc_nal     = g_nal;
1100         data.ioc_timeout = timeout;
1101         
1102         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_PING, &data);
1103         if (rc) {
1104                 fprintf(stderr, "failed to start pinger: %s\n",
1105                         strerror(errno));
1106                 return -1;
1107         }
1108         return 0;
1109 }
1110
1111 int jt_ptl_shownid(int argc, char **argv)
1112 {
1113         struct portal_ioctl_data data;
1114         int                      rc;
1115         
1116         if (argc > 1) {
1117                 fprintf(stderr, "usage: %s\n", argv[0]);
1118                 return 0;
1119         }
1120         
1121         if (!g_nal_is_set())
1122                 return -1;
1123
1124         PORTAL_IOC_INIT (data);
1125         data.ioc_nal = g_nal;
1126         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_GET_NID, &data);
1127         if (rc < 0)
1128                 fprintf(stderr, "getting my NID failed: %s\n",
1129                         strerror (errno));
1130         else
1131                 printf(LPX64"\n", data.ioc_nid);
1132         return 0;
1133 }
1134
1135 int jt_ptl_mynid(int argc, char **argv)
1136 {
1137         int rc;
1138         char hostname[1024];
1139         char *nidstr;
1140         struct portals_cfg pcfg;
1141         ptl_nid_t mynid;
1142
1143         if (argc > 2) {
1144                 fprintf(stderr, "usage: %s [NID]\n", argv[0]);
1145                 fprintf(stderr, "NID defaults to the primary IP address of the machine.\n");
1146                 return 0;
1147         }
1148
1149         if (!g_nal_is_set())
1150                 return -1;
1151
1152         if (argc >= 2)
1153                 nidstr = argv[1];
1154         else if (gethostname(hostname, sizeof(hostname)) != 0) {
1155                 fprintf(stderr, "gethostname failed: %s\n",
1156                         strerror(errno));
1157                 return -1;
1158         }
1159         else
1160                 nidstr = hostname;
1161
1162         rc = ptl_parse_nid (&mynid, nidstr);
1163         if (rc != 0) {
1164                 fprintf (stderr, "Can't convert '%s' into a NID\n", nidstr);
1165                 return -1;
1166         }
1167         
1168         PCFG_INIT(pcfg, NAL_CMD_REGISTER_MYNID);
1169         pcfg.pcfg_nid = mynid;
1170
1171         rc = pcfg_ioctl(&pcfg);
1172         if (rc < 0)
1173                 fprintf(stderr, "setting my NID failed: %s\n",
1174                        strerror(errno));
1175         else
1176                 printf("registered my nid "LPX64" (%s)\n", 
1177                        ptl_nid2u64(mynid), hostname);
1178         return 0;
1179 }
1180
1181 int
1182 jt_ptl_fail_nid (int argc, char **argv)
1183 {
1184         int                      rc;
1185         ptl_nid_t                nid;
1186         unsigned int             threshold;
1187         struct portal_ioctl_data data;
1188
1189         if (argc < 2 || argc > 3)
1190         {
1191                 fprintf (stderr, "usage: %s nid|\"_all_\" [count (0 == mend)]\n", argv[0]);
1192                 return (0);
1193         }
1194         
1195         if (!g_nal_is_set())
1196                 return (-1);
1197
1198         if (!strcmp (argv[1], "_all_"))
1199                 nid = PTL_NID_ANY;
1200         else if (ptl_parse_nid (&nid, argv[1]) != 0)
1201         {
1202                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1203                 return (-1);
1204         }
1205
1206         if (argc < 3)
1207                 threshold = PTL_MD_THRESH_INF;
1208         else if (sscanf (argv[2], "%i", &threshold) != 1) {
1209                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
1210                 return (-1);
1211         }
1212         
1213         PORTAL_IOC_INIT (data);
1214         data.ioc_nal = g_nal;
1215         data.ioc_nid = nid;
1216         data.ioc_count = threshold;
1217         
1218         rc = l_ioctl (PORTALS_DEV_ID, IOC_PORTAL_FAIL_NID, &data);
1219         if (rc < 0)
1220                 fprintf (stderr, "IOC_PORTAL_FAIL_NID failed: %s\n",
1221                          strerror (errno));
1222         else
1223                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1224         
1225         return (0);
1226 }
1227
1228 int
1229 jt_ptl_add_route (int argc, char **argv)
1230 {
1231         struct portals_cfg       pcfg;
1232         ptl_nid_t                nid1;
1233         ptl_nid_t                nid2;
1234         ptl_nid_t                gateway_nid;
1235         int                      rc;
1236         
1237         if (argc < 3)
1238         {
1239                 fprintf (stderr, "usage: %s gateway target [target]\n", argv[0]);
1240                 return (0);
1241         }
1242
1243         if (!g_nal_is_set())
1244                 return (-1);
1245
1246         if (ptl_parse_nid (&gateway_nid, argv[1]) != 0)
1247         {
1248                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1249                 return (-1);
1250         }
1251
1252         if (ptl_parse_nid (&nid1, argv[2]) != 0)
1253         {
1254                 fprintf (stderr, "Can't parse first target NID \"%s\"\n", argv[2]);
1255                 return (-1);
1256         }
1257
1258         if (argc < 4)
1259                 nid2 = nid1;
1260         else if (ptl_parse_nid (&nid2, argv[3]) != 0)
1261         {
1262                 fprintf (stderr, "Can't parse second target NID \"%s\"\n", argv[4]);
1263                 return (-1);
1264         }
1265
1266         PCFG_INIT(pcfg, NAL_CMD_ADD_ROUTE);
1267         pcfg.pcfg_nid = gateway_nid;
1268         pcfg.pcfg_nal = ROUTER;
1269         pcfg.pcfg_gw_nal = g_nal;
1270         pcfg.pcfg_nid2 = MIN (nid1, nid2);
1271         pcfg.pcfg_nid3 = MAX (nid1, nid2);
1272
1273         rc = pcfg_ioctl(&pcfg);
1274         if (rc != 0) 
1275         {
1276                 fprintf (stderr, "NAL_CMD_ADD_ROUTE failed: %s\n", strerror (errno));
1277                 return (-1);
1278         }
1279         
1280         return (0);
1281 }
1282
1283 int
1284 jt_ptl_del_route (int argc, char **argv)
1285 {
1286         struct portals_cfg       pcfg;
1287         ptl_nid_t                nid;
1288         ptl_nid_t                nid1 = PTL_NID_ANY;
1289         ptl_nid_t                nid2 = PTL_NID_ANY;
1290         int                      rc;
1291         
1292         if (argc < 2)
1293         {
1294                 fprintf (stderr, "usage: %s targetNID\n", argv[0]);
1295                 return (0);
1296         }
1297
1298         if (!g_nal_is_set())
1299                 return (-1);
1300
1301         if (ptl_parse_nid (&nid, argv[1]) != 0)
1302         {
1303                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1304                 return (-1);
1305         }
1306
1307         if (argc >= 3 &&
1308             ptl_parse_nid (&nid1, argv[2]) != 0)
1309         {
1310                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[2]);
1311                 return (-1);
1312         }
1313
1314         if (argc < 4) {
1315                 nid2 = nid1;
1316         } else {
1317                 if (ptl_parse_nid (&nid2, argv[3]) != 0) {
1318                         fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[3]);
1319                         return (-1);
1320                 }
1321
1322                 if (nid1 > nid2) {
1323                         ptl_nid_t tmp = nid1;
1324                         
1325                         nid1 = nid2;
1326                         nid2 = tmp;
1327                 }
1328         }
1329         
1330         PCFG_INIT(pcfg, NAL_CMD_DEL_ROUTE);
1331         pcfg.pcfg_nal = ROUTER;
1332         pcfg.pcfg_gw_nal = g_nal;
1333         pcfg.pcfg_nid = nid;
1334         pcfg.pcfg_nid2 = nid1;
1335         pcfg.pcfg_nid3 = nid2;
1336
1337         rc = pcfg_ioctl(&pcfg);
1338         if (rc != 0) 
1339         {
1340                 fprintf (stderr, "NAL_CMD_DEL_ROUTE ("LPX64") failed: %s\n", 
1341                          ptl_nid2u64(nid), strerror (errno));
1342                 return (-1);
1343         }
1344         
1345         return (0);
1346 }
1347
1348 int
1349 jt_ptl_notify_router (int argc, char **argv)
1350 {
1351         struct portals_cfg       pcfg;
1352         int                      enable;
1353         ptl_nid_t                nid;
1354         int                      rc;
1355         struct timeval           now;
1356         time_t                   when;
1357
1358         if (argc < 3)
1359         {
1360                 fprintf (stderr, "usage: %s targetNID <up/down> [<time>]\n", 
1361                          argv[0]);
1362                 return (0);
1363         }
1364
1365         if (ptl_parse_nid (&nid, argv[1]) != 0)
1366         {
1367                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1368                 return (-1);
1369         }
1370
1371         if (ptl_parse_bool (&enable, argv[2]) != 0) {
1372                 fprintf (stderr, "Can't parse boolean %s\n", argv[2]);
1373                 return (-1);
1374         }
1375
1376         gettimeofday(&now, NULL);
1377         
1378         if (argc < 4) {
1379                 when = now.tv_sec;
1380         } else if (ptl_parse_time (&when, argv[3]) != 0) {
1381                 fprintf(stderr, "Can't parse time %s\n"
1382                         "Please specify either 'YYYY-MM-DD-HH:MM:SS'\n"
1383                         "or an absolute unix time in seconds\n", argv[3]);
1384                 return (-1);
1385         } else if (when > now.tv_sec) {
1386                 fprintf (stderr, "%s specifies a time in the future\n",
1387                          argv[3]);
1388                 return (-1);
1389         }
1390
1391         PCFG_INIT(pcfg, NAL_CMD_NOTIFY_ROUTER);
1392         pcfg.pcfg_nal = ROUTER;
1393         pcfg.pcfg_gw_nal = g_nal;
1394         pcfg.pcfg_nid = nid;
1395         pcfg.pcfg_flags = enable;
1396         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
1397         pcfg.pcfg_nid3 = (__u64)when;
1398         
1399         rc = pcfg_ioctl(&pcfg);
1400         if (rc != 0) 
1401         {
1402                 fprintf (stderr, "NAL_CMD_NOTIFY_ROUTER ("LPX64") failed: %s\n",
1403                          ptl_nid2u64(nid), strerror (errno));
1404                 return (-1);
1405         }
1406         
1407         return (0);
1408 }
1409
1410 int
1411 jt_ptl_print_routes (int argc, char **argv)
1412 {
1413         char                      buffer[3][128];
1414         struct portals_cfg        pcfg;
1415         int                       rc;
1416         int                       index;
1417         int                       gateway_nal;
1418         ptl_nid_t                 gateway_nid;
1419         ptl_nid_t                 nid1;
1420         ptl_nid_t                 nid2;
1421         int                       alive;
1422
1423         for (index = 0;;index++)
1424         {
1425                 PCFG_INIT(pcfg, NAL_CMD_GET_ROUTE);
1426                 pcfg.pcfg_nal = ROUTER;
1427                 pcfg.pcfg_count = index;
1428                 
1429                 rc = pcfg_ioctl(&pcfg);
1430                 if (rc != 0)
1431                         break;
1432
1433                 gateway_nal = pcfg.pcfg_gw_nal;
1434                 gateway_nid = pcfg.pcfg_nid;
1435                 nid1 = pcfg.pcfg_nid2;
1436                 nid2 = pcfg.pcfg_nid3;
1437                 alive = pcfg.pcfg_flags;
1438
1439                 printf ("%8s %18s : %s - %s, %s\n", 
1440                         nal2name (gateway_nal), 
1441                         ptl_nid2str (buffer[0], gateway_nid),
1442                         ptl_nid2str (buffer[1], nid1),
1443                         ptl_nid2str (buffer[2], nid2),
1444                         alive ? "up" : "down");
1445         }
1446         return (0);
1447 }
1448
1449 static int
1450 lwt_control(int enable, int clear)
1451 {
1452         struct portal_ioctl_data data;
1453         int                      rc;
1454
1455         PORTAL_IOC_INIT(data);
1456         data.ioc_flags = enable;
1457         data.ioc_misc = clear;
1458
1459         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_CONTROL, &data);
1460         if (rc == 0)
1461                 return (0);
1462
1463         fprintf(stderr, "IOC_PORTAL_LWT_CONTROL failed: %s\n",
1464                 strerror(errno));
1465         return (-1);
1466 }
1467
1468 static int
1469 lwt_snapshot(cycles_t *now, int *ncpu, int *totalsize, 
1470              lwt_event_t *events, int size)
1471 {
1472         struct portal_ioctl_data data;
1473         int                      rc;
1474
1475         PORTAL_IOC_INIT(data);
1476         data.ioc_pbuf1 = (char *)events;
1477         data.ioc_plen1 = size;
1478
1479         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_LWT_SNAPSHOT, &data);
1480         if (rc != 0) {
1481                 fprintf(stderr, "IOC_PORTAL_LWT_SNAPSHOT failed: %s\n",
1482                         strerror(errno));
1483                 return (-1);
1484         }
1485
1486         /* crappy overloads */
1487         if (data.ioc_nid != sizeof(lwt_event_t) ||
1488             data.ioc_nid2 != offsetof(lwt_event_t, lwte_where)) {
1489                 fprintf(stderr,"kernel/user LWT event mismatch %d(%d),%d(%d)\n",
1490                         (int)data.ioc_nid, sizeof(lwt_event_t),
1491                         (int)data.ioc_nid2,
1492                         (int)offsetof(lwt_event_t, lwte_where));
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           *where = lwt_get_string(e->lwte_where);
1570
1571         if (where == NULL)
1572                 return (-1);
1573
1574         fprintf(f, "%#010lx %#010lx %#010lx %#010lx: %#010lx %1d %10.6f %10.2f %s\n",
1575                 e->lwte_p1, e->lwte_p2, e->lwte_p3, e->lwte_p4,
1576                 (long)e->lwte_task, cpu, (e->lwte_when - t0) / (mhz * 1000000.0),
1577                 (t0 == e->lwte_when) ? 0.0 : (e->lwte_when - tlast) / mhz,
1578                 where);
1579
1580         lwt_put_string(where);
1581
1582         return (0);
1583 }
1584
1585 double
1586 get_cycles_per_usec ()
1587 {
1588         FILE      *f = fopen ("/proc/cpuinfo", "r");
1589         double     mhz;
1590         char      line[64];
1591         
1592         if (f != NULL) {
1593                 while (fgets (line, sizeof (line), f) != NULL)
1594                         if (sscanf (line, "cpu MHz : %lf", &mhz) == 1) {
1595                                 fclose (f);
1596                                 return (mhz);
1597                         }
1598                 fclose (f);
1599         }
1600
1601         fprintf (stderr, "Can't read/parse /proc/cpuinfo\n");
1602         return (1000.0);
1603 }
1604
1605 int
1606 jt_ptl_lwt(int argc, char **argv)
1607 {
1608         const int       lwt_max_cpus = 32;
1609         int             ncpus;
1610         int             totalspace;
1611         int             nevents_per_cpu;
1612         lwt_event_t    *events;
1613         lwt_event_t    *cpu_event[lwt_max_cpus + 1];
1614         lwt_event_t    *next_event[lwt_max_cpus];
1615         lwt_event_t    *first_event[lwt_max_cpus];
1616         int             cpu;
1617         lwt_event_t    *e;
1618         int             rc;
1619         int             i;
1620         double          mhz;
1621         cycles_t        t0;
1622         cycles_t        tlast;
1623         cycles_t        tnow;
1624         struct timeval  tvnow;
1625         int             printed_date = 0;
1626         int             nlines = 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                         if (++nlines % 10000 == 0 && f != stdout) {
1778                                 /* show some activity... */
1779                                 printf(".");
1780                                 fflush (stdout);
1781                         }
1782                 }
1783
1784                 tlast = next_event[cpu]->lwte_when;
1785                 
1786                 next_event[cpu]++;
1787                 if (next_event[cpu] == cpu_event[cpu + 1])
1788                         next_event[cpu] = cpu_event[cpu];
1789
1790                 if (next_event[cpu]->lwte_where == NULL ||
1791                     next_event[cpu] == first_event[cpu])
1792                         next_event[cpu] = NULL;
1793         }
1794
1795         if (f != stdout) {
1796                 printf("\n");
1797                 fclose(f);
1798         }
1799
1800         free(events);
1801         return (0);
1802 }
1803
1804 int jt_ptl_memhog(int argc, char **argv)
1805 {
1806         static int                gfp = 0;        /* sticky! */
1807
1808         struct portal_ioctl_data  data;
1809         int                       rc;
1810         int                       count;
1811         char                     *end;
1812         
1813         if (argc < 2)  {
1814                 fprintf(stderr, "usage: %s <npages> [<GFP flags>]\n", argv[0]);
1815                 return 0;
1816         }
1817
1818         count = strtol(argv[1], &end, 0);
1819         if (count < 0 || *end != 0) {
1820                 fprintf(stderr, "Can't parse page count '%s'\n", argv[1]);
1821                 return -1;
1822         }
1823
1824         if (argc >= 3) {
1825                 rc = strtol(argv[2], &end, 0);
1826                 if (*end != 0) {
1827                         fprintf(stderr, "Can't parse gfp flags '%s'\n", argv[2]);
1828                         return -1;
1829                 }
1830                 gfp = rc;
1831         }
1832         
1833         PORTAL_IOC_INIT(data);
1834         data.ioc_count = count;
1835         data.ioc_flags = gfp;
1836         rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_MEMHOG, &data);
1837
1838         if (rc != 0) {
1839                 fprintf(stderr, "memhog %d failed: %s\n", count, strerror(errno));
1840                 return -1;
1841         }
1842         
1843         printf("memhog %d OK\n", count);
1844         return 0;
1845 }
1846