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