Whamcloud - gitweb
LU-4629 libcfs: fix buffer overflow of string buffer
[fs/lustre-release.git] / lnet / utils / portals.c
1 /*
2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3  *
4  *   This file is part of Portals, http://www.sf.net/projects/lustre/
5  *
6  *   Portals is free software; you can redistribute it and/or
7  *   modify it under the terms of version 2 of the GNU General Public
8  *   License as published by the Free Software Foundation.
9  *
10  *   Portals is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with Portals; if not, write to the Free Software
17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  */
20
21 #include <libcfs/libcfsutil.h>
22 #include <lnet/api-support.h>
23 #include <lnet/lnetctl.h>
24 #include <lnet/socklnd.h>
25
26 unsigned int libcfs_debug;
27 unsigned int libcfs_printk = D_CANTMASK;
28
29 static int   g_net_set;
30 static __u32 g_net;
31
32 /* Convert a string boolean to an int; "enable" -> 1 */
33 int
34 lnet_parse_bool (int *b, char *str)
35 {
36         if (!strcasecmp (str, "no") ||
37             !strcasecmp (str, "n") ||
38             !strcasecmp (str, "off") ||
39             !strcasecmp (str, "down") ||
40             !strcasecmp (str, "disable"))
41         {
42                 *b = 0;
43                 return (0);
44         }
45
46         if (!strcasecmp (str, "yes") ||
47             !strcasecmp (str, "y") ||
48             !strcasecmp (str, "on") ||
49             !strcasecmp (str, "up") ||
50             !strcasecmp (str, "enable"))
51         {
52                 *b = 1;
53                 return (0);
54         }
55
56         return (-1);
57 }
58
59 int
60 lnet_parse_port (int *port, char *str)
61 {
62         char      *end;
63
64         *port = strtol (str, &end, 0);
65
66         if (*end == 0 &&                        /* parsed whole string */
67             *port > 0 && *port < 65536)         /* minimal sanity check */
68                 return (0);
69
70         return (-1);
71 }
72
73 #ifdef HAVE_GETHOSTBYNAME
74 static struct hostent *
75 ptl_gethostbyname(char * hname) {
76         struct hostent *he;
77         he = gethostbyname(hname);
78         if (!he) {
79                 switch(h_errno) {
80                 case HOST_NOT_FOUND:
81                 case NO_ADDRESS:
82                         fprintf(stderr, "Unable to resolve hostname: %s\n",
83                                 hname);
84                         break;
85                 default:
86                         fprintf(stderr, "gethostbyname error for %s: %s\n",
87                                 hname, strerror(h_errno));
88                         break;
89                 }
90                 return NULL;
91         }
92         return he;
93 }
94 #endif
95
96 int
97 lnet_parse_ipquad (__u32 *ipaddrp, char *str)
98 {
99         int             a;
100         int             b;
101         int             c;
102         int             d;
103
104         if (sscanf (str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
105             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
106             (c & ~0xff) == 0 && (d & ~0xff) == 0)
107         {
108                 *ipaddrp = (a<<24)|(b<<16)|(c<<8)|d;
109                 return (0);
110         }
111
112         return (-1);
113 }
114
115 int
116 lnet_parse_ipaddr (__u32 *ipaddrp, char *str)
117 {
118 #ifdef HAVE_GETHOSTBYNAME
119         struct hostent *he;
120 #endif
121
122         if (!strcmp (str, "_all_")) {
123                 *ipaddrp = 0;
124                 return (0);
125         }
126
127         if (lnet_parse_ipquad(ipaddrp, str) == 0)
128                 return (0);
129
130 #ifdef HAVE_GETHOSTBYNAME
131         if ((('a' <= str[0] && str[0] <= 'z') ||
132              ('A' <= str[0] && str[0] <= 'Z')) &&
133              (he = ptl_gethostbyname (str)) != NULL) {
134                 __u32 addr = *(__u32 *)he->h_addr;
135
136                 *ipaddrp = ntohl(addr);         /* HOST byte order */
137                 return (0);
138         }
139 #endif
140
141         return (-1);
142 }
143
144 char *
145 ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup)
146 {
147 #ifdef HAVE_GETHOSTBYNAME
148         __u32           net_ip;
149         struct hostent *he;
150
151         if (lookup) {
152                 net_ip = htonl (ipaddr);
153                 he = gethostbyaddr (&net_ip, sizeof (net_ip), AF_INET);
154                 if (he != NULL) {
155                         strlcpy(str, he->h_name, strsize);
156                         return (str);
157                 }
158         }
159 #endif
160
161         sprintf (str, "%d.%d.%d.%d",
162                  (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
163                  (ipaddr >> 8) & 0xff, ipaddr & 0xff);
164         return (str);
165 }
166
167 int
168 lnet_parse_time (time_t *t, char *str)
169 {
170         char          *end;
171         int            n;
172         struct tm      tm;
173
174         *t = strtol (str, &end, 0);
175         if (*end == 0) /* parsed whole string */
176                 return (0);
177
178         memset (&tm, 0, sizeof (tm));
179         n = sscanf (str, "%d-%d-%d-%d:%d:%d",
180                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
181                     &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
182         if (n != 6)
183                 return (-1);
184
185         tm.tm_mon--;                    /* convert to 0 == Jan */
186         tm.tm_year -= 1900;             /* y2k quirk */
187         tm.tm_isdst = -1;               /* dunno if it's daylight savings... */
188
189         *t = mktime (&tm);
190         if (*t == (time_t)-1)
191                 return (-1);
192
193         return (0);
194 }
195
196 int
197 lnet_parse_nid(char *nid_str, lnet_process_id_t *id_ptr)
198 {
199         id_ptr->pid = LNET_PID_ANY;
200         id_ptr->nid = libcfs_str2nid(nid_str);
201         if (id_ptr->nid == LNET_NID_ANY) {
202                 fprintf (stderr, "Can't parse nid \"%s\"\n", nid_str);
203                 return -1;
204         }
205
206         return 0;
207 }
208
209 int g_net_is_set (char *cmd)
210 {
211         if (g_net_set)
212                 return 1;
213
214         if (cmd != NULL)
215                 fprintf(stderr,
216                         "You must run the 'network' command before '%s'.\n",
217                         cmd);
218         return 0;
219 }
220
221 int g_net_is_compatible (char *cmd, ...)
222 {
223         va_list       ap;
224         int           nal;
225
226         if (!g_net_is_set(cmd))
227                 return 0;
228
229         va_start(ap, cmd);
230
231         do {
232                 nal = va_arg (ap, int);
233                 if (nal == LNET_NETTYP(g_net)) {
234                         va_end (ap);
235                         return 1;
236                 }
237         } while (nal != 0);
238
239         va_end (ap);
240
241         if (cmd != NULL)
242                 fprintf (stderr,
243                          "Command %s not compatible with %s NAL\n",
244                          cmd,
245                          libcfs_lnd2str(LNET_NETTYP(g_net)));
246         return 0;
247 }
248
249 int ptl_initialize(int argc, char **argv)
250 {
251         register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH,
252                          LNET_DEV_MAJOR, LNET_DEV_MINOR);
253         return 0;
254 }
255
256
257 int jt_ptl_network(int argc, char **argv)
258 {
259         struct libcfs_ioctl_data data;
260         __u32                    net = LNET_NIDNET(LNET_NID_ANY);
261         int                      rc;
262
263         if (argc < 2) {
264                 fprintf(stderr, "usage: %s <net>|up|down\n", argv[0]);
265                 return 0;
266         }
267
268         if (!strcmp(argv[1], "unconfigure") ||
269             !strcmp(argv[1], "down")) {
270                 LIBCFS_IOC_INIT(data);
271                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_UNCONFIGURE, &data);
272
273                 if (rc == 0) {
274                         printf ("LNET ready to unload\n");
275                         return 0;
276                 }
277
278                 if (errno == EBUSY)
279                         fprintf(stderr, "LNET busy\n");
280                 else
281                         fprintf(stderr, "LNET unconfigure error %d: %s\n",
282                                 errno, strerror(errno));
283                 return -1;
284         }
285
286         if (!strcmp(argv[1], "configure") ||
287             !strcmp(argv[1], "up")) {
288                 LIBCFS_IOC_INIT(data);
289                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIGURE, &data);
290
291                 if (rc == 0) {
292                         printf ("LNET configured\n");
293                         return 0;
294                 }
295
296                 fprintf(stderr, "LNET configure error %d: %s\n",
297                         errno, strerror(errno));
298                 return -1;
299         }
300
301         net = libcfs_str2net(argv[1]);
302         if (net == LNET_NIDNET(LNET_NID_ANY)) {
303                 fprintf(stderr, "Can't parse net %s\n", argv[1]);
304                 return -1;
305         }
306
307         if (LNET_NETTYP(net) == CIBLND    ||
308             LNET_NETTYP(net) == OPENIBLND ||
309             LNET_NETTYP(net) == IIBLND    ||
310             LNET_NETTYP(net) == VIBLND) {
311                 fprintf(stderr, "Net %s obsoleted\n", libcfs_lnd2str(net));
312                 return -1;
313         }
314
315         g_net_set = 1;
316         g_net = net;
317         return 0;
318 }
319
320 int
321 jt_ptl_list_nids(int argc, char **argv)
322 {
323         struct libcfs_ioctl_data data;
324         int                      all = 0, return_nid = 0;
325         int                      count;
326         int                      rc;
327
328         all = (argc == 2) && (strcmp(argv[1], "all") == 0);
329         /* Hack to pass back value */
330         return_nid = (argc == 2) && (argv[1][0] == 1);
331
332         if ((argc > 2) && !(all || return_nid)) {
333                 fprintf(stderr, "usage: %s [all]\n", argv[0]);
334                 return 0;
335         }
336
337         for (count = 0;; count++) {
338                 LIBCFS_IOC_INIT (data);
339                 data.ioc_count = count;
340                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NI, &data);
341
342                 if (rc < 0) {
343                         if ((count > 0) && (errno == ENOENT))
344                                 /* We found them all */
345                                 break;
346                         fprintf(stderr,"IOC_LIBCFS_GET_NI error %d: %s\n",
347                                 errno, strerror(errno));
348                         return -1;
349                 }
350
351                 if (all || (LNET_NETTYP(LNET_NIDNET(data.ioc_nid)) != LOLND)) {
352                         printf("%s\n", libcfs_nid2str(data.ioc_nid));
353                         if (return_nid) {
354                                 *(__u64 *)(argv[1]) = data.ioc_nid;
355                                 return_nid--;
356                         }
357                 }
358         }
359
360         return 0;
361 }
362
363 int
364 jt_ptl_which_nid (int argc, char **argv)
365 {
366         struct libcfs_ioctl_data data;
367         int          best_dist = 0;
368         int          best_order = 0;
369         lnet_nid_t   best_nid = LNET_NID_ANY;
370         int          dist;
371         int          order;
372         lnet_nid_t   nid;
373         char        *nidstr;
374         int          rc;
375         int          i;
376
377         if (argc < 2) {
378                 fprintf(stderr, "usage: %s NID [NID...]\n", argv[0]);
379                 return 0;
380         }
381
382         for (i = 1; i < argc; i++) {
383                 nidstr = argv[i];
384                 nid = libcfs_str2nid(nidstr);
385                 if (nid == LNET_NID_ANY) {
386                         fprintf(stderr, "Can't parse NID %s\n", nidstr);
387                         return -1;
388                 }
389
390                 LIBCFS_IOC_INIT(data);
391                 data.ioc_nid = nid;
392
393                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_DIST, &data);
394                 if (rc != 0) {
395                         fprintf(stderr, "Can't get distance to %s: %s\n",
396                                 nidstr, strerror(errno));
397                         return -1;
398                 }
399
400                 dist = data.ioc_u32[0];
401                 order = data.ioc_u32[1];
402
403                 if (dist < 0) {
404                         if (dist == -EHOSTUNREACH)
405                                 continue;
406
407                         fprintf(stderr, "Unexpected distance to %s: %d\n",
408                                 nidstr, dist);
409                         return -1;
410                 }
411
412                 if (best_nid == LNET_NID_ANY ||
413                     dist < best_dist ||
414                     (dist == best_dist && order < best_order)) {
415                         best_dist = dist;
416                         best_order = order;
417                         best_nid = nid;
418                 }
419         }
420
421         if (best_nid == LNET_NID_ANY) {
422                 fprintf(stderr, "No reachable NID\n");
423                 return -1;
424         }
425
426         printf("%s\n", libcfs_nid2str(best_nid));
427         return 0;
428 }
429
430 int
431 jt_ptl_print_interfaces (int argc, char **argv)
432 {
433         struct libcfs_ioctl_data data;
434         char                     buffer[3][HOST_NAME_MAX + 1];
435         int                      index;
436         int                      rc;
437
438         if (!g_net_is_compatible (argv[0], SOCKLND, 0))
439                 return -1;
440
441         for (index = 0;;index++) {
442                 LIBCFS_IOC_INIT(data);
443                 data.ioc_net   = g_net;
444                 data.ioc_count = index;
445
446                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_INTERFACE, &data);
447                 if (rc != 0)
448                         break;
449
450                 printf ("%s: (%s/%s) npeer %d nroute %d\n",
451                         ptl_ipaddr_2_str(data.ioc_u32[0], buffer[2],
452                                          sizeof(buffer[2]), 1),
453                         ptl_ipaddr_2_str(data.ioc_u32[0], buffer[0],
454                                          sizeof(buffer[0]), 0),
455                         ptl_ipaddr_2_str(data.ioc_u32[1], buffer[1],
456                                          sizeof(buffer[1]), 0),
457                         data.ioc_u32[2], data.ioc_u32[3]);
458         }
459
460         if (index == 0) {
461                 if (errno == ENOENT) {
462                         printf ("<no interfaces>\n");
463                 } else {
464                         fprintf(stderr, "Error getting interfaces: %s: "
465                                 "check dmesg.\n",
466                                 strerror(errno));
467                 }
468         }
469
470         return 0;
471 }
472
473 int
474 jt_ptl_add_interface (int argc, char **argv)
475 {
476         struct libcfs_ioctl_data data;
477         __u32                    ipaddr;
478         int                      rc;
479         __u32                    netmask = 0xffffff00;
480         int                      i;
481         int                      count;
482         char                    *end;
483
484         if (argc < 2 || argc > 3) {
485                 fprintf (stderr, "usage: %s ipaddr [netmask]\n", argv[0]);
486                 return 0;
487         }
488
489         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
490                 return -1;
491
492         if (lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
493                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
494                 return -1;
495         }
496
497         if (argc > 2 ) {
498                 count = strtol(argv[2], &end, 0);
499                 if (count > 0 && count < 32 && *end == 0) {
500                         netmask = 0;
501                         for (i = count; i > 0; i--)
502                                 netmask = netmask|(1<<(32-i));
503                 } else if (lnet_parse_ipquad(&netmask, argv[2]) != 0) {
504                         fprintf (stderr, "Can't parse netmask: %s\n", argv[2]);
505                         return -1;
506                 }
507         }
508
509         LIBCFS_IOC_INIT(data);
510         data.ioc_net    = g_net;
511         data.ioc_u32[0] = ipaddr;
512         data.ioc_u32[1] = netmask;
513
514         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_INTERFACE, &data);
515         if (rc != 0) {
516                 fprintf (stderr, "failed to add interface: %s\n",
517                          strerror (errno));
518                 return -1;
519         }
520
521         return 0;
522 }
523
524 int
525 jt_ptl_del_interface (int argc, char **argv)
526 {
527         struct libcfs_ioctl_data data;
528         int                      rc;
529         __u32                    ipaddr = 0;
530
531         if (argc > 2) {
532                 fprintf (stderr, "usage: %s [ipaddr]\n", argv[0]);
533                 return 0;
534         }
535
536         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
537                 return -1;
538
539         if (argc == 2 &&
540             lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
541                 fprintf (stderr, "Can't parse ip: %s\n", argv[1]);
542                 return -1;
543         }
544
545         LIBCFS_IOC_INIT(data);
546         data.ioc_net    = g_net;
547         data.ioc_u32[0] = ipaddr;
548
549         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_INTERFACE, &data);
550         if (rc != 0) {
551                 fprintf (stderr, "failed to delete interface: %s\n",
552                          strerror (errno));
553                 return -1;
554         }
555
556         return 0;
557 }
558
559 int
560 jt_ptl_print_peers (int argc, char **argv)
561 {
562         struct libcfs_ioctl_data data;
563         lnet_process_id_t        id;
564         char                     buffer[2][HOST_NAME_MAX + 1];
565         int                      index;
566         int                      rc;
567
568         if (!g_net_is_compatible (argv[0], SOCKLND, RALND, MXLND,
569                                   O2IBLND, GNILND, 0))
570                 return -1;
571
572         for (index = 0;;index++) {
573                 LIBCFS_IOC_INIT(data);
574                 data.ioc_net     = g_net;
575                 data.ioc_count   = index;
576
577                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER, &data);
578                 if (rc != 0)
579                         break;
580
581                 if (g_net_is_compatible(NULL, SOCKLND, 0)) {
582                         id.nid = data.ioc_nid;
583                         id.pid = data.ioc_u32[4];
584                         printf ("%-20s [%d]%s->%s:%d #%d\n",
585                                 libcfs_id2str(id), 
586                                 data.ioc_count, /* persistence */
587                                 /* my ip */
588                                 ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
589                                                  sizeof(buffer[0]), 1),
590                                 /* peer ip */
591                                 ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
592                                                  sizeof(buffer[1]), 1),
593                                 data.ioc_u32[1], /* peer port */
594                                 data.ioc_u32[3]); /* conn_count */
595                 } else if (g_net_is_compatible(NULL, RALND, 0)) {
596                         printf ("%-20s [%d]@%s:%d\n",
597                                 libcfs_nid2str(data.ioc_nid), /* peer nid */
598                                 data.ioc_count,   /* peer persistence */
599                                 /* peer ip */
600                                 ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
601                                                  sizeof(buffer[1]), 1),
602                                 data.ioc_u32[1]); /* peer port */
603                 } else if (g_net_is_compatible(NULL, GNILND, 0)) {
604                         int disconn = data.ioc_flags >> 16;
605                         char *state;
606
607                         if (disconn)
608                                 state = "D";
609                         else
610                                 state = data.ioc_flags & 0xffff ? "C" : "U";
611
612                         printf ("%-20s (%d) %s [%d] "LPU64" "
613                                 "sq %d/%d tx %d/%d/%d\n",
614                                 libcfs_nid2str(data.ioc_nid), /* peer nid */
615                                 data.ioc_net, /* gemini device id */
616                                 state, /* peer is Connecting, Up, or Down */
617                                 data.ioc_count,   /* peer refcount */
618                                 data.ioc_u64[0], /* peerstamp */
619                                 data.ioc_u32[2], data.ioc_u32[3], /* tx and rx seq */
620                                 /* fmaq, nfma, nrdma */
621                                 data.ioc_u32[0], data.ioc_u32[1], data.ioc_u32[4]
622                                 );
623                 } else {
624                         printf ("%-20s [%d]\n",
625                                 libcfs_nid2str(data.ioc_nid), data.ioc_count);
626                 }
627         }
628
629         if (index == 0) {
630                 if (errno == ENOENT) {
631                         printf ("<no peers>\n");
632                 } else {
633                         fprintf(stderr, "Error getting peer list: %s: "
634                                 "check dmesg.\n",
635                                 strerror(errno));
636                 }
637         }
638         return 0;
639 }
640
641 int
642 jt_ptl_add_peer (int argc, char **argv)
643 {
644         struct libcfs_ioctl_data data;
645         lnet_nid_t               nid;
646         __u32                    ip = 0;
647         int                      port = 0;
648         int                      rc;
649
650         if (!g_net_is_compatible (argv[0], SOCKLND, RALND,
651                                   GNILND, 0))
652                 return -1;
653
654         if (argc != 4) {
655                 fprintf (stderr, "usage(tcp,ra,gni): %s nid ipaddr port\n",
656                          argv[0]);
657                 return 0;
658         }
659
660         nid = libcfs_str2nid(argv[1]);
661         if (nid == LNET_NID_ANY) {
662                 fprintf (stderr, "Can't parse NID: %s\n", argv[1]);
663                 return -1;
664         }
665
666         if (lnet_parse_ipaddr (&ip, argv[2]) != 0) {
667                 fprintf (stderr, "Can't parse ip addr: %s\n", argv[2]);
668                 return -1;
669         }
670
671         if (lnet_parse_port (&port, argv[3]) != 0) {
672                 fprintf (stderr, "Can't parse port: %s\n", argv[3]);
673                 return -1;
674         }
675
676         LIBCFS_IOC_INIT(data);
677         data.ioc_net    = g_net;
678         data.ioc_nid    = nid;
679         data.ioc_u32[0] = ip;
680         data.ioc_u32[1] = port;
681
682         rc = l_ioctl (LNET_DEV_ID, IOC_LIBCFS_ADD_PEER, &data);
683         if (rc != 0) {
684                 fprintf (stderr, "failed to add peer: %s\n",
685                          strerror (errno));
686                 return -1;
687         }
688
689         return 0;
690 }
691
692 int
693 jt_ptl_del_peer (int argc, char **argv)
694 {
695         struct libcfs_ioctl_data data;
696         lnet_nid_t               nid = LNET_NID_ANY;
697         lnet_pid_t               pid = LNET_PID_ANY;
698         __u32                    ip = 0;
699         int                      rc;
700
701         if (!g_net_is_compatible (argv[0], SOCKLND, RALND, MXLND,
702                                   O2IBLND, GNILND, 0))
703                 return -1;
704
705         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
706                 if (argc > 3) {
707                         fprintf (stderr, "usage: %s [nid] [ipaddr]\n",
708                                  argv[0]);
709                         return 0;
710                 }
711         } else if (argc > 2) {
712                 fprintf (stderr, "usage: %s [nid]\n", argv[0]);
713                 return 0;
714         }
715
716         if (argc > 1 &&
717             !libcfs_str2anynid(&nid, argv[1])) {
718                 fprintf (stderr, "Can't parse nid: %s\n", argv[1]);
719                 return -1;
720         }
721
722         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
723                 if (argc > 2 &&
724                     lnet_parse_ipaddr (&ip, argv[2]) != 0) {
725                         fprintf (stderr, "Can't parse ip addr: %s\n",
726                                  argv[2]);
727                         return -1;
728                 }
729         }
730
731         LIBCFS_IOC_INIT(data);
732         data.ioc_net    = g_net;
733         data.ioc_nid    = nid;
734         data.ioc_u32[0] = ip;
735         data.ioc_u32[1] = pid;
736
737         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_PEER, &data);
738         if (rc != 0) {
739                 fprintf (stderr, "failed to remove peer: %s\n",
740                          strerror (errno));
741                 return -1;
742         }
743
744         return 0;
745 }
746
747 int
748 jt_ptl_print_connections (int argc, char **argv)
749 {
750         struct libcfs_ioctl_data data;
751         lnet_process_id_t        id;
752         char                     buffer[2][HOST_NAME_MAX + 1];
753         int                      index;
754         int                      rc;
755
756         if (!g_net_is_compatible (argv[0], SOCKLND, RALND, MXLND, O2IBLND,
757                                   GNILND, 0))
758                 return -1;
759
760         for (index = 0; ; index++) {
761                 LIBCFS_IOC_INIT(data);
762                 data.ioc_net     = g_net;
763                 data.ioc_count   = index;
764
765                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_CONN, &data);
766                 if (rc != 0)
767                         break;
768
769                 if (g_net_is_compatible (NULL, SOCKLND, 0)) {
770                         id.nid = data.ioc_nid;
771                         id.pid = data.ioc_u32[6];
772                         printf ("%-20s %s[%d]%s->%s:%d %d/%d %s\n",
773                                 libcfs_id2str(id),
774                                 (data.ioc_u32[3] == SOCKLND_CONN_ANY) ? "A" :
775                                 (data.ioc_u32[3] == SOCKLND_CONN_CONTROL) ? "C" :
776                                 (data.ioc_u32[3] == SOCKLND_CONN_BULK_IN) ? "I" :
777                                 (data.ioc_u32[3] == SOCKLND_CONN_BULK_OUT) ? "O" : "?",
778                                 data.ioc_u32[4], /* scheduler */
779                                 /* local IP addr */
780                                 ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
781                                                  sizeof(buffer[0]), 1),
782                                 /* remote IP addr */
783                                 ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
784                                                  sizeof(buffer[1]), 1),
785                                 data.ioc_u32[1],         /* remote port */
786                                 data.ioc_count, /* tx buffer size */
787                                 data.ioc_u32[5], /* rx buffer size */
788                                 data.ioc_flags ? "nagle" : "nonagle");
789                 } else if (g_net_is_compatible (NULL, RALND, 0)) {
790                         printf ("%-20s [%d]\n",
791                                 libcfs_nid2str(data.ioc_nid),
792                                 data.ioc_u32[0] /* device id */);
793                 } else if (g_net_is_compatible (NULL, O2IBLND, 0)) {
794                         printf ("%s mtu %d\n",
795                                 libcfs_nid2str(data.ioc_nid),
796                                 data.ioc_u32[0]); /* path MTU */
797                 } else if (g_net_is_compatible (NULL, GNILND, 0)) {
798                         printf ("%-20s [%d]\n",
799                                 libcfs_nid2str(data.ioc_nid),
800                                 data.ioc_u32[0] /* device id */);
801                 } else {
802                         printf ("%s\n", libcfs_nid2str(data.ioc_nid));
803                 }
804         }
805
806         if (index == 0) {
807                 if (errno == ENOENT) {
808                         printf ("<no connections>\n");
809                 } else {
810                         fprintf(stderr, "Error getting connection list: %s: "
811                                 "check dmesg.\n",
812                                 strerror(errno));
813                 }
814         }
815         return 0;
816 }
817
818 int jt_ptl_disconnect(int argc, char **argv)
819 {
820         struct libcfs_ioctl_data data;
821         lnet_nid_t               nid = LNET_NID_ANY;
822         __u32                    ipaddr = 0;
823         int                      rc;
824
825         if (argc > 3) {
826                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
827                 return 0;
828         }
829
830         if (!g_net_is_compatible (NULL, SOCKLND, RALND, MXLND, O2IBLND,
831                                   GNILND, 0))
832                 return 0;
833
834         if (argc >= 2 &&
835             !libcfs_str2anynid(&nid, argv[1])) {
836                 fprintf (stderr, "Can't parse nid %s\n", argv[1]);
837                 return -1;
838         }
839
840         if (g_net_is_compatible (NULL, SOCKLND, 0) &&
841             argc >= 3 &&
842             lnet_parse_ipaddr (&ipaddr, argv[2]) != 0) {
843                 fprintf (stderr, "Can't parse ip addr %s\n", argv[2]);
844                 return -1;
845         }
846
847         LIBCFS_IOC_INIT(data);
848         data.ioc_net     = g_net;
849         data.ioc_nid     = nid;
850         data.ioc_u32[0]  = ipaddr;
851
852         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CLOSE_CONNECTION, &data);
853         if (rc != 0) {
854                 fprintf(stderr, "failed to remove connection: %s\n",
855                         strerror(errno));
856                 return -1;
857         }
858
859         return 0;
860 }
861
862 int jt_ptl_push_connection (int argc, char **argv)
863 {
864         struct libcfs_ioctl_data data;
865         int                      rc;
866         lnet_nid_t               nid = LNET_NID_ANY;
867
868         if (argc > 2) {
869                 fprintf(stderr, "usage: %s [nid]\n", argv[0]);
870                 return 0;
871         }
872
873         if (!g_net_is_compatible (argv[0], SOCKLND, GNILND, 0))
874                 return -1;
875
876         if (argc > 1 &&
877             !libcfs_str2anynid(&nid, argv[1])) {
878                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
879                 return -1;
880         }
881
882         LIBCFS_IOC_INIT(data);
883         data.ioc_net     = g_net;
884         data.ioc_nid     = nid;
885
886         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PUSH_CONNECTION, &data);
887         if (rc != 0) {
888                 fprintf(stderr, "failed to push connection: %s\n",
889                         strerror(errno));
890                 return -1;
891         }
892
893         return 0;
894 }
895
896 int
897 jt_ptl_print_active_txs (int argc, char **argv)
898 {
899         struct libcfs_ioctl_data data;
900         int                      index;
901         int                      rc;
902
903         if (!g_net_is_compatible (argv[0], QSWLND, 0))
904                 return -1;
905
906         for (index = 0;;index++) {
907                 LIBCFS_IOC_INIT(data);
908                 data.ioc_net   = g_net;
909                 data.ioc_count = index;
910
911                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_TXDESC, &data);
912                 if (rc != 0)
913                         break;
914
915                 printf ("type %u payload %6d to %s via %s by pid %6d: "
916                         "%s, %s, state %d\n",
917                         data.ioc_u32[0],
918                         data.ioc_count,
919                         libcfs_nid2str(data.ioc_nid),
920                         libcfs_nid2str(data.ioc_u64[0]),
921                         data.ioc_u32[1],
922                         (data.ioc_flags & 1) ? "delayed" : "immediate",
923                         (data.ioc_flags & 2) ? "nblk"    : "normal",
924                         data.ioc_flags >> 2);
925         }
926
927         if (index == 0) {
928                 if (errno == ENOENT) {
929                         printf ("<no active descs>\n");
930                 } else {
931                         fprintf(stderr, "Error getting active transmits list: "
932                                 "%s: check dmesg.\n",
933                                 strerror(errno));
934                 }
935         }
936         return 0;
937 }
938
939 int jt_ptl_ping(int argc, char **argv)
940 {
941         int                      rc;
942         int                      timeout;
943         lnet_process_id_t        id;
944         lnet_process_id_t        ids[16];
945         int                      maxids = sizeof(ids)/sizeof(ids[0]);
946         struct libcfs_ioctl_data data;
947         char                    *sep;
948         int                      i;
949
950         if (argc < 2) {
951                 fprintf(stderr, "usage: %s id [timeout (secs)]\n", argv[0]);
952                 return 0;
953         }
954
955         sep = strchr(argv[1], '-');
956         if (sep == NULL) {
957                 rc = lnet_parse_nid(argv[1], &id);
958                 if (rc != 0)
959                         return -1;
960         } else {
961                 char   *end;
962
963                 if (argv[1][0] == 'u' ||
964                     argv[1][0] == 'U')
965                         id.pid = strtoul(&argv[1][1], &end, 0) | LNET_PID_USERFLAG;
966                 else
967                         id.pid = strtoul(argv[1], &end, 0);
968
969                 if (end != sep) { /* assuming '-' is part of hostname */
970                         rc = lnet_parse_nid(argv[1], &id);
971                         if (rc != 0)
972                                 return -1;
973                 } else {
974                         id.nid = libcfs_str2nid(sep + 1);
975
976                         if (id.nid == LNET_NID_ANY) {
977                                 fprintf(stderr,
978                                         "Can't parse process id \"%s\"\n",
979                                         argv[1]);
980                                 return -1;
981                         }
982                 }
983         }
984
985         if (argc > 2)
986                 timeout = 1000 * atol(argv[2]);
987         else
988                 timeout = 1000;                 /* default 1 second timeout */
989
990         LIBCFS_IOC_INIT (data);
991         data.ioc_nid     = id.nid;
992         data.ioc_u32[0]  = id.pid;
993         data.ioc_u32[1]  = timeout;
994         data.ioc_plen1   = sizeof(ids);
995         data.ioc_pbuf1   = (char *)ids;
996
997         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING, &data);
998         if (rc != 0) {
999                 fprintf(stderr, "failed to ping %s: %s\n",
1000                         id.pid == LNET_PID_ANY ?
1001                         libcfs_nid2str(id.nid) : libcfs_id2str(id),
1002                         strerror(errno));
1003                 return -1;
1004         }
1005
1006         for (i = 0; i < data.ioc_count && i < maxids; i++)
1007                 printf("%s\n", libcfs_id2str(ids[i]));
1008
1009         if (data.ioc_count > maxids)
1010                 printf("%d out of %d ids listed\n", maxids, data.ioc_count);
1011
1012         return 0;
1013 }
1014
1015 int jt_ptl_mynid(int argc, char **argv)
1016 {
1017         struct libcfs_ioctl_data data;
1018         lnet_nid_t               nid;
1019         int rc;
1020
1021         if (argc != 2) {
1022                 fprintf(stderr, "usage: %s NID\n", argv[0]);
1023                 return 0;
1024         }
1025
1026         nid = libcfs_str2nid(argv[1]);
1027         if (nid == LNET_NID_ANY) {
1028                 fprintf(stderr, "Can't parse NID '%s'\n", argv[1]);
1029                 return -1;
1030         }
1031
1032         LIBCFS_IOC_INIT(data);
1033         data.ioc_net = LNET_NIDNET(nid);
1034         data.ioc_nid = nid;
1035
1036         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_REGISTER_MYNID, &data);
1037         if (rc < 0)
1038                 fprintf(stderr, "setting my NID failed: %s\n",
1039                        strerror(errno));
1040         else
1041                 printf("registered my nid %s\n", libcfs_nid2str(nid));
1042
1043         return 0;
1044 }
1045
1046 int
1047 jt_ptl_fail_nid (int argc, char **argv)
1048 {
1049         int                      rc;
1050         lnet_nid_t               nid;
1051         int                      threshold;
1052         struct libcfs_ioctl_data data;
1053
1054         if (argc < 2 || argc > 3)
1055         {
1056                 fprintf (stderr, "usage: %s nid|\"*\" [count (0 == mend)]\n", argv[0]);
1057                 return (0);
1058         }
1059
1060         if (!libcfs_str2anynid(&nid, argv[1]))
1061         {
1062                 fprintf (stderr, "Can't parse nid \"%s\"\n", argv[1]);
1063                 return (-1);
1064         }
1065
1066         if (argc < 3) {
1067                 threshold = LNET_MD_THRESH_INF;
1068         } else if (sscanf(argv[2], "%i", &threshold) != 1) {
1069                 fprintf (stderr, "Can't parse count \"%s\"\n", argv[2]);
1070                 return (-1);
1071         }
1072
1073         LIBCFS_IOC_INIT (data);
1074         data.ioc_nid = nid;
1075         data.ioc_count = threshold;
1076
1077         rc = l_ioctl (LNET_DEV_ID, IOC_LIBCFS_FAIL_NID, &data);
1078         if (rc < 0)
1079                 fprintf (stderr, "IOC_LIBCFS_FAIL_NID failed: %s\n",
1080                          strerror (errno));
1081         else
1082                 printf ("%s %s\n", threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1083
1084         return (0);
1085 }
1086
1087 int
1088 jt_ptl_add_route (int argc, char **argv)
1089 {
1090         struct libcfs_ioctl_data data;
1091         lnet_nid_t               gateway_nid;
1092         unsigned int             hops = 1;
1093         unsigned int             priority = 0;
1094         char                    *end;
1095         int                      rc;
1096
1097         if (argc < 2 || argc > 4) {
1098                 fprintf(stderr, "usage: %s gateway [hopcount [priority]]\n",
1099                         argv[0]);
1100                 return -1;
1101         }
1102
1103         if (!g_net_is_set(argv[0]))
1104                 return (-1);
1105
1106         gateway_nid = libcfs_str2nid(argv[1]);
1107         if (gateway_nid == LNET_NID_ANY) {
1108                 fprintf (stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1109                 return (-1);
1110         }
1111
1112         if (argc > 2) {
1113                 hops = strtoul(argv[2], &end, 0);
1114                 if (hops == 0 || hops >= 256 || (end != NULL && *end != 0)) {
1115                         fprintf(stderr, "Can't parse hopcount \"%s\"\n",
1116                                 argv[2]);
1117                         return -1;
1118                 }
1119                 if (argc == 4) {
1120                         priority = strtoul(argv[3], &end, 0);
1121                         if (end != NULL && *end != 0) {
1122                                 fprintf(stderr,
1123                                         "Can't parse priority \"%s\"\n",
1124                                         argv[3]);
1125                                 return -1;
1126                         }
1127                 }
1128         }
1129
1130         LIBCFS_IOC_INIT(data);
1131         data.ioc_net = g_net;
1132         data.ioc_count = hops;
1133         data.ioc_nid = gateway_nid;
1134         data.ioc_priority = priority;
1135
1136         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
1137         if (rc != 0) {
1138                 fprintf (stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n", strerror (errno));
1139                 return (-1);
1140         }
1141
1142         return (0);
1143 }
1144
1145 int
1146 jt_ptl_del_route (int argc, char **argv)
1147 {
1148         struct libcfs_ioctl_data data;
1149         lnet_nid_t               nid;
1150         int                      rc;
1151
1152         if (argc != 2) {
1153                 fprintf (stderr, "usage: %s gatewayNID\n", argv[0]);
1154                 return (0);
1155         }
1156
1157         if (!libcfs_str2anynid(&nid, argv[1])) {
1158                 fprintf (stderr, "Can't parse gateway NID "
1159                          "\"%s\"\n", argv[1]);
1160                 return -1;
1161         }
1162
1163         LIBCFS_IOC_INIT(data);
1164         data.ioc_net = g_net_set ? g_net : LNET_NIDNET(LNET_NID_ANY);
1165         data.ioc_nid = nid;
1166
1167         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
1168         if (rc != 0) {
1169                 fprintf (stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n",
1170                          libcfs_nid2str(nid), strerror (errno));
1171                 return (-1);
1172         }
1173
1174         return (0);
1175 }
1176
1177 int
1178 jt_ptl_notify_router (int argc, char **argv)
1179 {
1180         struct libcfs_ioctl_data data;
1181         int                      enable;
1182         lnet_nid_t               nid;
1183         int                      rc;
1184         struct timeval           now;
1185         time_t                   when;
1186
1187         if (argc < 3)
1188         {
1189                 fprintf (stderr, "usage: %s targetNID <up/down> [<time>]\n", 
1190                          argv[0]);
1191                 return (0);
1192         }
1193
1194         nid = libcfs_str2nid(argv[1]);
1195         if (nid == LNET_NID_ANY) {
1196                 fprintf (stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1197                 return (-1);
1198         }
1199
1200         if (lnet_parse_bool (&enable, argv[2]) != 0) {
1201                 fprintf (stderr, "Can't parse boolean %s\n", argv[2]);
1202                 return (-1);
1203         }
1204
1205         gettimeofday(&now, NULL);
1206
1207         if (argc < 4) {
1208                 when = now.tv_sec;
1209         } else if (lnet_parse_time (&when, argv[3]) != 0) {
1210                 fprintf(stderr, "Can't parse time %s\n"
1211                         "Please specify either 'YYYY-MM-DD-HH:MM:SS'\n"
1212                         "or an absolute unix time in seconds\n", argv[3]);
1213                 return (-1);
1214         } else if (when > now.tv_sec) {
1215                 fprintf (stderr, "%s specifies a time in the future\n",
1216                          argv[3]);
1217                 return (-1);
1218         }
1219
1220         LIBCFS_IOC_INIT(data);
1221         data.ioc_nid = nid;
1222         data.ioc_flags = enable;
1223         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
1224         data.ioc_u64[0] = (__u64)when;
1225
1226         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_NOTIFY_ROUTER, &data);
1227         if (rc != 0) {
1228                 fprintf (stderr, "IOC_LIBCFS_NOTIFY_ROUTER (%s) failed: %s\n",
1229                          libcfs_nid2str(nid), strerror (errno));
1230                 return (-1);
1231         }
1232
1233         return (0);
1234 }
1235
1236 int
1237 jt_ptl_print_routes (int argc, char **argv)
1238 {
1239         struct libcfs_ioctl_data  data;
1240         int                       rc;
1241         int                       index;
1242         __u32                     net;
1243         lnet_nid_t                nid;
1244         unsigned int              hops;
1245         int                       alive;
1246         unsigned int              pri;
1247
1248         for (index = 0;;index++)
1249         {
1250                 LIBCFS_IOC_INIT(data);
1251                 data.ioc_count = index;
1252
1253                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
1254                 if (rc != 0)
1255                         break;
1256
1257                 net     = data.ioc_net;
1258                 hops    = data.ioc_count;
1259                 nid     = data.ioc_nid;
1260                 alive   = data.ioc_flags;
1261                 pri     = data.ioc_priority;
1262
1263                 printf("net %18s hops %u gw %32s %s pri %u\n",
1264                        libcfs_net2str(net), hops,
1265                        libcfs_nid2str(nid), alive ? "up" : "down", pri);
1266         }
1267
1268         if (errno != ENOENT)
1269                 fprintf(stderr, "Error getting routes: %s: check dmesg.\n",
1270                         strerror(errno));
1271
1272         return (0);
1273 }
1274
1275 double
1276 get_cycles_per_usec ()
1277 {
1278         FILE      *f = fopen ("/proc/cpuinfo", "r");
1279         double     mhz;
1280         char      line[64];
1281
1282         if (f != NULL) {
1283                 while (fgets (line, sizeof (line), f) != NULL)
1284                         if (sscanf (line, "cpu MHz : %lf", &mhz) == 1) {
1285                                 fclose (f);
1286                                 return (mhz);
1287                         }
1288                 fclose (f);
1289         }
1290
1291         fprintf (stderr, "Can't read/parse /proc/cpuinfo\n");
1292         return (1000.0);
1293 }
1294
1295 int jt_ptl_memhog(int argc, char **argv)
1296 {
1297         static int                gfp = 0;        /* sticky! */
1298
1299         struct libcfs_ioctl_data  data;
1300         int                       rc;
1301         int                       count;
1302         char                     *end;
1303
1304         if (argc < 2)  {
1305                 fprintf(stderr, "usage: %s <npages> [<GFP flags>]\n", argv[0]);
1306                 return 0;
1307         }
1308
1309         count = strtol(argv[1], &end, 0);
1310         if (count < 0 || *end != 0) {
1311                 fprintf(stderr, "Can't parse page count '%s'\n", argv[1]);
1312                 return -1;
1313         }
1314
1315         if (argc >= 3) {
1316                 rc = strtol(argv[2], &end, 0);
1317                 if (*end != 0) {
1318                         fprintf(stderr, "Can't parse gfp flags '%s'\n", argv[2]);
1319                         return -1;
1320                 }
1321                 gfp = rc;
1322         }
1323
1324         LIBCFS_IOC_INIT(data);
1325         data.ioc_count = count;
1326         data.ioc_flags = gfp;
1327         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_MEMHOG, &data);
1328
1329         if (rc != 0) {
1330                 fprintf(stderr, "memhog %d failed: %s\n", count, strerror(errno));
1331                 return -1;
1332         }
1333
1334         printf("memhog %d OK\n", count);
1335         return 0;
1336 }
1337
1338 int jt_ptl_testprotocompat(int argc, char **argv)
1339 {
1340         struct libcfs_ioctl_data  data;
1341         int                       rc;
1342         int                       flags;
1343         char                     *end;
1344
1345         if (argc < 2)  {
1346                 fprintf(stderr, "usage: %s <number>\n", argv[0]);
1347                 return 0;
1348         }
1349
1350         flags = strtol(argv[1], &end, 0);
1351         if (flags < 0 || *end != 0) {
1352                 fprintf(stderr, "Can't parse flags '%s'\n", argv[1]);
1353                 return -1;
1354         }
1355
1356         LIBCFS_IOC_INIT(data);
1357         data.ioc_flags = flags;
1358         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_TESTPROTOCOMPAT, &data);
1359
1360         if (rc != 0) {
1361                 fprintf(stderr, "test proto compat %x failed: %s\n",
1362                         flags, strerror(errno));
1363                 return -1;
1364         }
1365
1366         printf("test proto compat %x OK\n", flags);
1367         return 0;
1368 }
1369
1370