Whamcloud - gitweb
a0220a6733de02cf71151ac6851204580b76bc4c
[fs/lustre-release.git] / lustre / utils / portals.c
1 /*
2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Copyright (c) 2013, 2017, Intel Corporation.
5  *
6  *   This file is part of Lustre, https://wiki.whamcloud.com/
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 #include <errno.h>
23 #include <getopt.h>
24 #include <inttypes.h>
25 #include <limits.h>
26 #ifdef HAVE_NETDB_H
27 # include <netdb.h>
28 #endif
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/ioctl.h>
34 #include <sys/time.h>
35 #include <time.h>
36 #include <linux/types.h>
37
38 #include <libcfs/util/ioctl.h>
39 #include <linux/lnet/libcfs_debug.h>
40 #include <linux/lnet/lnet-dlc.h>
41 #include <linux/lnet/lnetctl.h>
42 #include <linux/lnet/nidstr.h>
43 #include <linux/lnet/socklnd.h>
44 #include <lustre/lustreapi.h>
45
46 unsigned int libcfs_debug;
47 unsigned int libcfs_printk = D_CANTMASK;
48
49 static bool  g_net_interactive;
50 static bool  g_net_set;
51 static __u32 g_net;
52
53 #define IOC_BUF_SIZE    8192
54 static char local_buf[IOC_BUF_SIZE];
55 static char *ioc_buf = local_buf;
56
57 /* Convert a string boolean to an int; "enable" -> 1 */
58 int
59 lnet_parse_bool (int *b, char *str)
60 {
61         if (!strcasecmp(str, "no") ||
62             !strcasecmp(str, "n") ||
63             !strcasecmp(str, "off") ||
64             !strcasecmp(str, "down") ||
65             !strcasecmp(str, "disable")) {
66                 *b = 0;
67
68                 return 0;
69         }
70
71         if (!strcasecmp(str, "yes") ||
72             !strcasecmp(str, "y") ||
73             !strcasecmp(str, "on") ||
74             !strcasecmp(str, "up") ||
75             !strcasecmp(str, "enable")) {
76                 *b = 1;
77
78                 return 0;
79         }
80
81         return -1;
82 }
83
84 int
85 lnet_parse_port(int *port, char *str)
86 {
87         char *end;
88
89         *port = strtol(str, &end, 0);
90
91         if (*end == 0 &&                        /* parsed whole string */
92             *port > 0 && *port < 65536)         /* minimal sanity check */
93                 return 0;
94
95         return -1;
96 }
97
98 #ifdef HAVE_GETHOSTBYNAME
99 static struct hostent *
100 ptl_gethostbyname(char *hname)
101 {
102         struct hostent *he;
103
104         he = gethostbyname(hname);
105         if (!he) {
106                 switch (h_errno) {
107                 case HOST_NOT_FOUND:
108                 case NO_ADDRESS:
109                         fprintf(stderr, "Unable to resolve hostname: %s\n",
110                                 hname);
111                         break;
112                 default:
113                         fprintf(stderr, "gethostbyname error for %s: %s\n",
114                                 hname, strerror(h_errno));
115                         break;
116                 }
117                 return NULL;
118         }
119         return he;
120 }
121 #endif
122
123 int
124 lnet_parse_ipquad(__u32 *ipaddrp, char *str)
125 {
126         int a, b, c, d;
127
128         if (sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
129             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
130             (c & ~0xff) == 0 && (d & ~0xff) == 0) {
131                 *ipaddrp = (a << 24) | (b << 16) | (c << 8) | d;
132
133                 return 0;
134         }
135
136         return -1;
137 }
138
139 int
140 lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
141 {
142 #ifdef HAVE_GETHOSTBYNAME
143         struct hostent *he;
144 #endif
145
146         if (!strcmp(str, "_all_")) {
147                 *ipaddrp = 0;
148                 return 0;
149         }
150
151         if (lnet_parse_ipquad(ipaddrp, str) == 0)
152                 return 0;
153
154 #ifdef HAVE_GETHOSTBYNAME
155         if ((('a' <= str[0] && str[0] <= 'z') ||
156              ('A' <= str[0] && str[0] <= 'Z')) &&
157               (he = ptl_gethostbyname(str)) != NULL) {
158                 __u32 addr = *(__u32 *)he->h_addr;
159
160                 *ipaddrp = ntohl(addr);         /* HOST byte order */
161                 return 0;
162         }
163 #endif
164
165         return -1;
166 }
167
168 char *
169 ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup)
170 {
171 #ifdef HAVE_GETHOSTBYNAME
172         __u32 net_ip;
173         struct hostent *he;
174
175         if (lookup) {
176                 net_ip = htonl(ipaddr);
177                 he = gethostbyaddr(&net_ip, sizeof(net_ip), AF_INET);
178                 if (he) {
179                         snprintf(str, strsize, "%s", he->h_name);
180                         return str;
181                 }
182         }
183 #endif
184
185         sprintf(str, "%d.%d.%d.%d",
186                 (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
187                 (ipaddr >> 8) & 0xff, ipaddr & 0xff);
188         return str;
189 }
190
191 int
192 lnet_parse_time(time_t *t, char *str)
193 {
194         char *end;
195         int n;
196         struct tm tm;
197
198         *t = strtol(str, &end, 0);
199         if (*end == 0) /* parsed whole string */
200                 return 0;
201
202         memset(&tm, 0, sizeof(tm));
203         n = sscanf(str, "%d-%d-%d-%d:%d:%d",
204                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
205                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
206         if (n != 6)
207                 return -1;
208
209         tm.tm_mon--;                    /* convert to 0 == Jan */
210         tm.tm_year -= 1900;             /* y2k quirk */
211         tm.tm_isdst = -1;               /* dunno if it's daylight savings... */
212
213         *t = mktime(&tm);
214         if (*t == (time_t)-1)
215                 return -1;
216
217         return 0;
218 }
219
220 int
221 lnet_parse_nid(char *nid_str, struct lnet_process_id *id_ptr)
222 {
223         id_ptr->pid = LNET_PID_ANY;
224         id_ptr->nid = libcfs_str2nid(nid_str);
225         if (id_ptr->nid == LNET_NID_ANY) {
226                 fprintf(stderr, "Can't parse nid \"%s\"\n", nid_str);
227                 return -1;
228         }
229
230         return 0;
231 }
232
233 static int g_net_is_set(char *cmd)
234 {
235         if (g_net_set)
236                 return 1;
237
238         if (cmd) {
239                 char *net;
240
241                 if (g_net_interactive)
242                         net = "network";
243                 else
244                         net = "--net";
245
246                 fprintf(stderr,
247                         "You must run '%s <network>' command before '%s'\n",
248                         cmd, net);
249                 return 0;
250         }
251
252         return 0;
253 }
254
255 static int g_net_is_compatible(char *cmd, ...)
256 {
257         va_list ap;
258         int nal;
259
260         if (!g_net_is_set(cmd))
261                 return 0;
262
263         va_start(ap, cmd);
264
265         do {
266                 nal = va_arg(ap, int);
267                 if (nal == LNET_NETTYP(g_net)) {
268                         va_end(ap);
269                         return 1;
270                 }
271         } while (nal != 0);
272
273         va_end(ap);
274
275         if (cmd)
276                 fprintf(stderr, "Command %s not compatible with %s NAL\n",
277                         cmd, libcfs_lnd2str(LNET_NETTYP(g_net)));
278
279         return 0;
280 }
281
282 int ptl_initialize(int argc, char **argv)
283 {
284         if (argc > 1)
285                 g_net_interactive = true;
286
287         register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH);
288
289         return 0;
290 }
291
292 int jt_ptl_network(int argc, char **argv)
293 {
294         struct libcfs_ioctl_data data;
295         __u32 net = LNET_NIDNET(LNET_NID_ANY);
296         int rc;
297
298         if (argc != 2) {
299                 fprintf(stderr, "usage: %s <net>|up|down\n", argv[0]);
300                 return -1;
301         }
302
303         if (!strcmp(argv[1], "unconfigure") || !strcmp(argv[1], "down")) {
304                 LIBCFS_IOC_INIT(data);
305                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_UNCONFIGURE, &data);
306
307                 if (rc == 0) {
308                         printf("LNET ready to unload\n");
309                         return 0;
310                 }
311
312                 if (errno == ENODEV) {
313                         printf("LNET is currently not loaded.");
314                         return 0;
315                 }
316
317                 if (errno == EBUSY)
318                         fprintf(stderr, "LNET busy\n");
319                 else
320                         fprintf(stderr, "LNET unconfigure error %d: %s\n",
321                                 errno, strerror(errno));
322                 return -1;
323         } else if (!strcmp(argv[1], "configure") || !strcmp(argv[1], "up")) {
324                 LIBCFS_IOC_INIT(data);
325                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIGURE, &data);
326
327                 if (rc == 0) {
328                         printf("LNET configured\n");
329                         return 0;
330                 }
331
332                 fprintf(stderr, "LNET configure error %d: %s\n",
333                         errno, strerror(errno));
334                 return -1;
335         }
336
337         net = libcfs_str2net(argv[1]);
338         if (net == LNET_NIDNET(LNET_NID_ANY)) {
339                 fprintf(stderr, "Can't parse net %s\n", argv[1]);
340                 return -1;
341         }
342
343         g_net_set = true;
344         g_net = net;
345         return 0;
346 }
347
348 int
349 jt_ptl_list_nids(int argc, char **argv)
350 {
351         struct libcfs_ioctl_data data;
352         int all = 0, return_nid = 0;
353         int count;
354         int rc;
355
356         all = (argc == 2) && (strcmp(argv[1], "all") == 0);
357         /* Hack to pass back value */
358         return_nid = (argc == 2) && (argv[1][0] == 1);
359
360         if ((argc > 2) && !(all || return_nid)) {
361                 fprintf(stderr, "usage: %s [all]\n", argv[0]);
362                 return 0;
363         }
364
365         for (count = 0;; count++) {
366                 LIBCFS_IOC_INIT(data);
367                 data.ioc_count = count;
368                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NI, &data);
369
370                 if (rc < 0) {
371                         if ((count > 0) && (errno == ENOENT))
372                                 /* We found them all */
373                                 break;
374                         fprintf(stderr, "IOC_LIBCFS_GET_NI error %d: %s\n",
375                                 errno, strerror(errno));
376                         return -1;
377                 }
378
379                 if (all || (data.ioc_nid != LNET_NID_LO_0)) {
380                         printf("%s\n", libcfs_nid2str(data.ioc_nid));
381                         if (return_nid) {
382                                 *(__u64 *)(argv[1]) = data.ioc_nid;
383                                 return_nid--;
384                         }
385                 }
386         }
387
388         return 0;
389 }
390
391 int
392 jt_ptl_which_nid(int argc, char **argv)
393 {
394         struct libcfs_ioctl_data data;
395         int best_dist = 0;
396         int best_order = 0;
397         lnet_nid_t   best_nid = LNET_NID_ANY;
398         int dist;
399         int order;
400         lnet_nid_t nid;
401         char *nidstr;
402         int rc;
403         int i;
404
405         if (argc < 2) {
406                 fprintf(stderr, "usage: %s NID [NID...]\n", argv[0]);
407                 return 0;
408         }
409
410         for (i = 1; i < argc; i++) {
411                 nidstr = argv[i];
412                 nid = libcfs_str2nid(nidstr);
413                 if (nid == LNET_NID_ANY) {
414                         fprintf(stderr, "Can't parse NID %s\n", nidstr);
415                         return -1;
416                 }
417
418                 LIBCFS_IOC_INIT(data);
419                 data.ioc_nid = nid;
420
421                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_DIST, &data);
422                 if (rc != 0) {
423                         fprintf(stderr, "Can't get distance to %s: %s\n",
424                                 nidstr, strerror(errno));
425                         return -1;
426                 }
427
428                 dist = data.ioc_u32[0];
429                 order = data.ioc_u32[1];
430
431                 if (dist < 0) {
432                         if (dist == -EHOSTUNREACH)
433                                 continue;
434
435                         fprintf(stderr, "Unexpected distance to %s: %d\n",
436                                 nidstr, dist);
437                         return -1;
438                 }
439
440                 if (best_nid == LNET_NID_ANY ||
441                     dist < best_dist ||
442                     (dist == best_dist && order < best_order)) {
443                         best_dist = dist;
444                         best_order = order;
445                         best_nid = nid;
446                 }
447         }
448
449         if (best_nid == LNET_NID_ANY) {
450                 fprintf(stderr, "No reachable NID\n");
451                 return -1;
452         }
453
454         printf("%s\n", libcfs_nid2str(best_nid));
455         return 0;
456 }
457
458 int
459 jt_ptl_print_interfaces(int argc, char **argv)
460 {
461         struct libcfs_ioctl_data data;
462         char buffer[3][HOST_NAME_MAX + 1];
463         int index;
464         int rc;
465
466         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
467                 return -1;
468
469         for (index = 0; ; index++) {
470                 LIBCFS_IOC_INIT(data);
471                 data.ioc_net   = g_net;
472                 data.ioc_count = index;
473
474                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_INTERFACE, &data);
475                 if (rc != 0)
476                         break;
477
478                 printf("%s: (%s/%s) npeer %d nroute %d\n",
479                        ptl_ipaddr_2_str(data.ioc_u32[0], buffer[2],
480                                         sizeof(buffer[2]), 1),
481                        ptl_ipaddr_2_str(data.ioc_u32[0], buffer[0],
482                                         sizeof(buffer[0]), 0),
483                        ptl_ipaddr_2_str(data.ioc_u32[1], buffer[1],
484                                         sizeof(buffer[1]), 0),
485                        data.ioc_u32[2], data.ioc_u32[3]);
486         }
487
488         if (index == 0) {
489                 if (errno == ENOENT) {
490                         printf("<no interfaces>\n");
491                 } else {
492                         fprintf(stderr,
493                                 "Error getting interfaces: %s: check dmesg.\n",
494                                 strerror(errno));
495                 }
496         }
497
498         return 0;
499 }
500
501 int
502 jt_ptl_add_interface(int argc, char **argv)
503 {
504         struct libcfs_ioctl_data data;
505         __u32 ipaddr;
506         int rc;
507         __u32 netmask = 0xffffff00;
508         int i;
509         int count;
510         char *end;
511
512         if (argc < 2 || argc > 3) {
513                 fprintf(stderr, "usage: %s ipaddr [netmask]\n", argv[0]);
514                 return 0;
515         }
516
517         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
518                 return -1;
519
520         if (lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
521                 fprintf(stderr, "Can't parse ip: %s\n", argv[1]);
522                 return -1;
523         }
524
525         if (argc > 2) {
526                 count = strtol(argv[2], &end, 0);
527                 if (count > 0 && count < 32 && *end == 0) {
528                         netmask = 0;
529                         for (i = count; i > 0; i--)
530                                 netmask = netmask | (1 << (32 - i));
531                 } else if (lnet_parse_ipquad(&netmask, argv[2]) != 0) {
532                         fprintf(stderr, "Can't parse netmask: %s\n", argv[2]);
533                         return -1;
534                 }
535         }
536
537         LIBCFS_IOC_INIT(data);
538         data.ioc_net    = g_net;
539         data.ioc_u32[0] = ipaddr;
540         data.ioc_u32[1] = netmask;
541
542         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_INTERFACE, &data);
543         if (rc != 0) {
544                 fprintf(stderr, "failed to add interface: %s\n",
545                         strerror(errno));
546                 return -1;
547         }
548
549         return 0;
550 }
551
552 int
553 jt_ptl_del_interface(int argc, char **argv)
554 {
555         struct libcfs_ioctl_data data;
556         int rc;
557         __u32 ipaddr = 0;
558
559         if (argc > 2) {
560                 fprintf(stderr, "usage: %s [ipaddr]\n", argv[0]);
561                 return 0;
562         }
563
564         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
565                 return -1;
566
567         if (argc == 2 &&
568             lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
569                 fprintf(stderr, "Can't parse ip: %s\n", argv[1]);
570                 return -1;
571         }
572
573         LIBCFS_IOC_INIT(data);
574         data.ioc_net    = g_net;
575         data.ioc_u32[0] = ipaddr;
576
577         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_INTERFACE, &data);
578         if (rc != 0) {
579                 fprintf(stderr, "failed to delete interface: %s\n",
580                         strerror(errno));
581                 return -1;
582         }
583
584         return 0;
585 }
586
587 int
588 jt_ptl_print_peers(int argc, char **argv)
589 {
590         struct libcfs_ioctl_data data;
591         struct lnet_process_id id;
592         char buffer[2][HOST_NAME_MAX + 1];
593         int index;
594         int rc;
595
596         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND,
597                                  PTL4LND, 0))
598                 return -1;
599
600         for (index = 0; ; index++) {
601                 LIBCFS_IOC_INIT(data);
602                 data.ioc_net     = g_net;
603                 data.ioc_count   = index;
604
605                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER, &data);
606                 if (rc != 0)
607                         break;
608
609                 if (g_net_is_compatible(NULL, SOCKLND, 0)) {
610                         id.nid = data.ioc_nid;
611                         id.pid = data.ioc_u32[4];
612                         printf("%-20s [%d]%s->%s:%d #%d\n",
613                                libcfs_id2str(id),
614                                data.ioc_count, /* persistence */
615                                /* my ip */
616                                ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
617                                                 sizeof(buffer[0]), 1),
618                                /* peer ip */
619                                ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
620                                                 sizeof(buffer[1]), 1),
621                                data.ioc_u32[1], /* peer port */
622                                data.ioc_u32[3]); /* conn_count */
623                 } else if (g_net_is_compatible(NULL, GNILND, 0)) {
624                         int disconn = data.ioc_flags >> 16;
625                         char *state;
626
627                         if (disconn)
628                                 state = "D";
629                         else
630                                 state = data.ioc_flags & 0xffff ? "C" : "U";
631
632                         printf("%-20s (%d) %s [%d] %ju sq %d/%d tx %d/%d/%d\n",
633                                libcfs_nid2str(data.ioc_nid), /* peer nid */
634                                data.ioc_net, /* gemini device id */
635                                state, /* peer is Connecting, Up, or Down */
636                                data.ioc_count,   /* peer refcount */
637                                (uintmax_t)data.ioc_u64[0], /* peerstamp */
638                                data.ioc_u32[2], data.ioc_u32[3], /* tx and rx seq */
639                                /* fmaq, nfma, nrdma */
640                                data.ioc_u32[0], data.ioc_u32[1],
641                                data.ioc_u32[4]);
642                 } else {
643                         printf("%-20s [%d]\n",
644                                libcfs_nid2str(data.ioc_nid), data.ioc_count);
645                 }
646         }
647
648         if (index == 0) {
649                 if (errno == ENOENT) {
650                         printf("<no peers>\n");
651                 } else {
652                         fprintf(stderr,
653                                 "Error getting peer list: %s: check dmesg.\n",
654                                 strerror(errno));
655                 }
656         }
657         return 0;
658 }
659
660 int jt_ptl_add_peer(int argc, char **argv)
661 {
662         struct libcfs_ioctl_data data;
663         lnet_nid_t nid;
664         __u32 ip = 0;
665         int port = 0;
666         int rc;
667
668         if (!g_net_is_compatible(argv[0], SOCKLND, GNILND, 0))
669                 return -1;
670
671         if (argc != 4) {
672                 fprintf(stderr, "usage(tcp,gni): %s nid ipaddr port\n",
673                         argv[0]);
674                 return 0;
675         }
676
677         nid = libcfs_str2nid(argv[1]);
678         if (nid == LNET_NID_ANY) {
679                 fprintf(stderr, "Can't parse NID: %s\n", argv[1]);
680                 return -1;
681         }
682
683         if (lnet_parse_ipaddr(&ip, argv[2]) != 0) {
684                 fprintf(stderr, "Can't parse ip addr: %s\n", argv[2]);
685                 return -1;
686         }
687
688         if (lnet_parse_port(&port, argv[3]) != 0) {
689                 fprintf(stderr, "Can't parse port: %s\n", argv[3]);
690                 return -1;
691         }
692
693         LIBCFS_IOC_INIT(data);
694         data.ioc_net    = g_net;
695         data.ioc_nid    = nid;
696         data.ioc_u32[0] = ip;
697         data.ioc_u32[1] = port;
698
699         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_PEER, &data);
700         if (rc != 0) {
701                 fprintf(stderr, "failed to add peer: %s\n",
702                         strerror(errno));
703                 return -1;
704         }
705
706         return 0;
707 }
708
709 int
710 jt_ptl_del_peer(int argc, char **argv)
711 {
712         struct libcfs_ioctl_data data;
713         lnet_nid_t nid = LNET_NID_ANY;
714         lnet_pid_t pid = LNET_PID_ANY;
715         __u32 ip = 0;
716         int rc;
717
718         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND,
719                                  PTL4LND, 0))
720                 return -1;
721
722         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
723                 if (argc > 3) {
724                         fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
725                         return 0;
726                 }
727         } else if (argc > 2) {
728                 fprintf(stderr, "usage: %s [nid]\n", argv[0]);
729                 return 0;
730         }
731
732         if (argc > 1 && !libcfs_str2anynid(&nid, argv[1])) {
733                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
734                 return -1;
735         }
736
737         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
738                 if (argc > 2 && lnet_parse_ipaddr(&ip, argv[2]) != 0) {
739                         fprintf(stderr, "Can't parse ip addr: %s\n", argv[2]);
740                         return -1;
741                 }
742         }
743
744         LIBCFS_IOC_INIT(data);
745         data.ioc_net    = g_net;
746         data.ioc_nid    = nid;
747         data.ioc_u32[0] = ip;
748         data.ioc_u32[1] = pid;
749
750         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_PEER, &data);
751         if (rc != 0) {
752                 fprintf(stderr, "failed to remove peer: %s\n", strerror(errno));
753                 return -1;
754         }
755
756         return 0;
757 }
758
759 int
760 jt_ptl_print_connections(int argc, char **argv)
761 {
762         struct libcfs_ioctl_data data;
763         struct lnet_process_id id;
764         char buffer[2][HOST_NAME_MAX + 1];
765         int index;
766         int rc;
767
768         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND, 0))
769                 return -1;
770
771         for (index = 0; ; index++) {
772                 LIBCFS_IOC_INIT(data);
773                 data.ioc_net     = g_net;
774                 data.ioc_count   = index;
775
776                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_CONN, &data);
777                 if (rc != 0)
778                         break;
779
780                 if (g_net_is_compatible(NULL, SOCKLND, 0)) {
781                         id.nid = data.ioc_nid;
782                         id.pid = data.ioc_u32[6];
783                         printf("%-20s %s[%d]%s->%s:%d %d/%d %s\n",
784                                libcfs_id2str(id),
785                                (data.ioc_u32[3] == SOCKLND_CONN_ANY) ? "A" :
786                                (data.ioc_u32[3] == SOCKLND_CONN_CONTROL) ? "C" :
787                                (data.ioc_u32[3] == SOCKLND_CONN_BULK_IN) ? "I" :
788                          (data.ioc_u32[3] == SOCKLND_CONN_BULK_OUT) ? "O" : "?",
789                                data.ioc_u32[4], /* scheduler */
790                                /* local IP addr */
791                                ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
792                                                 sizeof(buffer[0]), 1),
793                                /* remote IP addr */
794                                ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
795                                                 sizeof(buffer[1]), 1),
796                                data.ioc_u32[1],         /* remote port */
797                                data.ioc_count, /* tx buffer size */
798                                data.ioc_u32[5], /* rx buffer size */
799                                data.ioc_flags ? "nagle" : "nonagle");
800                 } else if (g_net_is_compatible(NULL, O2IBLND, 0)) {
801                         printf("%s mtu %d\n",
802                                libcfs_nid2str(data.ioc_nid),
803                                data.ioc_u32[0]); /* path MTU */
804                 } else if (g_net_is_compatible(NULL, GNILND, 0)) {
805                         printf("%-20s [%d]\n",
806                                libcfs_nid2str(data.ioc_nid),
807                                data.ioc_u32[0] /* device id */);
808                 } else {
809                         printf("%s\n", libcfs_nid2str(data.ioc_nid));
810                 }
811         }
812
813         if (index == 0) {
814                 if (errno == ENOENT) {
815                         printf("<no connections>\n");
816                 } else {
817                         fprintf(stderr,
818                                 "Error getting connection list: %s: check dmesg.\n",
819                                 strerror(errno));
820                 }
821         }
822         return 0;
823 }
824
825 int jt_ptl_disconnect(int argc, char **argv)
826 {
827         struct libcfs_ioctl_data data;
828         lnet_nid_t nid = LNET_NID_ANY;
829         __u32 ipaddr = 0;
830         int rc;
831
832         if (argc > 3) {
833                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
834                 return 0;
835         }
836
837         if (!g_net_is_compatible(NULL, SOCKLND, O2IBLND, GNILND, 0))
838                 return 0;
839
840         if (argc >= 2 && !libcfs_str2anynid(&nid, argv[1])) {
841                 fprintf(stderr, "Can't parse nid %s\n", argv[1]);
842                 return -1;
843         }
844
845         if (g_net_is_compatible(NULL, SOCKLND, 0) && argc >= 3 &&
846             lnet_parse_ipaddr(&ipaddr, argv[2]) != 0) {
847                 fprintf(stderr, "Can't parse ip addr %s\n", argv[2]);
848                 return -1;
849         }
850
851         LIBCFS_IOC_INIT(data);
852         data.ioc_net     = g_net;
853         data.ioc_nid     = nid;
854         data.ioc_u32[0]  = ipaddr;
855
856         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CLOSE_CONNECTION, &data);
857         if (rc != 0) {
858                 fprintf(stderr, "failed to remove connection: %s\n",
859                         strerror(errno));
860                 return -1;
861         }
862
863         return 0;
864 }
865
866 int jt_ptl_push_connection(int argc, char **argv)
867 {
868         struct libcfs_ioctl_data data;
869         int rc;
870         lnet_nid_t nid = LNET_NID_ANY;
871
872         if (argc > 2) {
873                 fprintf(stderr, "usage: %s [nid]\n", argv[0]);
874                 return 0;
875         }
876
877         if (!g_net_is_compatible(argv[0], SOCKLND, GNILND, 0))
878                 return -1;
879
880         if (argc > 1 && !libcfs_str2anynid(&nid, argv[1])) {
881                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
882                 return -1;
883         }
884
885         LIBCFS_IOC_INIT(data);
886         data.ioc_net     = g_net;
887         data.ioc_nid     = nid;
888
889         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PUSH_CONNECTION, &data);
890         if (rc != 0) {
891                 fprintf(stderr, "failed to push connection: %s\n",
892                         strerror(errno));
893                 return -1;
894         }
895
896         return 0;
897 }
898
899 int jt_ptl_ping(int argc, char **argv)
900 {
901         int rc;
902         int timeout;
903         struct lnet_process_id id;
904         struct lnet_process_id ids[16];
905         int maxids = sizeof(ids) / sizeof(ids[0]);
906         struct libcfs_ioctl_data data;
907         char *sep;
908         int i;
909
910         if (argc < 2) {
911                 fprintf(stderr, "usage: %s id [timeout (secs)]\n", argv[0]);
912                 return 0;
913         }
914
915         sep = strchr(argv[1], '-');
916         if (!sep) {
917                 rc = lnet_parse_nid(argv[1], &id);
918                 if (rc != 0)
919                         return -1;
920         } else {
921                 char   *end;
922
923                 if (argv[1][0] == 'u' || argv[1][0] == 'U')
924                         id.pid = strtoul(&argv[1][1], &end, 0) |
925                                 LNET_PID_USERFLAG;
926                 else
927                         id.pid = strtoul(argv[1], &end, 0);
928
929                 if (end != sep) { /* assuming '-' is part of hostname */
930                         rc = lnet_parse_nid(argv[1], &id);
931                         if (rc != 0)
932                                 return -1;
933                 } else {
934                         id.nid = libcfs_str2nid(sep + 1);
935
936                         if (id.nid == LNET_NID_ANY) {
937                                 fprintf(stderr,
938                                         "Can't parse process id \"%s\"\n",
939                                         argv[1]);
940                                 return -1;
941                         }
942                 }
943         }
944
945         if (argc > 2) {
946                 timeout = 1000 * atol(argv[2]);
947                 if (timeout > 120 * 1000) {
948                         fprintf(stderr, "Timeout %s is to large\n",
949                                 argv[2]);
950                         return -1;
951                 }
952         } else {
953                 timeout = 1000; /* default 1 second timeout */
954         }
955
956         LIBCFS_IOC_INIT(data);
957         data.ioc_nid     = id.nid;
958         data.ioc_u32[0]  = id.pid;
959         data.ioc_u32[1]  = timeout;
960         data.ioc_plen1   = sizeof(ids);
961         data.ioc_pbuf1   = (char *)ids;
962
963         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING, &data);
964         if (rc != 0) {
965                 fprintf(stderr, "failed to ping %s: %s\n",
966                         id.pid == LNET_PID_ANY ?
967                         libcfs_nid2str(id.nid) : libcfs_id2str(id),
968                         strerror(errno));
969                 return -1;
970         }
971
972         for (i = 0; i < data.ioc_count && i < maxids; i++)
973                 printf("%s\n", libcfs_id2str(ids[i]));
974
975         if (data.ioc_count > maxids)
976                 printf("%d out of %d ids listed\n", maxids, data.ioc_count);
977
978         return 0;
979 }
980
981 int jt_ptl_mynid(int argc, char **argv)
982 {
983         struct libcfs_ioctl_data data;
984         lnet_nid_t nid;
985         int rc;
986
987         if (argc != 2) {
988                 fprintf(stderr, "usage: %s NID\n", argv[0]);
989                 return 0;
990         }
991
992         nid = libcfs_str2nid(argv[1]);
993         if (nid == LNET_NID_ANY) {
994                 fprintf(stderr, "Can't parse NID '%s'\n", argv[1]);
995                 return -1;
996         }
997
998         LIBCFS_IOC_INIT(data);
999         data.ioc_net = LNET_NIDNET(nid);
1000         data.ioc_nid = nid;
1001
1002         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_REGISTER_MYNID, &data);
1003         if (rc < 0)
1004                 fprintf(stderr, "setting my NID failed: %s\n",
1005                         strerror(errno));
1006         else
1007                 printf("registered my nid %s\n", libcfs_nid2str(nid));
1008
1009         return 0;
1010 }
1011
1012 int
1013 jt_ptl_fail_nid(int argc, char **argv)
1014 {
1015         int rc;
1016         lnet_nid_t nid;
1017         int threshold;
1018         struct libcfs_ioctl_data data;
1019
1020         if (argc < 2 || argc > 3) {
1021                 fprintf(stderr, "usage: %s nid|\"*\" [count (0 == mend)]\n",
1022                         argv[0]);
1023                 return 0;
1024         }
1025
1026         if (!libcfs_str2anynid(&nid, argv[1])) {
1027                 fprintf(stderr, "Can't parse nid \"%s\"\n", argv[1]);
1028                 return -1;
1029         }
1030
1031         if (argc < 3) {
1032                 threshold = LNET_MD_THRESH_INF;
1033         } else if (sscanf(argv[2], "%i", &threshold) != 1) {
1034                 fprintf(stderr, "Can't parse count \"%s\"\n", argv[2]);
1035                 return -1;
1036         }
1037
1038         LIBCFS_IOC_INIT(data);
1039         data.ioc_nid = nid;
1040         data.ioc_count = threshold;
1041
1042         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_FAIL_NID, &data);
1043         if (rc < 0)
1044                 fprintf(stderr, "IOC_LIBCFS_FAIL_NID failed: %s\n",
1045                         strerror(errno));
1046         else
1047                 printf("%s %s\n",
1048                        threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1049
1050         return 0;
1051 }
1052
1053 int
1054 jt_ptl_add_route(int argc, char **argv)
1055 {
1056         struct lnet_ioctl_config_data data;
1057         lnet_nid_t gateway_nid;
1058         __u32 hops = LNET_UNDEFINED_HOPS;
1059         unsigned int priority = 0;
1060         char *end;
1061         int rc;
1062
1063         if (argc < 2 || argc > 4) {
1064                 fprintf(stderr, "usage: %s gateway [hopcount [priority]]\n",
1065                         argv[0]);
1066                 return -1;
1067         }
1068
1069         if (g_net_is_set(argv[0]) == 0)
1070                 return -1;
1071
1072         gateway_nid = libcfs_str2nid(argv[1]);
1073         if (gateway_nid == LNET_NID_ANY) {
1074                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1075                 return -1;
1076         }
1077
1078         if (argc > 2) {
1079                 hops = strtol(argv[2], &end, 0);
1080                 if (hops == 0 || hops >= 256 ||
1081                     (end && *end != 0)) {
1082                         fprintf(stderr, "Can't parse hopcount \"%s\"\n",
1083                                 argv[2]);
1084                         return -1;
1085                 }
1086                 if (argc == 4) {
1087                         priority = strtoul(argv[3], &end, 0);
1088                         if (end && *end != 0) {
1089                                 fprintf(stderr,
1090                                         "Can't parse priority \"%s\"\n",
1091                                         argv[3]);
1092                                 return -1;
1093                         }
1094                 }
1095         }
1096
1097         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1098         data.cfg_net = g_net;
1099         data.cfg_config_u.cfg_route.rtr_hop = hops;
1100         data.cfg_nid = gateway_nid;
1101         data.cfg_config_u.cfg_route.rtr_priority = priority;
1102
1103         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
1104         if (rc != 0) {
1105                 fprintf(stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n",
1106                         strerror(errno));
1107                 return -1;
1108         }
1109
1110         return 0;
1111 }
1112
1113 int
1114 jt_ptl_del_route(int argc, char **argv)
1115 {
1116         struct lnet_ioctl_config_data data;
1117         lnet_nid_t nid;
1118         int rc;
1119
1120         if (argc != 2) {
1121                 fprintf(stderr, "usage: %s gatewayNID\n", argv[0]);
1122                 return 0;
1123         }
1124
1125         if (libcfs_str2anynid(&nid, argv[1]) == 0) {
1126                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1127                 return -1;
1128         }
1129
1130         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1131         data.cfg_net = g_net_set ? g_net : LNET_NIDNET(LNET_NID_ANY);
1132         data.cfg_nid = nid;
1133
1134         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
1135         if (rc != 0) {
1136                 fprintf(stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n",
1137                         libcfs_nid2str(nid), strerror(errno));
1138                 return -1;
1139         }
1140
1141         return 0;
1142 }
1143
1144 int
1145 jt_ptl_notify_router(int argc, char **argv)
1146 {
1147         struct libcfs_ioctl_data data;
1148         int enable;
1149         lnet_nid_t nid;
1150         int rc;
1151         struct timeval now;
1152         time_t when;
1153
1154         if (argc < 3) {
1155                 fprintf(stderr, "usage: %s targetNID <up/down> [<time>]\n",
1156                         argv[0]);
1157                 return 0;
1158         }
1159
1160         nid = libcfs_str2nid(argv[1]);
1161         if (nid == LNET_NID_ANY) {
1162                 fprintf(stderr, "Can't parse target NID \"%s\"\n", argv[1]);
1163                 return -1;
1164         }
1165
1166         if (lnet_parse_bool (&enable, argv[2]) != 0) {
1167                 fprintf(stderr, "Can't parse boolean %s\n", argv[2]);
1168                 return -1;
1169         }
1170
1171         gettimeofday(&now, NULL);
1172
1173         if (argc < 4) {
1174                 when = now.tv_sec;
1175         } else if (lnet_parse_time(&when, argv[3]) != 0) {
1176                 fprintf(stderr,
1177                         "Can't parse time %s\n Please specify either 'YYYY-MM-DD-HH:MM:SS'\n or an absolute unix time in seconds\n",
1178                         argv[3]);
1179                 return -1;
1180         } else if (when > now.tv_sec) {
1181                 fprintf(stderr, "%s specifies a time in the future\n",
1182                         argv[3]);
1183                 return -1;
1184         }
1185
1186         LIBCFS_IOC_INIT(data);
1187         data.ioc_nid = nid;
1188         data.ioc_flags = enable;
1189         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
1190         data.ioc_u64[0] = (__u64)when;
1191
1192         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_NOTIFY_ROUTER, &data);
1193         if (rc != 0) {
1194                 fprintf(stderr, "IOC_LIBCFS_NOTIFY_ROUTER (%s) failed: %s\n",
1195                         libcfs_nid2str(nid), strerror(errno));
1196                 return -1;
1197         }
1198
1199         return 0;
1200 }
1201
1202 int
1203 jt_ptl_print_routes(int argc, char **argv)
1204 {
1205         struct lnet_ioctl_config_data  data;
1206         int rc;
1207         int index;
1208         __u32 net;
1209         lnet_nid_t nid;
1210         unsigned int hops;
1211         int alive;
1212         unsigned int pri;
1213
1214         for (index = 0; ; index++) {
1215                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
1216                 data.cfg_count = index;
1217
1218                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
1219                 if (rc != 0)
1220                         break;
1221
1222                 net     = data.cfg_net;
1223                 hops    = data.cfg_config_u.cfg_route.rtr_hop;
1224                 nid     = data.cfg_nid;
1225                 alive   = data.cfg_config_u.cfg_route.rtr_flags & LNET_RT_ALIVE;
1226                 pri     = data.cfg_config_u.cfg_route.rtr_priority;
1227
1228                 printf("net %18s hops %u gw %32s %s pri %u\n",
1229                        libcfs_net2str(net), hops,
1230                        libcfs_nid2str(nid), alive ? "up" : "down", pri);
1231         }
1232
1233         if (errno != ENOENT)
1234                 fprintf(stderr, "Error getting routes: %s: check dmesg.\n",
1235                         strerror(errno));
1236
1237         return 0;
1238 }
1239
1240 static int
1241 fault_attr_nid_parse(char *str, lnet_nid_t *nid_p)
1242 {
1243         lnet_nid_t nid;
1244         __u32 net;
1245         int rc = 0;
1246
1247         /* NB: can't support range ipaddress except * and *@net */
1248         if (strlen(str) > 2 && str[0] == '*' && str[1] == '@') {
1249                 net = libcfs_str2net(str + 2);
1250                 if (net == LNET_NIDNET(LNET_NID_ANY))
1251                         goto failed;
1252
1253                 nid = LNET_MKNID(net, LNET_NIDADDR(LNET_NID_ANY));
1254         } else {
1255                 rc = libcfs_str2anynid(&nid, str);
1256                 if (!rc)
1257                         goto failed;
1258         }
1259
1260         *nid_p = nid;
1261         return 0;
1262 failed:
1263         fprintf(stderr, "Invalid NID : %s\n", str);
1264         return -1;
1265 }
1266
1267 static int
1268 fault_attr_msg_parse(char *msg_str, __u32 *mask_p)
1269 {
1270         if (!strcasecmp(msg_str, "put")) {
1271                 *mask_p |= LNET_PUT_BIT;
1272                 return 0;
1273
1274         } else if (!strcasecmp(msg_str, "ack")) {
1275                 *mask_p |= LNET_ACK_BIT;
1276                 return 0;
1277
1278         } else if (!strcasecmp(msg_str, "get")) {
1279                 *mask_p |= LNET_GET_BIT;
1280                 return 0;
1281
1282         } else if (!strcasecmp(msg_str, "reply")) {
1283                 *mask_p |= LNET_REPLY_BIT;
1284                 return 0;
1285         }
1286
1287         fprintf(stderr, "unknown message type %s\n", msg_str);
1288         return -1;
1289 }
1290
1291 static int
1292 fault_attr_ptl_parse(char *ptl_str, __u64 *mask_p)
1293 {
1294         unsigned long rc = strtoul(optarg, NULL, 0);
1295
1296         if (rc >= 64) {
1297                 fprintf(stderr, "invalid portal: %lu\n", rc);
1298                 return -1;
1299         }
1300
1301         *mask_p |= (1ULL << rc);
1302         return 0;
1303 }
1304
1305 static int
1306 fault_attr_health_error_parse(char *error, __u32 *mask)
1307 {
1308         if (!strcasecmp(error, "local_interrupt")) {
1309                 *mask |= HSTATUS_LOCAL_INTERRUPT_BIT;
1310                 return 0;
1311         }
1312         if (!strcasecmp(error, "local_dropped")) {
1313                 *mask |= HSTATUS_LOCAL_DROPPED_BIT;
1314                 return 0;
1315         }
1316         if (!strcasecmp(error, "local_aborted")) {
1317                 *mask |= HSTATUS_LOCAL_ABORTED_BIT;
1318                 return 0;
1319         }
1320         if (!strcasecmp(error, "local_no_route")) {
1321                 *mask |= HSTATUS_LOCAL_NO_ROUTE_BIT;
1322                 return 0;
1323         }
1324         if (!strcasecmp(error, "local_error")) {
1325                 *mask |= HSTATUS_LOCAL_ERROR_BIT;
1326                 return 0;
1327         }
1328         if (!strcasecmp(error, "local_timeout")) {
1329                 *mask |= HSTATUS_LOCAL_TIMEOUT_BIT;
1330                 return 0;
1331         }
1332         if (!strcasecmp(error, "remote_error")) {
1333                 *mask |= HSTATUS_REMOTE_ERROR_BIT;
1334                 return 0;
1335         }
1336         if (!strcasecmp(error, "remote_dropped")) {
1337                 *mask |= HSTATUS_REMOTE_DROPPED_BIT;
1338                 return 0;
1339         }
1340         if (!strcasecmp(error, "remote_timeout")) {
1341                 *mask |= HSTATUS_REMOTE_TIMEOUT_BIT;
1342                 return 0;
1343         }
1344         if (!strcasecmp(error, "network_timeout")) {
1345                 *mask |= HSTATUS_NETWORK_TIMEOUT_BIT;
1346                 return 0;
1347         }
1348         if (!strcasecmp(error, "random")) {
1349                 *mask = HSTATUS_RANDOM;
1350                 return 0;
1351         }
1352
1353         return -1;
1354 }
1355
1356 static int
1357 fault_simul_rule_add(__u32 opc, char *name, int argc, char **argv)
1358 {
1359         struct libcfs_ioctl_data  data = { { 0 } };
1360         struct lnet_fault_attr    attr;
1361         char *optstr;
1362         int rc;
1363
1364         static const struct option opts[] = {
1365         { .name = "source",   .has_arg = required_argument, .val = 's' },
1366         { .name = "dest",     .has_arg = required_argument, .val = 'd' },
1367         { .name = "rate",     .has_arg = required_argument, .val = 'r' },
1368         { .name = "interval", .has_arg = required_argument, .val = 'i' },
1369         { .name = "random",   .has_arg = no_argument,       .val = 'n' },
1370         { .name = "latency",  .has_arg = required_argument, .val = 'l' },
1371         { .name = "portal",   .has_arg = required_argument, .val = 'p' },
1372         { .name = "message",  .has_arg = required_argument, .val = 'm' },
1373         { .name = "health_error",  .has_arg = required_argument, .val = 'e' },
1374         { .name = "local_nid",  .has_arg = required_argument, .val = 'o' },
1375         { .name = "drop_all",  .has_arg = no_argument, .val = 'x' },
1376         { .name = NULL } };
1377
1378         if (argc == 1) {
1379                 fprintf(stderr,
1380                         "Failed, please provide source, destination and rate of rule\n");
1381                 return -1;
1382         }
1383
1384         optstr = opc == LNET_CTL_DROP_ADD ? "s:d:o:r:i:p:m:e:nx" : "s:d:o:r:l:p:m:";
1385         memset(&attr, 0, sizeof(attr));
1386         while (1) {
1387                 int c = getopt_long(argc, argv, optstr, opts, NULL);
1388
1389                 if (c == -1)
1390                         break;
1391
1392                 switch (c) {
1393                 case 'o':
1394                         rc = fault_attr_nid_parse(optarg, &attr.fa_local_nid);
1395                         if (rc != 0)
1396                                 goto getopt_failed;
1397                         break;
1398                 case 's': /* source NID/NET */
1399                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
1400                         if (rc != 0)
1401                                 goto getopt_failed;
1402                         break;
1403
1404                 case 'd': /* dest NID/NET */
1405                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
1406                         if (rc != 0)
1407                                 goto getopt_failed;
1408                         break;
1409
1410                 case 'r': /* drop rate */
1411                         if (opc == LNET_CTL_DROP_ADD)
1412                                 attr.u.drop.da_rate = strtoul(optarg, NULL, 0);
1413                         else
1414                                 attr.u.delay.la_rate = strtoul(optarg, NULL, 0);
1415                         break;
1416
1417                 case 'e':
1418                         if (opc == LNET_CTL_DROP_ADD) {
1419                                 rc = fault_attr_health_error_parse(optarg,
1420                                                                    &attr.u.drop.da_health_error_mask);
1421                                 if (rc)
1422                                         goto getopt_failed;
1423                         }
1424                         break;
1425
1426                 case 'x':
1427                         if (opc == LNET_CTL_DROP_ADD)
1428                                 attr.u.drop.da_drop_all = true;
1429                         break;
1430
1431                 case 'n':
1432                         if (opc == LNET_CTL_DROP_ADD)
1433                                 attr.u.drop.da_random = true;
1434                         break;
1435
1436                 case 'i': /* time interval (# seconds) for message drop */
1437                         if (opc == LNET_CTL_DROP_ADD)
1438                                 attr.u.drop.da_interval = strtoul(optarg,
1439                                                                   NULL, 0);
1440                         else
1441                                 attr.u.delay.la_interval = strtoul(optarg,
1442                                                                    NULL, 0);
1443                         break;
1444
1445                 case 'l': /* seconds to wait before activating rule */
1446                         attr.u.delay.la_latency = strtoul(optarg, NULL, 0);
1447                         break;
1448
1449                 case 'p': /* portal to filter */
1450                         rc = fault_attr_ptl_parse(optarg, &attr.fa_ptl_mask);
1451                         if (rc != 0)
1452                                 goto getopt_failed;
1453                         break;
1454
1455                 case 'm': /* message types to filter */
1456                         rc = fault_attr_msg_parse(optarg, &attr.fa_msg_mask);
1457                         if (rc != 0)
1458                                 goto getopt_failed;
1459                         break;
1460
1461                 default:
1462                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
1463                                 argv[0], argv[optind - 1]);
1464                         goto getopt_failed;
1465                 }
1466         }
1467         optind = 1;
1468
1469         if (opc == LNET_CTL_DROP_ADD) {
1470                 /* NB: drop rate and interval are exclusive to each other */
1471                 if (!((attr.u.drop.da_rate == 0) ^
1472                       (attr.u.drop.da_interval == 0))) {
1473                         fprintf(stderr,
1474                                 "please provide either drop rate or interval but not both at the same time.\n");
1475                         return -1;
1476                 }
1477
1478                 if (attr.u.drop.da_random &&
1479                     attr.u.drop.da_interval == 0) {
1480                         fprintf(stderr,
1481                                 "please provide an interval to randomize\n");
1482                         return -1;
1483                 }
1484         } else if (opc == LNET_CTL_DELAY_ADD) {
1485                 if (!((attr.u.delay.la_rate == 0) ^
1486                       (attr.u.delay.la_interval == 0))) {
1487                         fprintf(stderr,
1488                                 "please provide either delay rate or interval but not both at the same time.\n");
1489                         return -1;
1490                 }
1491
1492                 if (attr.u.delay.la_latency == 0) {
1493                         fprintf(stderr, "latency cannot be zero\n");
1494                         return -1;
1495                 }
1496         }
1497
1498         if (attr.fa_src == 0 || attr.fa_dst == 0) {
1499                 fprintf(stderr,
1500                         "Please provide both source and destination of %s rule\n",
1501                         name);
1502                 return -1;
1503         }
1504
1505         if (attr.fa_local_nid == 0)
1506                 attr.fa_local_nid = LNET_NID_ANY;
1507
1508         data.ioc_flags = opc;
1509         data.ioc_inllen1 = sizeof(attr);
1510         data.ioc_inlbuf1 = (char *)&attr;
1511         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
1512                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
1513                 return -1;
1514         }
1515
1516         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
1517         if (rc != 0) {
1518                 fprintf(stderr, "add %s rule %s->%s failed: %s\n",
1519                         name, libcfs_nid2str(attr.fa_src),
1520                         libcfs_nid2str(attr.fa_dst), strerror(errno));
1521                 return -1;
1522         }
1523
1524         printf("Added %s rule %s->%s (1/%d)\n",
1525                name, libcfs_nid2str(attr.fa_src), libcfs_nid2str(attr.fa_dst),
1526                opc == LNET_CTL_DROP_ADD ?
1527                attr.u.drop.da_rate : attr.u.delay.la_rate);
1528         return 0;
1529
1530 getopt_failed:
1531         optind = 1;
1532         return -1;
1533 }
1534
1535 int
1536 jt_ptl_drop_add(int argc, char **argv)
1537 {
1538         return fault_simul_rule_add(LNET_CTL_DROP_ADD, "drop", argc, argv);
1539 }
1540
1541 int
1542 jt_ptl_delay_add(int argc, char **argv)
1543 {
1544         return fault_simul_rule_add(LNET_CTL_DELAY_ADD, "delay", argc, argv);
1545 }
1546
1547 static int
1548 fault_simul_rule_del(__u32 opc, char *name, int argc, char **argv)
1549 {
1550         struct libcfs_ioctl_data data = { { 0 } };
1551         struct lnet_fault_attr   attr;
1552         bool all = false;
1553         int rc;
1554
1555         static const struct option opts[] = {
1556                 { .name = "source", .has_arg = required_argument, .val = 's' },
1557                 { .name = "dest",   .has_arg = required_argument, .val = 'd' },
1558                 { .name = "all",    .has_arg = no_argument,       .val = 'a' },
1559                 { .name = NULL } };
1560
1561         if (argc == 1) {
1562                 fprintf(stderr,
1563                         "Failed, please provide source and destination of rule\n");
1564                 return -1;
1565         }
1566
1567         memset(&attr, 0, sizeof(attr));
1568         while (1) {
1569                 int c = getopt_long(argc, argv, "s:d:a", opts, NULL);
1570
1571                 if (c == -1 || all)
1572                         break;
1573
1574                 switch (c) {
1575                 case 's':
1576                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
1577                         if (rc != 0)
1578                                 goto getopt_failed;
1579                         break;
1580                 case 'd':
1581                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
1582                         if (rc != 0)
1583                                 goto getopt_failed;
1584                         break;
1585                 case 'a':
1586                         attr.fa_src = 0;
1587                         attr.fa_dst = 0;
1588                         all = true;
1589
1590                         break;
1591                 default:
1592                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
1593                                 argv[0], argv[optind - 1]);
1594                         goto getopt_failed;
1595                 }
1596         }
1597         optind = 1;
1598
1599         data.ioc_flags = opc;
1600         data.ioc_inllen1 = sizeof(attr);
1601         data.ioc_inlbuf1 = (char *)&attr;
1602         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
1603                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
1604                 return -1;
1605         }
1606
1607         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
1608         if (rc != 0) {
1609                 fprintf(stderr, "remove %s rule %s->%s failed: %s\n", name,
1610                         all ? "all" : libcfs_nid2str(attr.fa_src),
1611                         all ? "all" : libcfs_nid2str(attr.fa_dst),
1612                         strerror(errno));
1613                 return -1;
1614         }
1615
1616         libcfs_ioctl_unpack(&data, ioc_buf);
1617         printf("Removed %d %s rules\n", data.ioc_count, name);
1618         return 0;
1619
1620 getopt_failed:
1621         optind = 1;
1622         return -1;
1623 }
1624
1625 int
1626 jt_ptl_drop_del(int argc, char **argv)
1627 {
1628         return fault_simul_rule_del(LNET_CTL_DROP_DEL, "drop", argc, argv);
1629 }
1630
1631 int
1632 jt_ptl_delay_del(int argc, char **argv)
1633 {
1634         return fault_simul_rule_del(LNET_CTL_DELAY_DEL, "delay", argc, argv);
1635 }
1636
1637 static int
1638 fault_simul_rule_reset(__u32 opc, char *name, int argc, char **argv)
1639 {
1640         struct libcfs_ioctl_data   data = { { 0 } };
1641         int                        rc;
1642
1643         LIBCFS_IOC_INIT(data);
1644         data.ioc_flags = opc;
1645
1646         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, &data);
1647         if (rc != 0) {
1648                 fprintf(stderr, "failed to reset %s stats: %s\n",
1649                         name, strerror(errno));
1650                 return -1;
1651         }
1652         return 0;
1653 }
1654
1655 int
1656 jt_ptl_drop_reset(int argc, char **argv)
1657 {
1658         return fault_simul_rule_reset(LNET_CTL_DROP_RESET, "drop", argc, argv);
1659 }
1660
1661 int
1662 jt_ptl_delay_reset(int argc, char **argv)
1663 {
1664         return fault_simul_rule_reset(LNET_CTL_DELAY_RESET, "delay",
1665                                       argc, argv);
1666 }
1667
1668 static int
1669 fault_simul_rule_list(__u32 opc, char *name, int argc, char **argv)
1670 {
1671         struct libcfs_ioctl_data data = { { 0 } };
1672         struct lnet_fault_attr   attr;
1673         struct lnet_fault_stat   stat;
1674         int pos;
1675
1676         printf("LNet %s rules:\n", name);
1677         for (pos = 0;; pos++) {
1678                 int rc;
1679
1680                 memset(&attr, 0, sizeof(attr));
1681                 memset(&stat, 0, sizeof(stat));
1682
1683                 data.ioc_count = pos;
1684                 data.ioc_flags = opc;
1685                 data.ioc_inllen1 = sizeof(attr);
1686                 data.ioc_inlbuf1 = (char *)&attr;
1687                 data.ioc_inllen2 = sizeof(stat);
1688                 data.ioc_inlbuf2 = (char *)&stat;
1689                 if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
1690                         fprintf(stderr, "libcfs_ioctl_pack failed\n");
1691                         return -1;
1692                 }
1693
1694                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
1695                 if (rc != 0)
1696                         break;
1697
1698                 libcfs_ioctl_unpack(&data, ioc_buf);
1699
1700                 if (opc == LNET_CTL_DROP_LIST) {
1701                         printf("%s->%s (1/%d | %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
1702                                libcfs_nid2str(attr.fa_src),
1703                                libcfs_nid2str(attr.fa_dst),
1704                                attr.u.drop.da_rate, attr.u.drop.da_interval,
1705                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
1706                                (uintmax_t)stat.u.drop.ds_dropped,
1707                                (uintmax_t)stat.fs_count,
1708                                (uintmax_t)stat.fs_put,
1709                                (uintmax_t)stat.fs_ack,
1710                                (uintmax_t)stat.fs_get,
1711                                (uintmax_t)stat.fs_reply);
1712
1713                 } else if (opc == LNET_CTL_DELAY_LIST) {
1714                         printf("%s->%s (1/%d | %d, latency %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
1715                                libcfs_nid2str(attr.fa_src),
1716                                libcfs_nid2str(attr.fa_dst),
1717                                attr.u.delay.la_rate, attr.u.delay.la_interval,
1718                                attr.u.delay.la_latency,
1719                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
1720                                (uintmax_t)stat.u.delay.ls_delayed,
1721                                (uintmax_t)stat.fs_count,
1722                                (uintmax_t)stat.fs_put,
1723                                (uintmax_t)stat.fs_ack,
1724                                (uintmax_t)stat.fs_get,
1725                                (uintmax_t)stat.fs_reply);
1726                 }
1727         }
1728         printf("found total %d\n", pos);
1729
1730         return 0;
1731 }
1732
1733 int
1734 jt_ptl_drop_list(int argc, char **argv)
1735 {
1736         return fault_simul_rule_list(LNET_CTL_DROP_LIST, "drop", argc, argv);
1737 }
1738
1739 int
1740 jt_ptl_delay_list(int argc, char **argv)
1741 {
1742         return fault_simul_rule_list(LNET_CTL_DELAY_LIST, "delay", argc, argv);
1743 }
1744
1745 double
1746 get_cycles_per_usec()
1747 {
1748         FILE *f = fopen("/proc/cpuinfo", "r");
1749         double mhz;
1750         char line[64];
1751
1752         if (f) {
1753                 while (fgets(line, sizeof(line), f))
1754                         if (sscanf(line, "cpu MHz : %lf", &mhz) == 1) {
1755                                 fclose(f);
1756                                 return mhz;
1757                         }
1758                 fclose(f);
1759         }
1760
1761         fprintf(stderr, "Can't read/parse /proc/cpuinfo\n");
1762         return 1000.0;
1763 }
1764
1765 int jt_ptl_testprotocompat(int argc, char **argv)
1766 {
1767         struct libcfs_ioctl_data  data;
1768         int rc;
1769         int flags;
1770         char *end;
1771
1772         if (argc < 2)  {
1773                 fprintf(stderr, "usage: %s <number>\n", argv[0]);
1774                 return 0;
1775         }
1776
1777         flags = strtol(argv[1], &end, 0);
1778         if (flags < 0 || *end != 0) {
1779                 fprintf(stderr, "Can't parse flags '%s'\n", argv[1]);
1780                 return -1;
1781         }
1782
1783         LIBCFS_IOC_INIT(data);
1784         data.ioc_flags = flags;
1785         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_TESTPROTOCOMPAT, &data);
1786
1787         if (rc != 0) {
1788                 fprintf(stderr, "test proto compat %x failed: %s\n",
1789                         flags, strerror(errno));
1790                 return -1;
1791         }
1792
1793         printf("test proto compat %x OK\n", flags);
1794         return 0;
1795 }