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