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