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