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