Whamcloud - gitweb
LU-10003 lnet: implement Netlink version of lnet distance API.
[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 <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <time.h>
39 #include <linux/types.h>
40
41 #include <libcfs/util/ioctl.h>
42 #include <linux/lnet/libcfs_debug.h>
43 #include <linux/lnet/lnet-dlc.h>
44 #include <linux/lnet/lnetctl.h>
45 #include <linux/lnet/nidstr.h>
46 #include <linux/lnet/socklnd.h>
47 #include <lnetconfig/liblnetconfig.h>
48 #include <lustre/lustreapi.h>
49 #include <lustre_ioctl_old.h>
50
51 unsigned int libcfs_debug;
52 unsigned int libcfs_printk = D_CANTMASK;
53
54 static bool  g_net_interactive;
55 static bool  g_net_set;
56 static __u32 g_net;
57
58 #define IOC_BUF_SIZE    8192
59 static char local_buf[IOC_BUF_SIZE];
60 static char *ioc_buf = local_buf;
61
62 /* Convert a string boolean to an int; "enable" -> 1 */
63 int
64 lnet_parse_bool (int *b, char *str)
65 {
66         if (!strcasecmp(str, "no") ||
67             !strcasecmp(str, "n") ||
68             !strcasecmp(str, "off") ||
69             !strcasecmp(str, "down") ||
70             !strcasecmp(str, "disable")) {
71                 *b = 0;
72
73                 return 0;
74         }
75
76         if (!strcasecmp(str, "yes") ||
77             !strcasecmp(str, "y") ||
78             !strcasecmp(str, "on") ||
79             !strcasecmp(str, "up") ||
80             !strcasecmp(str, "enable")) {
81                 *b = 1;
82
83                 return 0;
84         }
85
86         return -1;
87 }
88
89 int
90 lnet_parse_port(int *port, char *str)
91 {
92         char *end;
93
94         *port = strtol(str, &end, 0);
95
96         if (*end == 0 &&                        /* parsed whole string */
97             *port > 0 && *port < 65536)         /* minimal sanity check */
98                 return 0;
99
100         return -1;
101 }
102
103 int
104 lnet_parse_ipquad(__u32 *ipaddrp, char *str)
105 {
106         int a, b, c, d;
107
108         if (sscanf(str, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 &&
109             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
110             (c & ~0xff) == 0 && (d & ~0xff) == 0) {
111                 *ipaddrp = (a << 24) | (b << 16) | (c << 8) | d;
112
113                 return 0;
114         }
115
116         return -1;
117 }
118
119 int
120 lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
121 {
122         struct addrinfo *ai = NULL;
123         struct addrinfo *aip = NULL;
124         struct addrinfo hints;
125         int err = 0;
126         int rc = -1;
127
128         if (!strcmp(str, "_all_")) {
129                 *ipaddrp = 0;
130                 return 0;
131         }
132
133         if (lnet_parse_ipquad(ipaddrp, str) == 0)
134                 return 0;
135
136         memset(&hints, 0, sizeof(struct addrinfo));
137         hints.ai_family = AF_INET;
138
139         if (('a' <= str[0] && str[0] <= 'z') ||
140             ('A' <= str[0] && str[0] <= 'Z')) {
141                 err = getaddrinfo(str, NULL, &hints, &ai);
142                 if (err != 0) {
143                         fprintf(stderr,
144                                 "failed to get addrinfo for %s: %s\n",
145                                 str, gai_strerror(err));
146                         return -1;
147                 }
148
149                 for (aip = ai; aip; aip = aip->ai_next) {
150                         if (aip->ai_family == AF_INET && aip->ai_addr) {
151                                 struct sockaddr_in *sin =
152                                         (void *)ai->ai_addr;
153
154                                 __u32 addr = (__u32)sin->sin_addr.s_addr;
155                                 *ipaddrp = ntohl(addr);
156                                 break;
157                         }
158                 }
159                 /* FIXME: handle AF_INET6 */
160
161                 if (!aip) {
162                         fprintf(stderr, "failed to get IP address for %s\n",
163                                 str);
164                         rc = -1;
165                         goto out;
166                 }
167
168                 rc = 0;
169                 goto out;
170         }
171
172 out:
173         if (ai != NULL)
174                 freeaddrinfo(ai);
175         return rc;
176 }
177
178 char *
179 ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup)
180 {
181         struct sockaddr_in srcaddr;
182
183         if (lookup) {
184                 memset(&srcaddr, 0, sizeof(srcaddr));
185                 srcaddr.sin_family = AF_INET;
186                 srcaddr.sin_addr.s_addr = (in_addr_t)htonl(ipaddr);
187
188                 if (getnameinfo((struct sockaddr *)&srcaddr, sizeof(srcaddr),
189                                   str, strsize, NULL, 0, 0) == 0)
190                         goto out;
191         }
192
193         snprintf(str, strsize, "%d.%d.%d.%d",
194                  (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
195                  (ipaddr >> 8) & 0xff, ipaddr & 0xff);
196 out:
197         return str;
198 }
199
200 int
201 lnet_parse_time(time_t *t, char *str)
202 {
203         char *end;
204         int n;
205         struct tm tm;
206
207         *t = strtol(str, &end, 0);
208         if (*end == 0) /* parsed whole string */
209                 return 0;
210
211         memset(&tm, 0, sizeof(tm));
212         n = sscanf(str, "%d-%d-%d-%d:%d:%d",
213                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
214                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
215         if (n != 6)
216                 return -1;
217
218         tm.tm_mon--;                    /* convert to 0 == Jan */
219         tm.tm_year -= 1900;             /* y2k quirk */
220         tm.tm_isdst = -1;               /* dunno if it's daylight savings... */
221
222         *t = mktime(&tm);
223         if (*t == (time_t)-1)
224                 return -1;
225
226         return 0;
227 }
228
229 int
230 lnet_parse_nid(char *nid_str, struct lnet_process_id *id_ptr)
231 {
232         id_ptr->pid = LNET_PID_ANY;
233         id_ptr->nid = libcfs_str2nid(nid_str);
234         if (id_ptr->nid == LNET_NID_ANY) {
235                 fprintf(stderr, "Can't parse nid \"%s\"\n", nid_str);
236                 return -1;
237         }
238
239         return 0;
240 }
241
242 static int g_net_is_set(char *cmd)
243 {
244         if (g_net_set)
245                 return 1;
246
247         if (cmd) {
248                 char *net;
249
250                 if (g_net_interactive)
251                         net = "network";
252                 else
253                         net = "--net";
254
255                 fprintf(stderr,
256                         "You must run '%s <network>' command before '%s'\n",
257                         cmd, net);
258                 return 0;
259         }
260
261         return 0;
262 }
263
264 static int g_net_is_compatible(char *cmd, ...)
265 {
266         va_list ap;
267         int nal;
268
269         if (!g_net_is_set(cmd))
270                 return 0;
271
272         va_start(ap, cmd);
273
274         do {
275                 nal = va_arg(ap, int);
276                 if (nal == LNET_NETTYP(g_net)) {
277                         va_end(ap);
278                         return 1;
279                 }
280         } while (nal != 0);
281
282         va_end(ap);
283
284         if (cmd)
285                 fprintf(stderr, "Command %s not compatible with %s NAL\n",
286                         cmd, libcfs_lnd2str(LNET_NETTYP(g_net)));
287
288         return 0;
289 }
290
291 int ptl_initialize(int argc, char **argv)
292 {
293         if (argc > 1)
294                 g_net_interactive = true;
295
296         register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH);
297
298         return 0;
299 }
300
301 int jt_ptl_network(int argc, char **argv)
302 {
303         struct libcfs_ioctl_data data;
304         __u32 net = LNET_NET_ANY;
305         int rc;
306
307         if (argc != 2) {
308                 fprintf(stderr, "usage: %s <net>|up|down\n", argv[0]);
309                 return -1;
310         }
311
312         if (!strcmp(argv[1], "unconfigure") || !strcmp(argv[1], "down")) {
313                 LIBCFS_IOC_INIT(data);
314                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_UNCONFIGURE, &data);
315
316                 if (rc == 0) {
317                         printf("LNET ready to unload\n");
318                         return 0;
319                 }
320
321                 if (errno == ENODEV) {
322                         printf("LNET is currently not loaded.");
323                         return 0;
324                 }
325
326                 if (errno == EBUSY)
327                         fprintf(stderr, "LNET busy\n");
328                 else
329                         fprintf(stderr, "LNET unconfigure error %d: %s\n",
330                                 errno, strerror(errno));
331                 return -1;
332         } else if (!strcmp(argv[1], "configure") || !strcmp(argv[1], "up")) {
333                 LIBCFS_IOC_INIT(data);
334                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CONFIGURE, &data);
335
336                 if (rc == 0) {
337                         printf("LNET configured\n");
338                         return 0;
339                 }
340
341                 fprintf(stderr, "LNET configure error %d: %s\n",
342                         errno, strerror(errno));
343                 return -1;
344         }
345
346         net = libcfs_str2net(argv[1]);
347         if (net == LNET_NET_ANY) {
348                 fprintf(stderr, "Can't parse net %s\n", argv[1]);
349                 return -1;
350         }
351
352         g_net_set = true;
353         g_net = net;
354         return 0;
355 }
356
357 #ifndef IOC_LIBCFS_GET_NI
358 #define IOC_LIBCFS_GET_NI       _IOWR('e', 50, IOCTL_LIBCFS_TYPE)
359 #endif
360
361 int
362 jt_ptl_list_nids(int argc, char **argv)
363 {
364         int all = 0, return_nid = 0;
365         yaml_emitter_t request;
366         yaml_parser_t reply;
367         yaml_event_t event;
368         struct nl_sock *sk;
369         bool done = false;
370         int rc = 0;
371
372         all = (argc == 2) && (strcmp(argv[1], "all") == 0);
373         /* Hack to pass back value */
374         return_nid = (argc == 2) && (argv[1][0] == 1);
375
376         if ((argc > 2) && !(all || return_nid)) {
377                 fprintf(stderr, "usage: %s [all]\n", argv[0]);
378                 return 0;
379         }
380
381         sk = nl_socket_alloc();
382         if (!sk)
383                 goto old_api;
384
385         /* Setup parser to receive Netlink packets */
386         rc = yaml_parser_initialize(&reply);
387         if (rc == 0) {
388                 yaml_parser_log_error(&reply, stderr, NULL);
389                 goto old_api;
390         }
391
392         rc = yaml_parser_set_input_netlink(&reply, sk, false);
393         if (rc == 0) {
394                 yaml_parser_log_error(&reply, stderr, NULL);
395                 yaml_parser_delete(&reply);
396                 goto old_api;
397         }
398
399         /* Create Netlink emitter to send request to kernel */
400         rc = yaml_emitter_initialize(&request);
401         if (rc == 0) {
402                 yaml_parser_log_error(&reply, stderr, NULL);
403                 yaml_parser_delete(&reply);
404                 goto old_api;
405         }
406
407         rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME, 1,
408                                              LNET_CMD_NETS, NLM_F_DUMP);
409         if (rc == 0) {
410                 yaml_emitter_log_error(&request, stderr);
411                 yaml_emitter_delete(&request);
412                 yaml_parser_delete(&reply);
413                 goto old_api;
414         }
415
416         yaml_emitter_open(&request);
417         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
418         rc = yaml_emitter_emit(&request, &event);
419         if (rc == 0)
420                 goto emitter_error;
421
422         yaml_mapping_start_event_initialize(&event, NULL,
423                                             (yaml_char_t *)YAML_MAP_TAG,
424                                             1, YAML_ANY_MAPPING_STYLE);
425         rc = yaml_emitter_emit(&request, &event);
426         if (rc == 0)
427                 goto emitter_error;
428
429         yaml_scalar_event_initialize(&event, NULL,
430                                      (yaml_char_t *)YAML_STR_TAG,
431                                      (yaml_char_t *)"net",
432                                      strlen("net"), 1, 0,
433                                      YAML_PLAIN_SCALAR_STYLE);
434         rc = yaml_emitter_emit(&request, &event);
435         if (rc == 0)
436                 goto emitter_error;
437
438         /* no net_id */
439         if (!g_net_set || g_net == LNET_NET_ANY) {
440                 yaml_scalar_event_initialize(&event, NULL,
441                                              (yaml_char_t *)YAML_STR_TAG,
442                                              (yaml_char_t *)"",
443                                              strlen(""), 1, 0,
444                                              YAML_PLAIN_SCALAR_STYLE);
445                 rc = yaml_emitter_emit(&request, &event);
446                 if (rc == 0)
447                         goto emitter_error;
448         } else {
449                 char *net_id = libcfs_net2str(g_net);
450
451                 yaml_sequence_start_event_initialize(&event, NULL,
452                                                      (yaml_char_t *)YAML_SEQ_TAG,
453                                                      1, YAML_ANY_SEQUENCE_STYLE);
454                 rc = yaml_emitter_emit(&request, &event);
455                 if (rc == 0)
456                         goto emitter_error;
457
458                 yaml_mapping_start_event_initialize(&event, NULL,
459                                                     (yaml_char_t *)YAML_MAP_TAG,
460                                                     1, YAML_ANY_MAPPING_STYLE);
461                 rc = yaml_emitter_emit(&request, &event);
462                 if (rc == 0)
463                         goto emitter_error;
464
465                 yaml_scalar_event_initialize(&event, NULL,
466                                              (yaml_char_t *)YAML_STR_TAG,
467                                              (yaml_char_t *)"net type",
468                                              strlen("net type"),
469                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
470                 rc = yaml_emitter_emit(&request, &event);
471                 if (rc == 0)
472                         goto emitter_error;
473
474                 yaml_scalar_event_initialize(&event, NULL,
475                                              (yaml_char_t *)YAML_STR_TAG,
476                                              (yaml_char_t *)net_id,
477                                              strlen(net_id), 1, 0,
478                                              YAML_PLAIN_SCALAR_STYLE);
479                 rc = yaml_emitter_emit(&request, &event);
480                 if (rc == 0)
481                         goto emitter_error;
482
483                 yaml_mapping_end_event_initialize(&event);
484                 rc = yaml_emitter_emit(&request, &event);
485                 if (rc == 0)
486                         goto emitter_error;
487
488                 yaml_sequence_end_event_initialize(&event);
489                 rc = yaml_emitter_emit(&request, &event);
490                 if (rc == 0)
491                         goto emitter_error;
492         }
493         yaml_mapping_end_event_initialize(&event);
494         rc = yaml_emitter_emit(&request, &event);
495         if (rc == 0)
496                 goto emitter_error;
497
498         yaml_document_end_event_initialize(&event, 0);
499         rc = yaml_emitter_emit(&request, &event);
500         if (rc == 0)
501                 goto emitter_error;
502
503         rc = yaml_emitter_close(&request);
504 emitter_error:
505         if (rc == 0) {
506                 yaml_emitter_log_error(&request, stderr);
507                 rc = -EINVAL;
508         }
509         yaml_emitter_delete(&request);
510
511         while (!done) {
512                 rc = yaml_parser_parse(&reply, &event);
513                 if (rc == 0)
514                         break;
515
516                 if (event.type == YAML_SCALAR_EVENT &&
517                     strcmp((char *)event.data.scalar.value, "nid") == 0) {
518                         char *tmp;
519
520                         yaml_event_delete(&event);
521                         rc = yaml_parser_parse(&reply, &event);
522                         if (rc == 0) {
523                                 yaml_event_delete(&event);
524                                 break;
525                         }
526
527                         tmp = (char *)event.data.scalar.value;
528                         if (all || strcmp(tmp, "0@lo") != 0) {
529                                 printf("%s\n", tmp);
530                                 if (return_nid) {
531                                         *(__u64 *)(argv[1]) = libcfs_str2nid(tmp);
532                                         return_nid--;
533                                 }
534                         }
535                 }
536                 done = (event.type == YAML_STREAM_END_EVENT);
537                 yaml_event_delete(&event);
538         }
539
540         if (rc == 0)
541                 yaml_parser_log_error(&reply, stderr, NULL);
542         yaml_parser_delete(&reply);
543 old_api: {
544 #ifdef IOC_LIBCFS_GET_NI
545         int count;
546
547         if (sk)
548                 nl_socket_free(sk);
549         if (rc == 1)
550                 return 0;
551
552         for (count = 0;; count++) {
553                 struct libcfs_ioctl_data data;
554
555                 LIBCFS_IOC_INIT(data);
556                 data.ioc_count = count;
557                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NI, &data);
558
559                 if (rc < 0) {
560                         if ((count > 0) && (errno == ENOENT))
561                                 /* We found them all */
562                                 break;
563                         fprintf(stderr, "IOC_LIBCFS_GET_NI error %d: %s\n",
564                                 errno, strerror(errno));
565                         return -1;
566                 }
567
568                 if (all || (data.ioc_nid != LNET_NID_LO_0)) {
569                         printf("%s\n", libcfs_nid2str(data.ioc_nid));
570                         if (return_nid) {
571                                 *(__u64 *)(argv[1]) = data.ioc_nid;
572                                 return_nid--;
573                         }
574                 }
575         }
576
577 #else
578         rc = -1;
579 #endif
580         }
581         return rc;
582 }
583
584 int
585 jt_ptl_which_nid(int argc, char **argv)
586 {
587         struct lnet_nid best_nid = LNET_ANY_NID;
588         yaml_emitter_t request;
589         yaml_parser_t reply;
590         yaml_event_t event;
591         struct nl_sock *sk;
592         int best_dist = 0;
593         int best_order = 0;
594         bool done = false;
595         int dist = 0;
596         int order = 0;
597         char *nidstr;
598         int rc;
599         int i;
600
601         if (argc < 2) {
602                 fprintf(stderr, "usage: %s NID [NID...]\n", argv[0]);
603                 return 0;
604         }
605
606         /* Create Netlink emitter to send request to kernel */
607         sk = nl_socket_alloc();
608         if (!sk)
609                 goto old_api;
610
611         /* Setup parser to recieve Netlink packets */
612         rc = yaml_parser_initialize(&reply);
613         if (rc == 0)
614                 goto old_api;
615
616         rc = yaml_parser_set_input_netlink(&reply, sk, false);
617         if (rc == 0)
618                 goto free_reply;
619
620         /* Create Netlink emitter to send request to kernel */
621         rc = yaml_emitter_initialize(&request);
622         if (rc == 0)
623                 goto free_reply;
624
625         rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
626                                              LNET_GENL_VERSION,
627                                              LNET_CMD_PEER_DIST, NLM_F_DUMP);
628         if (rc == 0)
629                 goto emitter_error;
630
631         yaml_emitter_open(&request);
632         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
633         rc = yaml_emitter_emit(&request, &event);
634         if (rc == 0)
635                 goto emitter_error;
636
637         yaml_mapping_start_event_initialize(&event, NULL,
638                                             (yaml_char_t *)YAML_MAP_TAG,
639                                             1, YAML_ANY_MAPPING_STYLE);
640         rc = yaml_emitter_emit(&request, &event);
641         if (rc == 0)
642                 goto emitter_error;
643
644         yaml_scalar_event_initialize(&event, NULL,
645                                      (yaml_char_t *)YAML_STR_TAG,
646                                      (yaml_char_t *)"peer",
647                                      strlen("peer"), 1, 0,
648                                      YAML_PLAIN_SCALAR_STYLE);
649         rc = yaml_emitter_emit(&request, &event);
650         if (rc == 0)
651                 goto emitter_error;
652
653         yaml_sequence_start_event_initialize(&event, NULL,
654                                              (yaml_char_t *)YAML_SEQ_TAG,
655                                              1, YAML_BLOCK_SEQUENCE_STYLE);
656         rc = yaml_emitter_emit(&request, &event);
657         if (rc == 0)
658                 goto emitter_error;
659
660         for (i = 1; i < argc; i++) {
661                 struct lnet_nid nid;
662
663                 nidstr = argv[i];
664                 if (strcmp(nidstr, "*") == 0)
665                         nidstr = "<?>";
666
667                 rc = libcfs_strnid(&nid, nidstr);
668                 if (rc < 0 || nid_same(&nid, &LNET_ANY_NID)) {
669                         fprintf(stderr, "Can't parse NID %s\n", nidstr);
670                         return -1;
671                 }
672
673                 yaml_scalar_event_initialize(&event, NULL,
674                                              (yaml_char_t *)YAML_STR_TAG,
675                                              (yaml_char_t *)nidstr,
676                                              strlen(nidstr), 1, 0,
677                                              YAML_PLAIN_SCALAR_STYLE);
678                 rc = yaml_emitter_emit(&request, &event);
679                 if (rc == 0)
680                         goto emitter_error;
681         }
682
683         yaml_sequence_end_event_initialize(&event);
684         rc = yaml_emitter_emit(&request, &event);
685         if (rc == 0)
686                 goto emitter_error;
687
688         yaml_mapping_end_event_initialize(&event);
689         rc = yaml_emitter_emit(&request, &event);
690         if (rc == 0)
691                 goto emitter_error;
692
693         yaml_document_end_event_initialize(&event, 0);
694         rc = yaml_emitter_emit(&request, &event);
695         if (rc == 0)
696                 goto emitter_error;
697
698         rc = yaml_emitter_close(&request);
699 emitter_error:
700         if (rc == 0) {
701                 yaml_emitter_log_error(&request, stderr);
702                 rc = -EINVAL;
703         }
704         yaml_emitter_delete(&request);
705
706         while (!done) {
707                 rc = yaml_parser_parse(&reply, &event);
708                 if (rc == 0)
709                         break;
710
711                 if (event.type != YAML_SCALAR_EVENT)
712                         goto not_scalar;
713
714
715                 if (strcmp((char *)event.data.scalar.value, "nid") == 0) {
716                         yaml_event_delete(&event);
717                         rc = yaml_parser_parse(&reply, &event);
718                         if (rc == 0) {
719                                 yaml_event_delete(&event);
720                                 break;
721                         }
722
723                         nidstr = (char *)event.data.scalar.value;
724
725                         if (nid_same(&best_nid, &LNET_ANY_NID) ||
726                             dist < best_dist ||
727                             (dist == best_dist && order < best_order)) {
728                                 best_dist = dist;
729                                 best_order = order;
730                                 libcfs_strnid(&best_nid, nidstr);
731                         }
732                 } else if (strcmp((char *)event.data.scalar.value,
733                                   "distance") == 0) {
734                         yaml_event_delete(&event);
735                         rc = yaml_parser_parse(&reply, &event);
736                         if (rc == 0) {
737                                 yaml_event_delete(&event);
738                                 break;
739                         }
740
741                         dist = strtol((char *)event.data.scalar.value, NULL, 10);
742                 } else if (strcmp((char *)event.data.scalar.value,
743                                   "order") == 0) {
744                         yaml_event_delete(&event);
745                         rc = yaml_parser_parse(&reply, &event);
746                         if (rc == 0) {
747                                 yaml_event_delete(&event);
748                                 break;
749                         }
750
751                         order = strtol((char *)event.data.scalar.value, NULL, 10);
752                 }
753 not_scalar:
754                 done = (event.type == YAML_STREAM_END_EVENT);
755                 yaml_event_delete(&event);
756         }
757
758 free_reply:
759         if (rc == 0) {
760                 /* yaml_* functions return 0 for error */
761                 const char *msg = yaml_parser_get_reader_error(&reply);
762
763                 fprintf(stderr, "Unexpected distance: %s\n", msg);
764                 rc = -1;
765         } else if (rc == 1) {
766                 /* yaml_* functions return 1 for success */
767                 rc = 0;
768         }
769
770         yaml_parser_delete(&reply);
771         nl_socket_free(sk);
772         goto finished;
773
774 old_api:
775         for (i = 1; i < argc; i++) {
776                 struct libcfs_ioctl_data data;
777                 lnet_nid_t nid4;
778
779                 nidstr = argv[i];
780                 nid4 = libcfs_str2nid(nidstr);
781                 if (nid4 == LNET_NID_ANY) {
782                         fprintf(stderr, "Can't parse NID %s\n", nidstr);
783                         return -1;
784                 }
785
786                 LIBCFS_IOC_INIT(data);
787                 data.ioc_nid = nid4;
788
789                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_DIST, &data);
790                 if (rc != 0) {
791                         fprintf(stderr, "Can't get distance to %s: %s\n",
792                                 nidstr, strerror(errno));
793                         return -1;
794                 }
795
796                 dist = data.ioc_u32[0];
797                 order = data.ioc_u32[1];
798
799                 if (dist < 0) {
800                         if (dist == -EHOSTUNREACH)
801                                 continue;
802
803                         fprintf(stderr, "Unexpected distance to %s: %d\n",
804                                 nidstr, dist);
805                         return -1;
806                 }
807
808                 if (nid_same(&best_nid, &LNET_ANY_NID) ||
809                     dist < best_dist ||
810                     (dist == best_dist && order < best_order)) {
811                         best_dist = dist;
812                         best_order = order;
813                         lnet_nid4_to_nid(nid4, &best_nid);
814                 }
815         }
816 finished:
817         if (nid_same(&best_nid, &LNET_ANY_NID)) {
818                 fprintf(stderr, "No reachable NID\n");
819                 return -1;
820         }
821
822         printf("%s\n", libcfs_nidstr(&best_nid));
823         return 0;
824 }
825
826 int
827 jt_ptl_print_interfaces(int argc, char **argv)
828 {
829         struct libcfs_ioctl_data data;
830         char buffer[3][HOST_NAME_MAX + 1];
831         int index;
832         int rc;
833
834         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
835                 return -1;
836
837         for (index = 0; ; index++) {
838                 LIBCFS_IOC_INIT(data);
839                 data.ioc_net   = g_net;
840                 data.ioc_count = index;
841
842                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_INTERFACE, &data);
843                 if (rc != 0)
844                         break;
845
846                 printf("%s: (%s/%s) npeer %d nroute %d\n",
847                        ptl_ipaddr_2_str(data.ioc_u32[0], buffer[2],
848                                         sizeof(buffer[2]), 1),
849                        ptl_ipaddr_2_str(data.ioc_u32[0], buffer[0],
850                                         sizeof(buffer[0]), 0),
851                        ptl_ipaddr_2_str(data.ioc_u32[1], buffer[1],
852                                         sizeof(buffer[1]), 0),
853                        data.ioc_u32[2], data.ioc_u32[3]);
854         }
855
856         if (index == 0) {
857                 if (errno == ENOENT) {
858                         printf("<no interfaces>\n");
859                 } else {
860                         fprintf(stderr,
861                                 "Error getting interfaces: %s: check dmesg.\n",
862                                 strerror(errno));
863                 }
864         }
865
866         return 0;
867 }
868
869 int
870 jt_ptl_add_interface(int argc, char **argv)
871 {
872         struct libcfs_ioctl_data data;
873         __u32 ipaddr;
874         int rc;
875         __u32 netmask = 0xffffff00;
876         int i;
877         int count;
878         char *end;
879
880         if (argc < 2 || argc > 3) {
881                 fprintf(stderr, "usage: %s ipaddr [netmask]\n", argv[0]);
882                 return 0;
883         }
884
885         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
886                 return -1;
887
888         if (lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
889                 fprintf(stderr, "Can't parse ip: %s\n", argv[1]);
890                 return -1;
891         }
892
893         if (argc > 2) {
894                 count = strtol(argv[2], &end, 0);
895                 if (count > 0 && count < 32 && *end == 0) {
896                         netmask = 0;
897                         for (i = count; i > 0; i--)
898                                 netmask = netmask | (1 << (32 - i));
899                 } else if (lnet_parse_ipquad(&netmask, argv[2]) != 0) {
900                         fprintf(stderr, "Can't parse netmask: %s\n", argv[2]);
901                         return -1;
902                 }
903         }
904
905         LIBCFS_IOC_INIT(data);
906         data.ioc_net    = g_net;
907         data.ioc_u32[0] = ipaddr;
908         data.ioc_u32[1] = netmask;
909
910         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_INTERFACE, &data);
911         if (rc != 0) {
912                 fprintf(stderr, "failed to add interface: %s\n",
913                         strerror(errno));
914                 return -1;
915         }
916
917         return 0;
918 }
919
920 int
921 jt_ptl_del_interface(int argc, char **argv)
922 {
923         struct libcfs_ioctl_data data;
924         int rc;
925         __u32 ipaddr = 0;
926
927         if (argc > 2) {
928                 fprintf(stderr, "usage: %s [ipaddr]\n", argv[0]);
929                 return 0;
930         }
931
932         if (!g_net_is_compatible(argv[0], SOCKLND, 0))
933                 return -1;
934
935         if (argc == 2 &&
936             lnet_parse_ipaddr(&ipaddr, argv[1]) != 0) {
937                 fprintf(stderr, "Can't parse ip: %s\n", argv[1]);
938                 return -1;
939         }
940
941         LIBCFS_IOC_INIT(data);
942         data.ioc_net    = g_net;
943         data.ioc_u32[0] = ipaddr;
944
945         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_INTERFACE, &data);
946         if (rc != 0) {
947                 fprintf(stderr, "failed to delete interface: %s\n",
948                         strerror(errno));
949                 return -1;
950         }
951
952         return 0;
953 }
954
955 int
956 jt_ptl_print_peers(int argc, char **argv)
957 {
958         struct libcfs_ioctl_data data;
959         struct lnet_process_id id;
960         char buffer[2][HOST_NAME_MAX + 1];
961         int index;
962         int rc;
963
964         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND,
965                                  PTL4LND, 0))
966                 return -1;
967
968         for (index = 0; ; index++) {
969                 LIBCFS_IOC_INIT(data);
970                 data.ioc_net     = g_net;
971                 data.ioc_count   = index;
972
973                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_PEER, &data);
974                 if (rc != 0)
975                         break;
976
977                 if (g_net_is_compatible(NULL, SOCKLND, 0)) {
978                         id.nid = data.ioc_nid;
979                         id.pid = data.ioc_u32[4];
980                         printf("%-20s [%d]%s->%s:%d #%d\n",
981                                libcfs_id2str(id),
982                                data.ioc_count, /* persistence */
983                                /* my ip */
984                                ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
985                                                 sizeof(buffer[0]), 1),
986                                /* peer ip */
987                                ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
988                                                 sizeof(buffer[1]), 1),
989                                data.ioc_u32[1], /* peer port */
990                                data.ioc_u32[3]); /* conn_count */
991                 } else if (g_net_is_compatible(NULL, GNILND, 0)) {
992                         int disconn = data.ioc_flags >> 16;
993                         char *state;
994
995                         if (disconn)
996                                 state = "D";
997                         else
998                                 state = data.ioc_flags & 0xffff ? "C" : "U";
999
1000                         printf("%-20s (%d) %s [%d] %ju sq %d/%d tx %d/%d/%d\n",
1001                                libcfs_nid2str(data.ioc_nid), /* peer nid */
1002                                data.ioc_net, /* gemini device id */
1003                                state, /* peer is Connecting, Up, or Down */
1004                                data.ioc_count,   /* peer refcount */
1005                                (uintmax_t)data.ioc_u64[0], /* peerstamp */
1006                                data.ioc_u32[2], data.ioc_u32[3], /* tx and rx seq */
1007                                /* fmaq, nfma, nrdma */
1008                                data.ioc_u32[0], data.ioc_u32[1],
1009                                data.ioc_u32[4]);
1010                 } else {
1011                         printf("%-20s [%d]\n",
1012                                libcfs_nid2str(data.ioc_nid), data.ioc_count);
1013                 }
1014         }
1015
1016         if (index == 0) {
1017                 if (errno == ENOENT) {
1018                         printf("<no peers>\n");
1019                 } else {
1020                         fprintf(stderr,
1021                                 "Error getting peer list: %s: check dmesg.\n",
1022                                 strerror(errno));
1023                 }
1024         }
1025         return 0;
1026 }
1027
1028 int jt_ptl_add_peer(int argc, char **argv)
1029 {
1030         struct libcfs_ioctl_data data;
1031         lnet_nid_t nid;
1032         __u32 ip = 0;
1033         int port = 0;
1034         int rc;
1035
1036         if (!g_net_is_compatible(argv[0], SOCKLND, GNILND, 0))
1037                 return -1;
1038
1039         if (argc != 4) {
1040                 fprintf(stderr, "usage(tcp,gni): %s nid ipaddr port\n",
1041                         argv[0]);
1042                 return 0;
1043         }
1044
1045         nid = libcfs_str2nid(argv[1]);
1046         if (nid == LNET_NID_ANY) {
1047                 fprintf(stderr, "Can't parse NID: %s\n", argv[1]);
1048                 return -1;
1049         }
1050
1051         if (lnet_parse_ipaddr(&ip, argv[2]) != 0) {
1052                 fprintf(stderr, "Can't parse ip addr: %s\n", argv[2]);
1053                 return -1;
1054         }
1055
1056         if (lnet_parse_port(&port, argv[3]) != 0) {
1057                 fprintf(stderr, "Can't parse port: %s\n", argv[3]);
1058                 return -1;
1059         }
1060
1061         LIBCFS_IOC_INIT(data);
1062         data.ioc_net    = g_net;
1063         data.ioc_nid    = nid;
1064         data.ioc_u32[0] = ip;
1065         data.ioc_u32[1] = port;
1066
1067         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_PEER, &data);
1068         if (rc != 0) {
1069                 fprintf(stderr, "failed to add peer: %s\n",
1070                         strerror(errno));
1071                 return -1;
1072         }
1073
1074         return 0;
1075 }
1076
1077 int
1078 jt_ptl_del_peer(int argc, char **argv)
1079 {
1080         struct libcfs_ioctl_data data;
1081         lnet_nid_t nid = LNET_NID_ANY;
1082         lnet_pid_t pid = LNET_PID_ANY;
1083         __u32 ip = 0;
1084         int rc;
1085
1086         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND,
1087                                  PTL4LND, 0))
1088                 return -1;
1089
1090         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
1091                 if (argc > 3) {
1092                         fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
1093                         return 0;
1094                 }
1095         } else if (argc > 2) {
1096                 fprintf(stderr, "usage: %s [nid]\n", argv[0]);
1097                 return 0;
1098         }
1099
1100         if (argc > 1 && !libcfs_str2anynid(&nid, argv[1])) {
1101                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
1102                 return -1;
1103         }
1104
1105         if (g_net_is_compatible(NULL, SOCKLND, 0)) {
1106                 if (argc > 2 && lnet_parse_ipaddr(&ip, argv[2]) != 0) {
1107                         fprintf(stderr, "Can't parse ip addr: %s\n", argv[2]);
1108                         return -1;
1109                 }
1110         }
1111
1112         LIBCFS_IOC_INIT(data);
1113         data.ioc_net    = g_net;
1114         data.ioc_nid    = nid;
1115         data.ioc_u32[0] = ip;
1116         data.ioc_u32[1] = pid;
1117
1118         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_PEER, &data);
1119         if (rc != 0) {
1120                 fprintf(stderr, "failed to remove peer: %s\n", strerror(errno));
1121                 return -1;
1122         }
1123
1124         return 0;
1125 }
1126
1127 int
1128 jt_ptl_print_connections(int argc, char **argv)
1129 {
1130         struct libcfs_ioctl_data data;
1131         struct lnet_process_id id;
1132         char buffer[2][HOST_NAME_MAX + 1];
1133         int index;
1134         int rc;
1135
1136         if (!g_net_is_compatible(argv[0], SOCKLND, O2IBLND, GNILND, 0))
1137                 return -1;
1138
1139         for (index = 0; ; index++) {
1140                 LIBCFS_IOC_INIT(data);
1141                 data.ioc_net     = g_net;
1142                 data.ioc_count   = index;
1143
1144                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_CONN, &data);
1145                 if (rc != 0)
1146                         break;
1147
1148                 if (g_net_is_compatible(NULL, SOCKLND, 0)) {
1149                         id.nid = data.ioc_nid;
1150                         id.pid = data.ioc_u32[6];
1151                         printf("%-20s %s[%d]%s->%s:%d %d/%d %s\n",
1152                                libcfs_id2str(id),
1153                                (data.ioc_u32[3] == SOCKLND_CONN_ANY) ? "A" :
1154                                (data.ioc_u32[3] == SOCKLND_CONN_CONTROL) ? "C" :
1155                                (data.ioc_u32[3] == SOCKLND_CONN_BULK_IN) ? "I" :
1156                          (data.ioc_u32[3] == SOCKLND_CONN_BULK_OUT) ? "O" : "?",
1157                                data.ioc_u32[4], /* scheduler */
1158                                /* local IP addr */
1159                                ptl_ipaddr_2_str(data.ioc_u32[2], buffer[0],
1160                                                 sizeof(buffer[0]), 1),
1161                                /* remote IP addr */
1162                                ptl_ipaddr_2_str(data.ioc_u32[0], buffer[1],
1163                                                 sizeof(buffer[1]), 1),
1164                                data.ioc_u32[1],         /* remote port */
1165                                data.ioc_count, /* tx buffer size */
1166                                data.ioc_u32[5], /* rx buffer size */
1167                                data.ioc_flags ? "nagle" : "nonagle");
1168                 } else if (g_net_is_compatible(NULL, O2IBLND, 0)) {
1169                         printf("%s mtu %d\n",
1170                                libcfs_nid2str(data.ioc_nid),
1171                                data.ioc_u32[0]); /* path MTU */
1172                 } else if (g_net_is_compatible(NULL, GNILND, 0)) {
1173                         printf("%-20s [%d]\n",
1174                                libcfs_nid2str(data.ioc_nid),
1175                                data.ioc_u32[0] /* device id */);
1176                 } else {
1177                         printf("%s\n", libcfs_nid2str(data.ioc_nid));
1178                 }
1179         }
1180
1181         if (index == 0) {
1182                 if (errno == ENOENT) {
1183                         printf("<no connections>\n");
1184                 } else {
1185                         fprintf(stderr,
1186                                 "Error getting connection list: %s: check dmesg.\n",
1187                                 strerror(errno));
1188                 }
1189         }
1190         return 0;
1191 }
1192
1193 int jt_ptl_disconnect(int argc, char **argv)
1194 {
1195         struct libcfs_ioctl_data data;
1196         lnet_nid_t nid = LNET_NID_ANY;
1197         __u32 ipaddr = 0;
1198         int rc;
1199
1200         if (argc > 3) {
1201                 fprintf(stderr, "usage: %s [nid] [ipaddr]\n", argv[0]);
1202                 return 0;
1203         }
1204
1205         if (!g_net_is_compatible(NULL, SOCKLND, O2IBLND, GNILND, 0))
1206                 return 0;
1207
1208         if (argc >= 2 && !libcfs_str2anynid(&nid, argv[1])) {
1209                 fprintf(stderr, "Can't parse nid %s\n", argv[1]);
1210                 return -1;
1211         }
1212
1213         if (g_net_is_compatible(NULL, SOCKLND, 0) && argc >= 3 &&
1214             lnet_parse_ipaddr(&ipaddr, argv[2]) != 0) {
1215                 fprintf(stderr, "Can't parse ip addr %s\n", argv[2]);
1216                 return -1;
1217         }
1218
1219         LIBCFS_IOC_INIT(data);
1220         data.ioc_net     = g_net;
1221         data.ioc_nid     = nid;
1222         data.ioc_u32[0]  = ipaddr;
1223
1224         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_CLOSE_CONNECTION, &data);
1225         if (rc != 0) {
1226                 fprintf(stderr, "failed to remove connection: %s\n",
1227                         strerror(errno));
1228                 return -1;
1229         }
1230
1231         return 0;
1232 }
1233
1234 int jt_ptl_push_connection(int argc, char **argv)
1235 {
1236         struct libcfs_ioctl_data data;
1237         int rc;
1238         lnet_nid_t nid = LNET_NID_ANY;
1239
1240         if (argc > 2) {
1241                 fprintf(stderr, "usage: %s [nid]\n", argv[0]);
1242                 return 0;
1243         }
1244
1245         if (!g_net_is_compatible(argv[0], SOCKLND, GNILND, 0))
1246                 return -1;
1247
1248         if (argc > 1 && !libcfs_str2anynid(&nid, argv[1])) {
1249                 fprintf(stderr, "Can't parse nid: %s\n", argv[1]);
1250                 return -1;
1251         }
1252
1253         LIBCFS_IOC_INIT(data);
1254         data.ioc_net     = g_net;
1255         data.ioc_nid     = nid;
1256
1257         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PUSH_CONNECTION, &data);
1258         if (rc != 0) {
1259                 fprintf(stderr, "failed to push connection: %s\n",
1260                         strerror(errno));
1261                 return -1;
1262         }
1263
1264         return 0;
1265 }
1266
1267 #ifndef IOC_LIBCFS_PING_PEER
1268 #define IOC_LIBCFS_PING_PEER            _IOWR('e', 62, IOCTL_LIBCFS_TYPE)
1269 #endif
1270
1271 int jt_ptl_ping(int argc, char **argv)
1272 {
1273         bool done = false, print = true;
1274         int rc;
1275         int timeout;
1276         struct lnet_process_id id;
1277         yaml_emitter_t request;
1278         yaml_parser_t reply;
1279         yaml_event_t event;
1280         struct nl_sock *sk;
1281         char *sep;
1282
1283         if (argc < 2) {
1284                 fprintf(stderr, "usage: %s id [timeout (secs)]\n", argv[0]);
1285                 return -EINVAL;
1286         }
1287
1288         sep = strchr(argv[1], '-');
1289         if (!sep) {
1290                 rc = lnet_parse_nid(argv[1], &id);
1291                 if (rc != 0)
1292                         return -EINVAL;
1293         } else {
1294                 char   *end;
1295
1296                 if (argv[1][0] == 'u' || argv[1][0] == 'U')
1297                         id.pid = strtoul(&argv[1][1], &end, 0) |
1298                                 LNET_PID_USERFLAG;
1299                 else
1300                         id.pid = strtoul(argv[1], &end, 0);
1301
1302                 if (end != sep) { /* assuming '-' is part of hostname */
1303                         rc = lnet_parse_nid(argv[1], &id);
1304                         if (rc != 0)
1305                                 return -EINVAL;
1306                 } else {
1307                         id.nid = libcfs_str2nid(sep + 1);
1308
1309                         if (id.nid == LNET_NID_ANY) {
1310                                 fprintf(stderr,
1311                                         "Can't parse process id \"%s\"\n",
1312                                         argv[1]);
1313                                 return -EINVAL;
1314                         }
1315                 }
1316         }
1317
1318         if (argc > 2) {
1319                 timeout = 1000 * atol(argv[2]);
1320                 if (timeout > 120 * 1000) {
1321                         fprintf(stderr, "Timeout %s is to large\n",
1322                                 argv[2]);
1323                         return -EINVAL;
1324                 }
1325         } else {
1326                 timeout = 1000; /* default 1 second timeout */
1327         }
1328
1329         /* Create Netlink emitter to send request to kernel */
1330         sk = nl_socket_alloc();
1331         if (!sk)
1332                 goto old_api;
1333
1334         /* Setup parser to recieve Netlink packets */
1335         rc = yaml_parser_initialize(&reply);
1336         if (rc == 0)
1337                 goto old_api;
1338
1339         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1340         if (rc == 0)
1341                 goto free_reply;
1342
1343         /* Create Netlink emitter to send request to kernel */
1344         rc = yaml_emitter_initialize(&request);
1345         if (rc == 0)
1346                 goto free_reply;
1347
1348         rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
1349                                              LNET_GENL_VERSION, LNET_CMD_PING,
1350                                              NLM_F_DUMP);
1351         if (rc == 0)
1352                 goto emitter_error;
1353
1354         yaml_emitter_open(&request);
1355         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1356         rc = yaml_emitter_emit(&request, &event);
1357         if (rc == 0)
1358                 goto emitter_error;
1359
1360         yaml_mapping_start_event_initialize(&event, NULL,
1361                                             (yaml_char_t *)YAML_MAP_TAG,
1362                                             1, YAML_ANY_MAPPING_STYLE);
1363         rc = yaml_emitter_emit(&request, &event);
1364         if (rc == 0)
1365                 goto emitter_error;
1366
1367         yaml_scalar_event_initialize(&event, NULL,
1368                                      (yaml_char_t *)YAML_STR_TAG,
1369                                      (yaml_char_t *)"ping",
1370                                      strlen("ping"), 1, 0,
1371                                      YAML_PLAIN_SCALAR_STYLE);
1372         rc = yaml_emitter_emit(&request, &event);
1373         if (rc == 0)
1374                 goto emitter_error;
1375
1376         yaml_mapping_start_event_initialize(&event, NULL,
1377                                             (yaml_char_t *)YAML_MAP_TAG,
1378                                             1, YAML_ANY_MAPPING_STYLE);
1379         rc = yaml_emitter_emit(&request, &event);
1380         if (rc == 0)
1381                 goto emitter_error;
1382
1383         if (timeout != 1000) {
1384                 yaml_scalar_event_initialize(&event, NULL,
1385                                              (yaml_char_t *)YAML_STR_TAG,
1386                                              (yaml_char_t *)"timeout",
1387                                              strlen("timeout"), 1, 0,
1388                                              YAML_PLAIN_SCALAR_STYLE);
1389                 rc = yaml_emitter_emit(&request, &event);
1390                 if (rc == 0)
1391                         goto emitter_error;
1392
1393                 yaml_scalar_event_initialize(&event, NULL,
1394                                              (yaml_char_t *)YAML_INT_TAG,
1395                                              (yaml_char_t *)argv[2],
1396                                              strlen(argv[2]), 1, 0,
1397                                              YAML_PLAIN_SCALAR_STYLE);
1398                 rc = yaml_emitter_emit(&request, &event);
1399                 if (rc == 0)
1400                         goto emitter_error;
1401         }
1402
1403         yaml_scalar_event_initialize(&event, NULL,
1404                                      (yaml_char_t *)YAML_STR_TAG,
1405                                      (yaml_char_t *)"nids",
1406                                      strlen("nids"), 1, 0,
1407                                      YAML_PLAIN_SCALAR_STYLE);
1408         rc = yaml_emitter_emit(&request, &event);
1409         if (rc == 0)
1410                 goto emitter_error;
1411
1412         yaml_sequence_start_event_initialize(&event, NULL,
1413                                              (yaml_char_t *)YAML_SEQ_TAG,
1414                                              1, YAML_FLOW_SEQUENCE_STYLE);
1415         rc = yaml_emitter_emit(&request, &event);
1416         if (rc == 0)
1417                 goto emitter_error;
1418
1419         /* convert NID to string, in case libcfs_str2nid() did name lookup */
1420         yaml_scalar_event_initialize(&event, NULL,
1421                                      (yaml_char_t *)YAML_STR_TAG,
1422                                      (yaml_char_t *)libcfs_nid2str(id.nid),
1423                                      strlen(libcfs_nid2str(id.nid)), 1, 0,
1424                                      YAML_PLAIN_SCALAR_STYLE);
1425         rc = yaml_emitter_emit(&request, &event);
1426         if (rc == 0)
1427                 goto emitter_error;
1428
1429         yaml_sequence_end_event_initialize(&event);
1430         rc = yaml_emitter_emit(&request, &event);
1431         if (rc == 0)
1432                 goto emitter_error;
1433
1434         yaml_mapping_end_event_initialize(&event);
1435         rc = yaml_emitter_emit(&request, &event);
1436         if (rc == 0)
1437                 goto emitter_error;
1438
1439         yaml_mapping_end_event_initialize(&event);
1440         rc = yaml_emitter_emit(&request, &event);
1441         if (rc == 0)
1442                 goto emitter_error;
1443
1444         yaml_document_end_event_initialize(&event, 0);
1445         rc = yaml_emitter_emit(&request, &event);
1446         if (rc == 0)
1447                 goto emitter_error;
1448
1449         rc = yaml_emitter_close(&request);
1450 emitter_error:
1451         if (rc == 0) {
1452                 yaml_emitter_log_error(&request, stderr);
1453                 rc = -EINVAL;
1454                 goto old_api;
1455         }
1456         yaml_emitter_delete(&request);
1457
1458         /* Now parse the reply results */
1459         while (!done) {
1460                 rc = yaml_parser_parse(&reply, &event);
1461                 if (rc == 0)
1462                         break;
1463
1464                 if (event.type != YAML_SCALAR_EVENT)
1465                         goto skip;
1466
1467                 if (strcmp((char *)event.data.scalar.value, "nid") == 0) {
1468                         yaml_event_delete(&event);
1469                         rc = yaml_parser_parse(&reply, &event);
1470                         if (rc == 0) {
1471                                 yaml_event_delete(&event);
1472                                 goto free_reply;
1473                         }
1474                         if (print) {
1475                                 /* Print 0@lo. Its not sent */
1476                                 printf("12345-0@lo\n");
1477                                 print = false;
1478                         }
1479                         printf("%s\n", (char *)event.data.scalar.value);
1480                 } else if (strcmp((char *)event.data.scalar.value,
1481                                   "errno") == 0) {
1482                         yaml_event_delete(&event);
1483                         rc = yaml_parser_parse(&reply, &event);
1484                         if (rc == 0) {
1485                                 yaml_event_delete(&event);
1486                                 goto free_reply;
1487                         }
1488                         rc = strtol((char *)event.data.scalar.value, NULL, 10);
1489                         fprintf(stdout, "failed to ping %s: %s\n",
1490                                 argv[1], strerror(-rc));
1491                         break; /* "rc" is clobbered if loop is run again */
1492                 }
1493 skip:
1494                 done = (event.type == YAML_STREAM_END_EVENT);
1495                 yaml_event_delete(&event);
1496         }
1497 free_reply:
1498         if (rc == 0) {
1499                 /* yaml_* functions return 0 for error */
1500                 const char *msg = yaml_parser_get_reader_error(&reply);
1501
1502                 rc = errno ? -errno : -EHOSTUNREACH;
1503                 if (strcmp(msg, "Unspecific failure") != 0) {
1504                         fprintf(stdout, "failed to ping %s: %s\n",
1505                                 argv[1], msg);
1506                 } else {
1507                         fprintf(stdout, "failed to ping %s: %s\n",
1508                                 argv[1], strerror(errno));
1509                 }
1510         } else if (rc == 1) {
1511                 /* yaml_* functions return 1 for success */
1512                 rc = 0;
1513         }
1514         yaml_parser_delete(&reply);
1515         nl_socket_free(sk);
1516         return rc;
1517 old_api:
1518 #ifdef IOC_LIBCFS_PING_PEER
1519         {
1520         struct lnet_process_id ids[LNET_INTERFACES_MAX_DEFAULT];
1521         int maxids = sizeof(ids) / sizeof(ids[0]);
1522         struct lnet_ioctl_ping_data ping = { { 0 } };
1523         int i;
1524
1525         if (sk)
1526                 nl_socket_free(sk);
1527
1528         LIBCFS_IOC_INIT_V2(ping, ping_hdr);
1529         ping.ping_hdr.ioc_len = sizeof(ping);
1530         ping.ping_id = id;
1531         ping.ping_src = LNET_NID_ANY;
1532         ping.op_param = timeout;
1533         ping.ping_count = maxids;
1534         ping.ping_buf = ids;
1535
1536         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING_PEER, &ping);
1537         if (rc != 0) {
1538                 fprintf(stderr, "failed to ping %s: %s\n", argv[1],
1539                         strerror(errno));
1540                 return rc;
1541         }
1542
1543         for (i = 0; i < ping.ping_count && i < maxids; i++)
1544                 printf("%s\n", libcfs_id2str(ids[i]));
1545
1546         if (ping.ping_count > maxids)
1547                 printf("%d out of %d ids listed\n", maxids, ping.ping_count);
1548         }
1549 #else
1550         rc = -ENOTTY;
1551 #endif
1552         return rc;
1553 }
1554
1555 int jt_ptl_mynid(int argc, char **argv)
1556 {
1557         struct libcfs_ioctl_data data;
1558         lnet_nid_t nid;
1559         int rc;
1560
1561         if (argc != 2) {
1562                 fprintf(stderr, "usage: %s NID\n", argv[0]);
1563                 return 0;
1564         }
1565
1566         nid = libcfs_str2nid(argv[1]);
1567         if (nid == LNET_NID_ANY) {
1568                 fprintf(stderr, "Can't parse NID '%s'\n", argv[1]);
1569                 return -1;
1570         }
1571
1572         LIBCFS_IOC_INIT(data);
1573         data.ioc_net = LNET_NIDNET(nid);
1574         data.ioc_nid = nid;
1575
1576         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_REGISTER_MYNID, &data);
1577         if (rc < 0)
1578                 fprintf(stderr, "setting my NID failed: %s\n",
1579                         strerror(errno));
1580         else
1581                 printf("registered my nid %s\n", libcfs_nid2str(nid));
1582
1583         return 0;
1584 }
1585
1586 int
1587 jt_ptl_fail_nid(int argc, char **argv)
1588 {
1589         int rc;
1590         lnet_nid_t nid;
1591         int threshold;
1592         struct libcfs_ioctl_data data;
1593
1594         if (argc < 2 || argc > 3) {
1595                 fprintf(stderr, "usage: %s nid|\"*\" [count (0 == mend)]\n",
1596                         argv[0]);
1597                 return 0;
1598         }
1599
1600         if (!libcfs_str2anynid(&nid, argv[1])) {
1601                 fprintf(stderr, "Can't parse nid \"%s\"\n", argv[1]);
1602                 return -1;
1603         }
1604
1605         if (argc < 3) {
1606                 threshold = LNET_MD_THRESH_INF;
1607         } else if (sscanf(argv[2], "%i", &threshold) != 1) {
1608                 fprintf(stderr, "Can't parse count \"%s\"\n", argv[2]);
1609                 return -1;
1610         }
1611
1612         LIBCFS_IOC_INIT(data);
1613         data.ioc_nid = nid;
1614         data.ioc_count = threshold;
1615
1616         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_FAIL_NID, &data);
1617         if (rc < 0)
1618                 fprintf(stderr, "IOC_LIBCFS_FAIL_NID failed: %s\n",
1619                         strerror(errno));
1620         else
1621                 printf("%s %s\n",
1622                        threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1623
1624         return 0;
1625 }
1626
1627 static int ptl_yaml_route_display(yaml_parser_t *reply)
1628 {
1629         char gw[LNET_MAX_STR_LEN], net[18];
1630         bool done = false, alive = false;
1631         int hops = -1, prio = -1;
1632         yaml_event_t event;
1633         int rc;
1634
1635         /* Now parse the reply results */
1636         while (!done) {
1637                 char *value;
1638
1639                 rc = yaml_parser_parse(reply, &event);
1640                 if (rc == 0)
1641                         break;
1642
1643                 if (event.type == YAML_SEQUENCE_END_EVENT) {
1644                         printf("net %18s hops %d gw %32.128s %s pri %u\n",
1645                                net, hops, gw, alive ? "up" : "down",
1646                                prio);
1647                         memset(net, '\0', sizeof(net));
1648                         memset(gw, '\0', sizeof(gw));
1649                         prio = -1;
1650                         hops = -1;
1651                 }
1652
1653                 if (event.type != YAML_SCALAR_EVENT)
1654                         goto skip;
1655
1656                 value = (char *)event.data.scalar.value;
1657                 if (strcmp(value, "net") == 0) {
1658                         yaml_event_delete(&event);
1659                         rc = yaml_parser_parse(reply, &event);
1660                         if (rc == 0) {
1661                                 yaml_event_delete(&event);
1662                                 goto free_reply;
1663                         }
1664
1665                         value = (char *)event.data.scalar.value;
1666                         strncpy(net, value, sizeof(net) - 1);
1667                 } else if (strcmp(value, "gateway") == 0) {
1668                         yaml_event_delete(&event);
1669                         rc = yaml_parser_parse(reply, &event);
1670                         if (rc == 0) {
1671                                 yaml_event_delete(&event);
1672                                 goto free_reply;
1673                         }
1674
1675                         value = (char *)event.data.scalar.value;
1676                         strncpy(gw, value, sizeof(gw) - 1);
1677                 } else if (strcmp(value, "state") == 0) {
1678                         yaml_event_delete(&event);
1679                         rc = yaml_parser_parse(reply, &event);
1680                         if (rc == 0) {
1681                                 yaml_event_delete(&event);
1682                                 goto free_reply;
1683                         }
1684
1685                         value = (char *)event.data.scalar.value;
1686                         if (strcmp(value, "up") == 0) {
1687                                 alive = true;
1688                         } else if (strcmp(value, "down") == 0) {
1689                                 alive = false;
1690                         }
1691                 } else if (strcmp(value, "hop") == 0) {
1692                         yaml_event_delete(&event);
1693                         rc = yaml_parser_parse(reply, &event);
1694                         if (rc == 0) {
1695                                 yaml_event_delete(&event);
1696                                 goto free_reply;
1697                         }
1698
1699                         value = (char *)event.data.scalar.value;
1700                         hops = strtol(value, NULL, 10);
1701                 } else if (strcmp(value, "priority") == 0) {
1702                         yaml_event_delete(&event);
1703                         rc = yaml_parser_parse(reply, &event);
1704                         if (rc == 0) {
1705                                 yaml_event_delete(&event);
1706                                 goto free_reply;
1707                         }
1708
1709                         value = (char *)event.data.scalar.value;
1710                         prio = strtol(value, NULL, 10);
1711                 }
1712 skip:
1713                 done = (event.type == YAML_STREAM_END_EVENT);
1714                 yaml_event_delete(&event);
1715         }
1716
1717 free_reply:
1718         return rc;
1719 }
1720
1721 static int ptl_yaml_route(char *nw, char *gws, int hops, int prio, bool enable,
1722                           time_t notify_time, int flags, int version)
1723 {
1724         struct nl_sock *sk = NULL;
1725         const char *msg = NULL;
1726         yaml_emitter_t output;
1727         yaml_parser_t reply;
1728         yaml_event_t event;
1729         int rc;
1730
1731         sk = nl_socket_alloc();
1732         if (!sk)
1733                 return -EOPNOTSUPP;
1734
1735         /* Setup parser to receive Netlink packets */
1736         rc = yaml_parser_initialize(&reply);
1737         if (rc == 0) {
1738                 nl_socket_free(sk);
1739                 return -EOPNOTSUPP;
1740         }
1741
1742         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1743         if (rc == 0) {
1744                 msg = yaml_parser_get_reader_error(&reply);
1745                 goto free_reply;
1746         }
1747
1748         /* Create Netlink emitter to send request to kernel */
1749         rc = yaml_emitter_initialize(&output);
1750         if (rc == 0) {
1751                 msg = "failed to initialize emitter";
1752                 goto free_reply;
1753         }
1754
1755         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1756                                              version, LNET_CMD_ROUTES, flags);
1757         if (rc == 0)
1758                 goto emitter_error;
1759
1760         yaml_emitter_open(&output);
1761         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1762         rc = yaml_emitter_emit(&output, &event);
1763         if (rc == 0)
1764                 goto emitter_error;
1765
1766         yaml_mapping_start_event_initialize(&event, NULL,
1767                                             (yaml_char_t *)YAML_MAP_TAG,
1768                                             1, YAML_ANY_MAPPING_STYLE);
1769         rc = yaml_emitter_emit(&output, &event);
1770         if (rc == 0)
1771                 goto emitter_error;
1772
1773         yaml_scalar_event_initialize(&event, NULL,
1774                                      (yaml_char_t *)YAML_STR_TAG,
1775                                      (yaml_char_t *)"route",
1776                                      strlen("route"), 1, 0,
1777                                      YAML_PLAIN_SCALAR_STYLE);
1778         rc = yaml_emitter_emit(&output, &event);
1779         if (rc == 0)
1780                 goto emitter_error;
1781
1782         if (nw || gws) {
1783                 yaml_sequence_start_event_initialize(&event, NULL,
1784                                                      (yaml_char_t *)YAML_SEQ_TAG,
1785                                                      1,
1786                                                      YAML_BLOCK_SEQUENCE_STYLE);
1787                 rc = yaml_emitter_emit(&output, &event);
1788                 if (rc == 0)
1789                         goto emitter_error;
1790
1791                 yaml_mapping_start_event_initialize(&event, NULL,
1792                                                     (yaml_char_t *)YAML_MAP_TAG, 1,
1793                                                     YAML_BLOCK_MAPPING_STYLE);
1794                 rc = yaml_emitter_emit(&output, &event);
1795                 if (rc == 0)
1796                         goto emitter_error;
1797
1798                 if (nw) {
1799                         yaml_scalar_event_initialize(&event, NULL,
1800                                                      (yaml_char_t *)YAML_STR_TAG,
1801                                                      (yaml_char_t *)"net",
1802                                                      strlen("net"), 1, 0,
1803                                                      YAML_PLAIN_SCALAR_STYLE);
1804                         rc = yaml_emitter_emit(&output, &event);
1805                         if (rc == 0)
1806                                 goto emitter_error;
1807
1808                         yaml_scalar_event_initialize(&event, NULL,
1809                                                      (yaml_char_t *)YAML_STR_TAG,
1810                                                      (yaml_char_t *)nw,
1811                                                      strlen(nw), 1, 0,
1812                                                      YAML_PLAIN_SCALAR_STYLE);
1813                         rc = yaml_emitter_emit(&output, &event);
1814                         if (rc == 0)
1815                                 goto emitter_error;
1816                 }
1817
1818                 if (gws) {
1819                         yaml_scalar_event_initialize(&event, NULL,
1820                                                      (yaml_char_t *)YAML_STR_TAG,
1821                                                      (yaml_char_t *)"gateway",
1822                                                      strlen("gateway"), 1, 0,
1823                                                      YAML_PLAIN_SCALAR_STYLE);
1824                         rc = yaml_emitter_emit(&output, &event);
1825                         if (rc == 0)
1826                                 goto emitter_error;
1827
1828                         yaml_scalar_event_initialize(&event, NULL,
1829                                                      (yaml_char_t *)YAML_STR_TAG,
1830                                                      (yaml_char_t *)gws,
1831                                                      strlen(gws), 1, 0,
1832                                                      YAML_PLAIN_SCALAR_STYLE);
1833                         rc = yaml_emitter_emit(&output, &event);
1834                         if (rc == 0)
1835                                 goto emitter_error;
1836                 }
1837
1838                 if (notify_time) {
1839                         char when[INT_STRING_LEN];
1840
1841                         yaml_scalar_event_initialize(&event, NULL,
1842                                                      (yaml_char_t *)YAML_STR_TAG,
1843                                                      (yaml_char_t *)"notify_time",
1844                                                      strlen("notify_time"), 1, 0,
1845                                                      YAML_PLAIN_SCALAR_STYLE);
1846                         rc = yaml_emitter_emit(&output, &event);
1847                         if (rc == 0)
1848                                 goto emitter_error;
1849
1850                         snprintf(when, sizeof(when), "%ld", notify_time);
1851                         yaml_scalar_event_initialize(&event, NULL,
1852                                                      (yaml_char_t *)YAML_INT_TAG,
1853                                                      (yaml_char_t *)when,
1854                                                      strlen(when), 1, 0,
1855                                                      YAML_PLAIN_SCALAR_STYLE);
1856                         rc = yaml_emitter_emit(&output, &event);
1857                         if (rc == 0)
1858                                 goto emitter_error;
1859                 }
1860
1861                 yaml_scalar_event_initialize(&event, NULL,
1862                                              (yaml_char_t *)YAML_STR_TAG,
1863                                              (yaml_char_t *)"state",
1864                                              strlen("state"), 1, 0,
1865                                              YAML_PLAIN_SCALAR_STYLE);
1866                 rc = yaml_emitter_emit(&output, &event);
1867                 if (rc == 0)
1868                         goto emitter_error;
1869
1870                 if (enable)
1871                         yaml_scalar_event_initialize(&event, NULL,
1872                                                      (yaml_char_t *)YAML_STR_TAG,
1873                                                      (yaml_char_t *)"up",
1874                                                      strlen("up"), 1, 0,
1875                                                      YAML_PLAIN_SCALAR_STYLE);
1876                 else
1877                         yaml_scalar_event_initialize(&event, NULL,
1878                                                      (yaml_char_t *)YAML_STR_TAG,
1879                                                      (yaml_char_t *)"down",
1880                                                      strlen("down"), 1, 0,
1881                                                      YAML_PLAIN_SCALAR_STYLE);
1882
1883                 rc = yaml_emitter_emit(&output, &event);
1884                 if (rc == 0)
1885                         goto emitter_error;
1886
1887                 yaml_mapping_end_event_initialize(&event);
1888                 rc = yaml_emitter_emit(&output, &event);
1889                 if (rc == 0)
1890                         goto emitter_error;
1891
1892                 yaml_sequence_end_event_initialize(&event);
1893                 rc = yaml_emitter_emit(&output, &event);
1894                 if (rc == 0)
1895                         goto emitter_error;
1896         } else {
1897                 yaml_scalar_event_initialize(&event, NULL,
1898                                              (yaml_char_t *)YAML_STR_TAG,
1899                                              (yaml_char_t *)"",
1900                                              strlen(""), 1, 0,
1901                                              YAML_PLAIN_SCALAR_STYLE);
1902                 rc = yaml_emitter_emit(&output, &event);
1903                 if (rc == 0)
1904                         goto emitter_error;
1905         }
1906
1907         yaml_mapping_end_event_initialize(&event);
1908         rc = yaml_emitter_emit(&output, &event);
1909         if (rc == 0)
1910                 goto emitter_error;
1911
1912         yaml_document_end_event_initialize(&event, 0);
1913         rc = yaml_emitter_emit(&output, &event);
1914         if (rc == 0)
1915                 goto emitter_error;
1916
1917         rc = yaml_emitter_close(&output);
1918 emitter_error:
1919         if (rc == 0) {
1920                 yaml_emitter_log_error(&output, stderr);
1921                 rc = -EINVAL;
1922         } else {
1923                 if (flags != NLM_F_DUMP) {
1924                         yaml_document_t errmsg;
1925
1926                         rc = yaml_parser_load(&reply, &errmsg);
1927                         if (rc == 1) {
1928                                 yaml_emitter_t debug;
1929
1930                                 rc = yaml_emitter_initialize(&debug);
1931                                 if (rc == 1) {
1932                                         yaml_emitter_set_indent(&debug,
1933                                                                 LNET_DEFAULT_INDENT);
1934                                         yaml_emitter_set_output_file(&debug,
1935                                                                      stdout);
1936                                         rc = yaml_emitter_dump(&debug,
1937                                                                &errmsg);
1938                                 } else if (rc == 0) {
1939                                         yaml_emitter_log_error(&debug, stderr);
1940                                         rc = -EINVAL;
1941                                 }
1942                                 yaml_emitter_delete(&debug);
1943                         }
1944                         yaml_document_delete(&errmsg);
1945                 } else {
1946                         rc = ptl_yaml_route_display(&reply);
1947                 }
1948                 if (rc == 0)
1949                         msg = yaml_parser_get_reader_error(&reply);
1950         }
1951         yaml_emitter_delete(&output);
1952 free_reply:
1953         if (msg)
1954                 fprintf(stdout, "%s\n", msg);
1955         yaml_parser_delete(&reply);
1956         nl_socket_free(sk);
1957
1958         return rc == 1 ? 0 : rc;
1959 }
1960
1961 int
1962 jt_ptl_add_route(int argc, char **argv)
1963 {
1964         struct lnet_ioctl_config_data data;
1965         lnet_nid_t gateway_nid;
1966         __u32 hops = LNET_UNDEFINED_HOPS;
1967         unsigned int priority = 0;
1968         char *end;
1969         int rc;
1970
1971         if (argc < 2 || argc > 4) {
1972                 fprintf(stderr, "usage: %s gateway [hopcount [priority]]\n",
1973                         argv[0]);
1974                 return -1;
1975         }
1976
1977         if (g_net_is_set(argv[0]) == 0)
1978                 return -1;
1979
1980         gateway_nid = libcfs_str2nid(argv[1]);
1981         if (gateway_nid == LNET_NID_ANY) {
1982                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1983                 return -1;
1984         }
1985
1986         if (argc > 2) {
1987                 hops = strtol(argv[2], &end, 0);
1988                 if (hops == 0 || hops >= 256 ||
1989                     (end && *end != 0)) {
1990                         fprintf(stderr, "Can't parse hopcount \"%s\"\n",
1991                                 argv[2]);
1992                         return -1;
1993                 }
1994                 if (argc == 4) {
1995                         priority = strtoul(argv[3], &end, 0);
1996                         if (end && *end != 0) {
1997                                 fprintf(stderr,
1998                                         "Can't parse priority \"%s\"\n",
1999                                         argv[3]);
2000                                 return -1;
2001                         }
2002                 }
2003         }
2004
2005         rc = ptl_yaml_route(libcfs_net2str(g_net), argv[1], hops,
2006                             priority, false, 0, NLM_F_CREATE, LNET_GENL_VERSION);
2007         if (rc <= 0) {
2008                 if (rc == -EOPNOTSUPP)
2009                         goto old_api;
2010                 return rc;
2011         }
2012 old_api:
2013         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2014         data.cfg_net = g_net;
2015         data.cfg_config_u.cfg_route.rtr_hop = hops;
2016         data.cfg_nid = gateway_nid;
2017         data.cfg_config_u.cfg_route.rtr_priority = priority;
2018
2019         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
2020         if (rc != 0) {
2021                 fprintf(stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n",
2022                         strerror(errno));
2023                 return -1;
2024         }
2025
2026         return 0;
2027 }
2028
2029 int
2030 jt_ptl_del_route(int argc, char **argv)
2031 {
2032         struct lnet_ioctl_config_data data;
2033         lnet_nid_t nid;
2034         int rc;
2035
2036         if (argc != 2) {
2037                 fprintf(stderr, "usage: %s gatewayNID\n", argv[0]);
2038                 return 0;
2039         }
2040
2041         if (libcfs_str2anynid(&nid, argv[1]) == 0) {
2042                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
2043                 return -1;
2044         }
2045
2046         rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
2047                             -1, -1, false, 0, 0, LNET_GENL_VERSION);
2048         if (rc <= 0) {
2049                 if (rc == -EOPNOTSUPP)
2050                         goto old_api;
2051                 return rc;
2052         }
2053 old_api:
2054         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2055         data.cfg_net = g_net_set ? g_net : LNET_NET_ANY;
2056         data.cfg_nid = nid;
2057
2058         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
2059         if (rc != 0) {
2060                 fprintf(stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n",
2061                         libcfs_nid2str(nid), strerror(errno));
2062                 return -1;
2063         }
2064
2065         return 0;
2066 }
2067
2068 int
2069 jt_ptl_notify_router(int argc, char **argv)
2070 {
2071         struct libcfs_ioctl_data data;
2072         int enable;
2073         lnet_nid_t nid;
2074         int rc;
2075         struct timeval now;
2076         time_t when;
2077
2078         if (argc < 3) {
2079                 fprintf(stderr, "usage: %s targetNID <up/down> [<time>]\n",
2080                         argv[0]);
2081                 return 0;
2082         }
2083
2084         nid = libcfs_str2nid(argv[1]);
2085         if (nid == LNET_NID_ANY) {
2086                 fprintf(stderr, "Can't parse target NID \"%s\"\n", argv[1]);
2087                 return -1;
2088         }
2089
2090         if (lnet_parse_bool (&enable, argv[2]) != 0) {
2091                 fprintf(stderr, "Can't parse boolean %s\n", argv[2]);
2092                 return -1;
2093         }
2094
2095         gettimeofday(&now, NULL);
2096
2097         if (argc < 4) {
2098                 when = now.tv_sec;
2099         } else if (lnet_parse_time(&when, argv[3]) != 0) {
2100                 fprintf(stderr,
2101                         "Can't parse time %s\n Please specify either 'YYYY-MM-DD-HH:MM:SS'\n or an absolute unix time in seconds\n",
2102                         argv[3]);
2103                 return -1;
2104         } else if (when > now.tv_sec) {
2105                 fprintf(stderr, "%s specifies a time in the future\n",
2106                         argv[3]);
2107                 return -1;
2108         }
2109
2110         rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
2111                             -1, -1, enable, when, NLM_F_REPLACE, LNET_GENL_VERSION);
2112         if (rc <= 0) {
2113                 if (rc == -EOPNOTSUPP)
2114                         goto old_api;
2115                 return rc;
2116         }
2117 old_api:
2118         LIBCFS_IOC_INIT(data);
2119         data.ioc_nid = nid;
2120         data.ioc_flags = enable;
2121         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
2122         data.ioc_u64[0] = (__u64)when;
2123
2124         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_NOTIFY_ROUTER, &data);
2125         if (rc != 0) {
2126                 fprintf(stderr, "IOC_LIBCFS_NOTIFY_ROUTER (%s) failed: %s\n",
2127                         libcfs_nid2str(nid), strerror(errno));
2128                 return -1;
2129         }
2130
2131         return 0;
2132 }
2133
2134 int
2135 jt_ptl_print_routes(int argc, char **argv)
2136 {
2137         struct lnet_ioctl_config_data  data;
2138         int rc;
2139         int index;
2140         __u32 net;
2141         lnet_nid_t nid;
2142         int hops;
2143         int alive;
2144         unsigned int pri;
2145
2146         rc = ptl_yaml_route(NULL, NULL, -1, -1, false, 0, NLM_F_DUMP,
2147                             LNET_GENL_VERSION);
2148         if (rc <= 0) {
2149                 if (rc == -EOPNOTSUPP)
2150                         goto old_api;
2151                 return rc;
2152         }
2153 old_api:
2154         for (index = 0; ; index++) {
2155                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2156                 data.cfg_count = index;
2157
2158                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
2159                 if (rc != 0)
2160                         break;
2161
2162                 net     = data.cfg_net;
2163                 hops    = data.cfg_config_u.cfg_route.rtr_hop;
2164                 nid     = data.cfg_nid;
2165                 alive   = data.cfg_config_u.cfg_route.rtr_flags & LNET_RT_ALIVE;
2166                 pri     = data.cfg_config_u.cfg_route.rtr_priority;
2167
2168                 printf("net %18s hops %d gw %32s %s pri %u\n",
2169                        libcfs_net2str(net), hops,
2170                        libcfs_nid2str(nid), alive ? "up" : "down", pri);
2171         }
2172
2173         if (errno != ENOENT)
2174                 fprintf(stderr, "Error getting routes: %s: check dmesg.\n",
2175                         strerror(errno));
2176
2177         return 0;
2178 }
2179
2180 static int
2181 fault_attr_nid_parse(char *str, lnet_nid_t *nid_p)
2182 {
2183         lnet_nid_t nid;
2184         __u32 net;
2185         int rc = 0;
2186
2187         /* NB: can't support range ipaddress except * and *@net */
2188         if (strlen(str) > 2 && str[0] == '*' && str[1] == '@') {
2189                 net = libcfs_str2net(str + 2);
2190                 if (net == LNET_NET_ANY)
2191                         goto failed;
2192
2193                 nid = LNET_MKNID(net, LNET_NIDADDR(LNET_NID_ANY));
2194         } else {
2195                 rc = libcfs_str2anynid(&nid, str);
2196                 if (!rc)
2197                         goto failed;
2198         }
2199
2200         *nid_p = nid;
2201         return 0;
2202 failed:
2203         fprintf(stderr, "Invalid NID : %s\n", str);
2204         return -1;
2205 }
2206
2207 static int
2208 fault_attr_msg_parse(char *msg_str, __u32 *mask_p)
2209 {
2210         if (!strcasecmp(msg_str, "put")) {
2211                 *mask_p |= LNET_PUT_BIT;
2212                 return 0;
2213
2214         } else if (!strcasecmp(msg_str, "ack")) {
2215                 *mask_p |= LNET_ACK_BIT;
2216                 return 0;
2217
2218         } else if (!strcasecmp(msg_str, "get")) {
2219                 *mask_p |= LNET_GET_BIT;
2220                 return 0;
2221
2222         } else if (!strcasecmp(msg_str, "reply")) {
2223                 *mask_p |= LNET_REPLY_BIT;
2224                 return 0;
2225         }
2226
2227         fprintf(stderr, "unknown message type %s\n", msg_str);
2228         return -1;
2229 }
2230
2231 static int
2232 fault_attr_ptl_parse(char *ptl_str, __u64 *mask_p)
2233 {
2234         unsigned long rc = strtoul(optarg, NULL, 0);
2235
2236         if (rc >= 64) {
2237                 fprintf(stderr, "invalid portal: %lu\n", rc);
2238                 return -1;
2239         }
2240
2241         *mask_p |= (1ULL << rc);
2242         return 0;
2243 }
2244
2245 static int
2246 fault_attr_health_error_parse(char *error, __u32 *mask)
2247 {
2248         if (!strcasecmp(error, "local_interrupt")) {
2249                 *mask |= HSTATUS_LOCAL_INTERRUPT_BIT;
2250                 return 0;
2251         }
2252         if (!strcasecmp(error, "local_dropped")) {
2253                 *mask |= HSTATUS_LOCAL_DROPPED_BIT;
2254                 return 0;
2255         }
2256         if (!strcasecmp(error, "local_aborted")) {
2257                 *mask |= HSTATUS_LOCAL_ABORTED_BIT;
2258                 return 0;
2259         }
2260         if (!strcasecmp(error, "local_no_route")) {
2261                 *mask |= HSTATUS_LOCAL_NO_ROUTE_BIT;
2262                 return 0;
2263         }
2264         if (!strcasecmp(error, "local_error")) {
2265                 *mask |= HSTATUS_LOCAL_ERROR_BIT;
2266                 return 0;
2267         }
2268         if (!strcasecmp(error, "local_timeout")) {
2269                 *mask |= HSTATUS_LOCAL_TIMEOUT_BIT;
2270                 return 0;
2271         }
2272         if (!strcasecmp(error, "remote_error")) {
2273                 *mask |= HSTATUS_REMOTE_ERROR_BIT;
2274                 return 0;
2275         }
2276         if (!strcasecmp(error, "remote_dropped")) {
2277                 *mask |= HSTATUS_REMOTE_DROPPED_BIT;
2278                 return 0;
2279         }
2280         if (!strcasecmp(error, "remote_timeout")) {
2281                 *mask |= HSTATUS_REMOTE_TIMEOUT_BIT;
2282                 return 0;
2283         }
2284         if (!strcasecmp(error, "network_timeout")) {
2285                 *mask |= HSTATUS_NETWORK_TIMEOUT_BIT;
2286                 return 0;
2287         }
2288         if (!strcasecmp(error, "random")) {
2289                 *mask = HSTATUS_RANDOM;
2290                 return 0;
2291         }
2292
2293         return -1;
2294 }
2295
2296 static int
2297 fault_simul_rule_add(__u32 opc, char *name, int argc, char **argv)
2298 {
2299         struct libcfs_ioctl_data  data = { { 0 } };
2300         struct lnet_fault_attr    attr;
2301         char *optstr;
2302         int rc;
2303
2304         static const struct option opts[] = {
2305         { .name = "source",   .has_arg = required_argument, .val = 's' },
2306         { .name = "dest",     .has_arg = required_argument, .val = 'd' },
2307         { .name = "rate",     .has_arg = required_argument, .val = 'r' },
2308         { .name = "interval", .has_arg = required_argument, .val = 'i' },
2309         { .name = "random",   .has_arg = no_argument,       .val = 'n' },
2310         { .name = "latency",  .has_arg = required_argument, .val = 'l' },
2311         { .name = "portal",   .has_arg = required_argument, .val = 'p' },
2312         { .name = "message",  .has_arg = required_argument, .val = 'm' },
2313         { .name = "health_error",  .has_arg = required_argument, .val = 'e' },
2314         { .name = "local_nid",  .has_arg = required_argument, .val = 'o' },
2315         { .name = "drop_all",  .has_arg = no_argument, .val = 'x' },
2316         { .name = NULL } };
2317
2318         if (argc == 1) {
2319                 fprintf(stderr,
2320                         "Failed, please provide source, destination and rate of rule\n");
2321                 return -1;
2322         }
2323
2324         optstr = opc == LNET_CTL_DROP_ADD ? "s:d:o:r:i:p:m:e:nx" : "s:d:o:r:l:p:m:";
2325         memset(&attr, 0, sizeof(attr));
2326         while (1) {
2327                 int c = getopt_long(argc, argv, optstr, opts, NULL);
2328
2329                 if (c == -1)
2330                         break;
2331
2332                 switch (c) {
2333                 case 'o':
2334                         rc = fault_attr_nid_parse(optarg, &attr.fa_local_nid);
2335                         if (rc != 0)
2336                                 goto getopt_failed;
2337                         break;
2338                 case 's': /* source NID/NET */
2339                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
2340                         if (rc != 0)
2341                                 goto getopt_failed;
2342                         break;
2343
2344                 case 'd': /* dest NID/NET */
2345                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
2346                         if (rc != 0)
2347                                 goto getopt_failed;
2348                         break;
2349
2350                 case 'r': /* drop rate */
2351                         if (opc == LNET_CTL_DROP_ADD)
2352                                 attr.u.drop.da_rate = strtoul(optarg, NULL, 0);
2353                         else
2354                                 attr.u.delay.la_rate = strtoul(optarg, NULL, 0);
2355                         break;
2356
2357                 case 'e':
2358                         if (opc == LNET_CTL_DROP_ADD) {
2359                                 rc = fault_attr_health_error_parse(optarg,
2360                                                                    &attr.u.drop.da_health_error_mask);
2361                                 if (rc)
2362                                         goto getopt_failed;
2363                         }
2364                         break;
2365
2366                 case 'x':
2367                         if (opc == LNET_CTL_DROP_ADD)
2368                                 attr.u.drop.da_drop_all = true;
2369                         break;
2370
2371                 case 'n':
2372                         if (opc == LNET_CTL_DROP_ADD)
2373                                 attr.u.drop.da_random = true;
2374                         break;
2375
2376                 case 'i': /* time interval (# seconds) for message drop */
2377                         if (opc == LNET_CTL_DROP_ADD)
2378                                 attr.u.drop.da_interval = strtoul(optarg,
2379                                                                   NULL, 0);
2380                         else
2381                                 attr.u.delay.la_interval = strtoul(optarg,
2382                                                                    NULL, 0);
2383                         break;
2384
2385                 case 'l': /* seconds to wait before activating rule */
2386                         attr.u.delay.la_latency = strtoul(optarg, NULL, 0);
2387                         break;
2388
2389                 case 'p': /* portal to filter */
2390                         rc = fault_attr_ptl_parse(optarg, &attr.fa_ptl_mask);
2391                         if (rc != 0)
2392                                 goto getopt_failed;
2393                         break;
2394
2395                 case 'm': /* message types to filter */
2396                         rc = fault_attr_msg_parse(optarg, &attr.fa_msg_mask);
2397                         if (rc != 0)
2398                                 goto getopt_failed;
2399                         break;
2400
2401                 default:
2402                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
2403                                 argv[0], argv[optind - 1]);
2404                         goto getopt_failed;
2405                 }
2406         }
2407         optind = 1;
2408
2409         if (opc == LNET_CTL_DROP_ADD) {
2410                 /* NB: drop rate and interval are exclusive to each other */
2411                 if (!((attr.u.drop.da_rate == 0) ^
2412                       (attr.u.drop.da_interval == 0))) {
2413                         fprintf(stderr,
2414                                 "please provide either drop rate or interval but not both at the same time.\n");
2415                         return -1;
2416                 }
2417
2418                 if (attr.u.drop.da_random &&
2419                     attr.u.drop.da_interval == 0) {
2420                         fprintf(stderr,
2421                                 "please provide an interval to randomize\n");
2422                         return -1;
2423                 }
2424         } else if (opc == LNET_CTL_DELAY_ADD) {
2425                 if (!((attr.u.delay.la_rate == 0) ^
2426                       (attr.u.delay.la_interval == 0))) {
2427                         fprintf(stderr,
2428                                 "please provide either delay rate or interval but not both at the same time.\n");
2429                         return -1;
2430                 }
2431
2432                 if (attr.u.delay.la_latency == 0) {
2433                         fprintf(stderr, "latency cannot be zero\n");
2434                         return -1;
2435                 }
2436         }
2437
2438         if (attr.fa_src == 0 || attr.fa_dst == 0) {
2439                 fprintf(stderr,
2440                         "Please provide both source and destination of %s rule\n",
2441                         name);
2442                 return -1;
2443         }
2444
2445         if (attr.fa_local_nid == 0)
2446                 attr.fa_local_nid = LNET_NID_ANY;
2447
2448         data.ioc_flags = opc;
2449         data.ioc_inllen1 = sizeof(attr);
2450         data.ioc_inlbuf1 = (char *)&attr;
2451         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2452                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
2453                 return -1;
2454         }
2455
2456         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2457         if (rc != 0) {
2458                 fprintf(stderr, "add %s rule %s->%s failed: %s\n",
2459                         name, libcfs_nid2str(attr.fa_src),
2460                         libcfs_nid2str(attr.fa_dst), strerror(errno));
2461                 return -1;
2462         }
2463
2464         printf("Added %s rule %s->%s (1/%d)\n",
2465                name, libcfs_nid2str(attr.fa_src), libcfs_nid2str(attr.fa_dst),
2466                opc == LNET_CTL_DROP_ADD ?
2467                attr.u.drop.da_rate : attr.u.delay.la_rate);
2468         return 0;
2469
2470 getopt_failed:
2471         optind = 1;
2472         return -1;
2473 }
2474
2475 int
2476 jt_ptl_drop_add(int argc, char **argv)
2477 {
2478         return fault_simul_rule_add(LNET_CTL_DROP_ADD, "drop", argc, argv);
2479 }
2480
2481 int
2482 jt_ptl_delay_add(int argc, char **argv)
2483 {
2484         return fault_simul_rule_add(LNET_CTL_DELAY_ADD, "delay", argc, argv);
2485 }
2486
2487 static int
2488 fault_simul_rule_del(__u32 opc, char *name, int argc, char **argv)
2489 {
2490         struct libcfs_ioctl_data data = { { 0 } };
2491         struct lnet_fault_attr   attr;
2492         bool all = false;
2493         int rc;
2494
2495         static const struct option opts[] = {
2496                 { .name = "source", .has_arg = required_argument, .val = 's' },
2497                 { .name = "dest",   .has_arg = required_argument, .val = 'd' },
2498                 { .name = "all",    .has_arg = no_argument,       .val = 'a' },
2499                 { .name = NULL } };
2500
2501         if (argc == 1) {
2502                 fprintf(stderr,
2503                         "Failed, please provide source and destination of rule\n");
2504                 return -1;
2505         }
2506
2507         memset(&attr, 0, sizeof(attr));
2508         while (1) {
2509                 int c = getopt_long(argc, argv, "s:d:a", opts, NULL);
2510
2511                 if (c == -1 || all)
2512                         break;
2513
2514                 switch (c) {
2515                 case 's':
2516                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
2517                         if (rc != 0)
2518                                 goto getopt_failed;
2519                         break;
2520                 case 'd':
2521                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
2522                         if (rc != 0)
2523                                 goto getopt_failed;
2524                         break;
2525                 case 'a':
2526                         attr.fa_src = 0;
2527                         attr.fa_dst = 0;
2528                         all = true;
2529
2530                         break;
2531                 default:
2532                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
2533                                 argv[0], argv[optind - 1]);
2534                         goto getopt_failed;
2535                 }
2536         }
2537         optind = 1;
2538
2539         data.ioc_flags = opc;
2540         data.ioc_inllen1 = sizeof(attr);
2541         data.ioc_inlbuf1 = (char *)&attr;
2542         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2543                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
2544                 return -1;
2545         }
2546
2547         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2548         if (rc != 0) {
2549                 fprintf(stderr, "remove %s rule %s->%s failed: %s\n", name,
2550                         all ? "all" : libcfs_nid2str(attr.fa_src),
2551                         all ? "all" : libcfs_nid2str(attr.fa_dst),
2552                         strerror(errno));
2553                 return -1;
2554         }
2555
2556         libcfs_ioctl_unpack(&data, ioc_buf);
2557         printf("Removed %d %s rules\n", data.ioc_count, name);
2558         return 0;
2559
2560 getopt_failed:
2561         optind = 1;
2562         return -1;
2563 }
2564
2565 int
2566 jt_ptl_drop_del(int argc, char **argv)
2567 {
2568         return fault_simul_rule_del(LNET_CTL_DROP_DEL, "drop", argc, argv);
2569 }
2570
2571 int
2572 jt_ptl_delay_del(int argc, char **argv)
2573 {
2574         return fault_simul_rule_del(LNET_CTL_DELAY_DEL, "delay", argc, argv);
2575 }
2576
2577 static int
2578 fault_simul_rule_reset(__u32 opc, char *name, int argc, char **argv)
2579 {
2580         struct libcfs_ioctl_data   data = { { 0 } };
2581         int                        rc;
2582
2583         LIBCFS_IOC_INIT(data);
2584         data.ioc_flags = opc;
2585
2586         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, &data);
2587         if (rc != 0) {
2588                 fprintf(stderr, "failed to reset %s stats: %s\n",
2589                         name, strerror(errno));
2590                 return -1;
2591         }
2592         return 0;
2593 }
2594
2595 int
2596 jt_ptl_drop_reset(int argc, char **argv)
2597 {
2598         return fault_simul_rule_reset(LNET_CTL_DROP_RESET, "drop", argc, argv);
2599 }
2600
2601 int
2602 jt_ptl_delay_reset(int argc, char **argv)
2603 {
2604         return fault_simul_rule_reset(LNET_CTL_DELAY_RESET, "delay",
2605                                       argc, argv);
2606 }
2607
2608 static int
2609 fault_simul_rule_list(__u32 opc, char *name, int argc, char **argv)
2610 {
2611         struct libcfs_ioctl_data data = { { 0 } };
2612         struct lnet_fault_attr   attr;
2613         struct lnet_fault_stat   stat;
2614         int pos;
2615
2616         printf("LNet %s rules:\n", name);
2617         for (pos = 0;; pos++) {
2618                 int rc;
2619
2620                 memset(&attr, 0, sizeof(attr));
2621                 memset(&stat, 0, sizeof(stat));
2622
2623                 data.ioc_count = pos;
2624                 data.ioc_flags = opc;
2625                 data.ioc_inllen1 = sizeof(attr);
2626                 data.ioc_inlbuf1 = (char *)&attr;
2627                 data.ioc_inllen2 = sizeof(stat);
2628                 data.ioc_inlbuf2 = (char *)&stat;
2629                 if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2630                         fprintf(stderr, "libcfs_ioctl_pack failed\n");
2631                         return -1;
2632                 }
2633
2634                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2635                 if (rc != 0)
2636                         break;
2637
2638                 libcfs_ioctl_unpack(&data, ioc_buf);
2639
2640                 if (opc == LNET_CTL_DROP_LIST) {
2641                         printf("%s->%s (1/%d | %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
2642                                libcfs_nid2str(attr.fa_src),
2643                                libcfs_nid2str(attr.fa_dst),
2644                                attr.u.drop.da_rate, attr.u.drop.da_interval,
2645                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
2646                                (uintmax_t)stat.u.drop.ds_dropped,
2647                                (uintmax_t)stat.fs_count,
2648                                (uintmax_t)stat.fs_put,
2649                                (uintmax_t)stat.fs_ack,
2650                                (uintmax_t)stat.fs_get,
2651                                (uintmax_t)stat.fs_reply);
2652
2653                 } else if (opc == LNET_CTL_DELAY_LIST) {
2654                         printf("%s->%s (1/%d | %d, latency %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
2655                                libcfs_nid2str(attr.fa_src),
2656                                libcfs_nid2str(attr.fa_dst),
2657                                attr.u.delay.la_rate, attr.u.delay.la_interval,
2658                                attr.u.delay.la_latency,
2659                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
2660                                (uintmax_t)stat.u.delay.ls_delayed,
2661                                (uintmax_t)stat.fs_count,
2662                                (uintmax_t)stat.fs_put,
2663                                (uintmax_t)stat.fs_ack,
2664                                (uintmax_t)stat.fs_get,
2665                                (uintmax_t)stat.fs_reply);
2666                 }
2667         }
2668         printf("found total %d\n", pos);
2669
2670         return 0;
2671 }
2672
2673 int
2674 jt_ptl_drop_list(int argc, char **argv)
2675 {
2676         return fault_simul_rule_list(LNET_CTL_DROP_LIST, "drop", argc, argv);
2677 }
2678
2679 int
2680 jt_ptl_delay_list(int argc, char **argv)
2681 {
2682         return fault_simul_rule_list(LNET_CTL_DELAY_LIST, "delay", argc, argv);
2683 }
2684
2685 double
2686 get_cycles_per_usec()
2687 {
2688         FILE *f = fopen("/proc/cpuinfo", "r");
2689         double mhz;
2690         char line[64];
2691
2692         if (f) {
2693                 while (fgets(line, sizeof(line), f))
2694                         if (sscanf(line, "cpu MHz : %lf", &mhz) == 1) {
2695                                 fclose(f);
2696                                 return mhz;
2697                         }
2698                 fclose(f);
2699         }
2700
2701         fprintf(stderr, "Can't read/parse /proc/cpuinfo\n");
2702         return 1000.0;
2703 }
2704
2705 int jt_ptl_testprotocompat(int argc, char **argv)
2706 {
2707         struct libcfs_ioctl_data  data;
2708         int rc;
2709         int flags;
2710         char *end;
2711
2712         if (argc < 2)  {
2713                 fprintf(stderr, "usage: %s <number>\n", argv[0]);
2714                 return 0;
2715         }
2716
2717         flags = strtol(argv[1], &end, 0);
2718         if (flags < 0 || *end != 0) {
2719                 fprintf(stderr, "Can't parse flags '%s'\n", argv[1]);
2720                 return -1;
2721         }
2722
2723         LIBCFS_IOC_INIT(data);
2724         data.ioc_flags = flags;
2725         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_TESTPROTOCOMPAT, &data);
2726
2727         if (rc != 0) {
2728                 fprintf(stderr, "test proto compat %x failed: %s\n",
2729                         flags, strerror(errno));
2730                 return -1;
2731         }
2732
2733         printf("test proto compat %x OK\n", flags);
2734         return 0;
2735 }