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