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