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