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