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