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