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