Whamcloud - gitweb
LU-10003 lnet: Update lctl ping to work with large NIDs
[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_processid *id_ptr)
231 {
232         id_ptr->pid = LNET_PID_ANY;
233         if (libcfs_strnid(&id_ptr->nid, nid_str) < 0 ||
234             LNET_NID_IS_ANY(&id_ptr->nid)) {
235                 fprintf(stderr, "Invalid NID argument \"%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_processid 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                         if (libcfs_strnid(&id.nid, (sep + 1)) < 0 ||
1308                             LNET_NID_IS_ANY(&id.nid)) {
1309                                 fprintf(stderr,
1310                                         "Invalid PID argument \"%s\"\n",
1311                                         argv[1]);
1312                                 return -EINVAL;
1313                         }
1314                 }
1315         }
1316
1317         if (argc > 2) {
1318                 timeout = 1000 * atol(argv[2]);
1319                 if (timeout > 120 * 1000) {
1320                         fprintf(stderr, "Timeout %s is to large\n",
1321                                 argv[2]);
1322                         return -EINVAL;
1323                 }
1324         } else {
1325                 timeout = 1000; /* default 1 second timeout */
1326         }
1327
1328         /* Create Netlink emitter to send request to kernel */
1329         sk = nl_socket_alloc();
1330         if (!sk)
1331                 goto old_api;
1332
1333         /* Setup parser to recieve Netlink packets */
1334         rc = yaml_parser_initialize(&reply);
1335         if (rc == 0)
1336                 goto old_api;
1337
1338         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1339         if (rc == 0)
1340                 goto free_reply;
1341
1342         /* Create Netlink emitter to send request to kernel */
1343         rc = yaml_emitter_initialize(&request);
1344         if (rc == 0)
1345                 goto free_reply;
1346
1347         rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
1348                                              LNET_GENL_VERSION, LNET_CMD_PING,
1349                                              NLM_F_DUMP);
1350         if (rc == 0)
1351                 goto emitter_error;
1352
1353         yaml_emitter_open(&request);
1354         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1355         rc = yaml_emitter_emit(&request, &event);
1356         if (rc == 0)
1357                 goto emitter_error;
1358
1359         yaml_mapping_start_event_initialize(&event, NULL,
1360                                             (yaml_char_t *)YAML_MAP_TAG,
1361                                             1, YAML_ANY_MAPPING_STYLE);
1362         rc = yaml_emitter_emit(&request, &event);
1363         if (rc == 0)
1364                 goto emitter_error;
1365
1366         yaml_scalar_event_initialize(&event, NULL,
1367                                      (yaml_char_t *)YAML_STR_TAG,
1368                                      (yaml_char_t *)"ping",
1369                                      strlen("ping"), 1, 0,
1370                                      YAML_PLAIN_SCALAR_STYLE);
1371         rc = yaml_emitter_emit(&request, &event);
1372         if (rc == 0)
1373                 goto emitter_error;
1374
1375         yaml_mapping_start_event_initialize(&event, NULL,
1376                                             (yaml_char_t *)YAML_MAP_TAG,
1377                                             1, YAML_ANY_MAPPING_STYLE);
1378         rc = yaml_emitter_emit(&request, &event);
1379         if (rc == 0)
1380                 goto emitter_error;
1381
1382         if (timeout != 1000) {
1383                 yaml_scalar_event_initialize(&event, NULL,
1384                                              (yaml_char_t *)YAML_STR_TAG,
1385                                              (yaml_char_t *)"timeout",
1386                                              strlen("timeout"), 1, 0,
1387                                              YAML_PLAIN_SCALAR_STYLE);
1388                 rc = yaml_emitter_emit(&request, &event);
1389                 if (rc == 0)
1390                         goto emitter_error;
1391
1392                 yaml_scalar_event_initialize(&event, NULL,
1393                                              (yaml_char_t *)YAML_INT_TAG,
1394                                              (yaml_char_t *)argv[2],
1395                                              strlen(argv[2]), 1, 0,
1396                                              YAML_PLAIN_SCALAR_STYLE);
1397                 rc = yaml_emitter_emit(&request, &event);
1398                 if (rc == 0)
1399                         goto emitter_error;
1400         }
1401
1402         yaml_scalar_event_initialize(&event, NULL,
1403                                      (yaml_char_t *)YAML_STR_TAG,
1404                                      (yaml_char_t *)"nids",
1405                                      strlen("nids"), 1, 0,
1406                                      YAML_PLAIN_SCALAR_STYLE);
1407         rc = yaml_emitter_emit(&request, &event);
1408         if (rc == 0)
1409                 goto emitter_error;
1410
1411         yaml_sequence_start_event_initialize(&event, NULL,
1412                                              (yaml_char_t *)YAML_SEQ_TAG,
1413                                              1, YAML_FLOW_SEQUENCE_STYLE);
1414         rc = yaml_emitter_emit(&request, &event);
1415         if (rc == 0)
1416                 goto emitter_error;
1417
1418         /* convert NID to string, in case libcfs_str2nid() did name lookup */
1419         yaml_scalar_event_initialize(&event, NULL,
1420                                      (yaml_char_t *)YAML_STR_TAG,
1421                                      (yaml_char_t *)libcfs_nidstr(&id.nid),
1422                                      strlen(libcfs_nidstr(&id.nid)), 1, 0,
1423                                      YAML_PLAIN_SCALAR_STYLE);
1424         rc = yaml_emitter_emit(&request, &event);
1425         if (rc == 0)
1426                 goto emitter_error;
1427
1428         yaml_sequence_end_event_initialize(&event);
1429         rc = yaml_emitter_emit(&request, &event);
1430         if (rc == 0)
1431                 goto emitter_error;
1432
1433         yaml_mapping_end_event_initialize(&event);
1434         rc = yaml_emitter_emit(&request, &event);
1435         if (rc == 0)
1436                 goto emitter_error;
1437
1438         yaml_mapping_end_event_initialize(&event);
1439         rc = yaml_emitter_emit(&request, &event);
1440         if (rc == 0)
1441                 goto emitter_error;
1442
1443         yaml_document_end_event_initialize(&event, 0);
1444         rc = yaml_emitter_emit(&request, &event);
1445         if (rc == 0)
1446                 goto emitter_error;
1447
1448         rc = yaml_emitter_close(&request);
1449 emitter_error:
1450         if (rc == 0) {
1451                 yaml_emitter_log_error(&request, stderr);
1452                 rc = -EINVAL;
1453                 goto old_api;
1454         }
1455         yaml_emitter_delete(&request);
1456
1457         /* Now parse the reply results */
1458         while (!done) {
1459                 rc = yaml_parser_parse(&reply, &event);
1460                 if (rc == 0)
1461                         break;
1462
1463                 if (event.type != YAML_SCALAR_EVENT)
1464                         goto skip;
1465
1466                 if (strcmp((char *)event.data.scalar.value, "nid") == 0) {
1467                         yaml_event_delete(&event);
1468                         rc = yaml_parser_parse(&reply, &event);
1469                         if (rc == 0) {
1470                                 yaml_event_delete(&event);
1471                                 goto free_reply;
1472                         }
1473                         if (print) {
1474                                 /* Print 0@lo. Its not sent */
1475                                 printf("12345-0@lo\n");
1476                                 print = false;
1477                         }
1478                         printf("%s\n", (char *)event.data.scalar.value);
1479                 } else if (strcmp((char *)event.data.scalar.value,
1480                                   "errno") == 0) {
1481                         yaml_event_delete(&event);
1482                         rc = yaml_parser_parse(&reply, &event);
1483                         if (rc == 0) {
1484                                 yaml_event_delete(&event);
1485                                 goto free_reply;
1486                         }
1487                         rc = strtol((char *)event.data.scalar.value, NULL, 10);
1488                         fprintf(stdout, "failed to ping %s: %s\n",
1489                                 argv[1], strerror(-rc));
1490                         break; /* "rc" is clobbered if loop is run again */
1491                 }
1492 skip:
1493                 done = (event.type == YAML_STREAM_END_EVENT);
1494                 yaml_event_delete(&event);
1495         }
1496 free_reply:
1497         if (rc == 0) {
1498                 /* yaml_* functions return 0 for error */
1499                 const char *msg = yaml_parser_get_reader_error(&reply);
1500
1501                 rc = errno ? -errno : -EHOSTUNREACH;
1502                 if (strcmp(msg, "Unspecific failure") != 0) {
1503                         fprintf(stdout, "failed to ping %s: %s\n",
1504                                 argv[1], msg);
1505                 } else {
1506                         fprintf(stdout, "failed to ping %s: %s\n",
1507                                 argv[1], strerror(errno));
1508                 }
1509         } else if (rc == 1) {
1510                 /* yaml_* functions return 1 for success */
1511                 rc = 0;
1512         }
1513         yaml_parser_delete(&reply);
1514         nl_socket_free(sk);
1515         return rc;
1516 old_api:
1517 #ifdef IOC_LIBCFS_PING_PEER
1518         {
1519         struct lnet_process_id ids[LNET_INTERFACES_MAX_DEFAULT];
1520         int maxids = sizeof(ids) / sizeof(ids[0]);
1521         struct lnet_ioctl_ping_data ping = { { 0 } };
1522         int i;
1523
1524         if (sk)
1525                 nl_socket_free(sk);
1526
1527         LIBCFS_IOC_INIT_V2(ping, ping_hdr);
1528         ping.ping_hdr.ioc_len = sizeof(ping);
1529         ping.ping_id = lnet_pid_to_pid4(&id);
1530         ping.ping_src = LNET_NID_ANY;
1531         ping.op_param = timeout;
1532         ping.ping_count = maxids;
1533         ping.ping_buf = ids;
1534
1535         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_PING_PEER, &ping);
1536         if (rc != 0) {
1537                 fprintf(stderr, "failed to ping %s: %s\n", argv[1],
1538                         strerror(errno));
1539                 return rc;
1540         }
1541
1542         for (i = 0; i < ping.ping_count && i < maxids; i++)
1543                 printf("%s\n", libcfs_id2str(ids[i]));
1544
1545         if (ping.ping_count > maxids)
1546                 printf("%d out of %d ids listed\n", maxids, ping.ping_count);
1547         }
1548 #else
1549         rc = -ENOTTY;
1550 #endif
1551         return rc;
1552 }
1553
1554 int jt_ptl_mynid(int argc, char **argv)
1555 {
1556         struct libcfs_ioctl_data data;
1557         lnet_nid_t nid;
1558         int rc;
1559
1560         if (argc != 2) {
1561                 fprintf(stderr, "usage: %s NID\n", argv[0]);
1562                 return 0;
1563         }
1564
1565         nid = libcfs_str2nid(argv[1]);
1566         if (nid == LNET_NID_ANY) {
1567                 fprintf(stderr, "Can't parse NID '%s'\n", argv[1]);
1568                 return -1;
1569         }
1570
1571         LIBCFS_IOC_INIT(data);
1572         data.ioc_net = LNET_NIDNET(nid);
1573         data.ioc_nid = nid;
1574
1575         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_REGISTER_MYNID, &data);
1576         if (rc < 0)
1577                 fprintf(stderr, "setting my NID failed: %s\n",
1578                         strerror(errno));
1579         else
1580                 printf("registered my nid %s\n", libcfs_nid2str(nid));
1581
1582         return 0;
1583 }
1584
1585 int
1586 jt_ptl_fail_nid(int argc, char **argv)
1587 {
1588         int rc;
1589         lnet_nid_t nid;
1590         int threshold;
1591         struct libcfs_ioctl_data data;
1592
1593         if (argc < 2 || argc > 3) {
1594                 fprintf(stderr, "usage: %s nid|\"*\" [count (0 == mend)]\n",
1595                         argv[0]);
1596                 return 0;
1597         }
1598
1599         if (!libcfs_str2anynid(&nid, argv[1])) {
1600                 fprintf(stderr, "Can't parse nid \"%s\"\n", argv[1]);
1601                 return -1;
1602         }
1603
1604         if (argc < 3) {
1605                 threshold = LNET_MD_THRESH_INF;
1606         } else if (sscanf(argv[2], "%i", &threshold) != 1) {
1607                 fprintf(stderr, "Can't parse count \"%s\"\n", argv[2]);
1608                 return -1;
1609         }
1610
1611         LIBCFS_IOC_INIT(data);
1612         data.ioc_nid = nid;
1613         data.ioc_count = threshold;
1614
1615         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_FAIL_NID, &data);
1616         if (rc < 0)
1617                 fprintf(stderr, "IOC_LIBCFS_FAIL_NID failed: %s\n",
1618                         strerror(errno));
1619         else
1620                 printf("%s %s\n",
1621                        threshold == 0 ? "Unfailing" : "Failing", argv[1]);
1622
1623         return 0;
1624 }
1625
1626 static int ptl_yaml_route_display(yaml_parser_t *reply)
1627 {
1628         char gw[LNET_MAX_STR_LEN], net[18];
1629         bool done = false, alive = false;
1630         int hops = -1, prio = -1;
1631         yaml_event_t event;
1632         int rc;
1633
1634         /* Now parse the reply results */
1635         while (!done) {
1636                 char *value;
1637
1638                 rc = yaml_parser_parse(reply, &event);
1639                 if (rc == 0)
1640                         break;
1641
1642                 if (event.type == YAML_SEQUENCE_END_EVENT) {
1643                         printf("net %18s hops %d gw %32.128s %s pri %u\n",
1644                                net, hops, gw, alive ? "up" : "down",
1645                                prio);
1646                         memset(net, '\0', sizeof(net));
1647                         memset(gw, '\0', sizeof(gw));
1648                         prio = -1;
1649                         hops = -1;
1650                 }
1651
1652                 if (event.type != YAML_SCALAR_EVENT)
1653                         goto skip;
1654
1655                 value = (char *)event.data.scalar.value;
1656                 if (strcmp(value, "net") == 0) {
1657                         yaml_event_delete(&event);
1658                         rc = yaml_parser_parse(reply, &event);
1659                         if (rc == 0) {
1660                                 yaml_event_delete(&event);
1661                                 goto free_reply;
1662                         }
1663
1664                         value = (char *)event.data.scalar.value;
1665                         strncpy(net, value, sizeof(net) - 1);
1666                 } else if (strcmp(value, "gateway") == 0) {
1667                         yaml_event_delete(&event);
1668                         rc = yaml_parser_parse(reply, &event);
1669                         if (rc == 0) {
1670                                 yaml_event_delete(&event);
1671                                 goto free_reply;
1672                         }
1673
1674                         value = (char *)event.data.scalar.value;
1675                         strncpy(gw, value, sizeof(gw) - 1);
1676                 } else if (strcmp(value, "state") == 0) {
1677                         yaml_event_delete(&event);
1678                         rc = yaml_parser_parse(reply, &event);
1679                         if (rc == 0) {
1680                                 yaml_event_delete(&event);
1681                                 goto free_reply;
1682                         }
1683
1684                         value = (char *)event.data.scalar.value;
1685                         if (strcmp(value, "up") == 0) {
1686                                 alive = true;
1687                         } else if (strcmp(value, "down") == 0) {
1688                                 alive = false;
1689                         }
1690                 } else if (strcmp(value, "hop") == 0) {
1691                         yaml_event_delete(&event);
1692                         rc = yaml_parser_parse(reply, &event);
1693                         if (rc == 0) {
1694                                 yaml_event_delete(&event);
1695                                 goto free_reply;
1696                         }
1697
1698                         value = (char *)event.data.scalar.value;
1699                         hops = strtol(value, NULL, 10);
1700                 } else if (strcmp(value, "priority") == 0) {
1701                         yaml_event_delete(&event);
1702                         rc = yaml_parser_parse(reply, &event);
1703                         if (rc == 0) {
1704                                 yaml_event_delete(&event);
1705                                 goto free_reply;
1706                         }
1707
1708                         value = (char *)event.data.scalar.value;
1709                         prio = strtol(value, NULL, 10);
1710                 }
1711 skip:
1712                 done = (event.type == YAML_STREAM_END_EVENT);
1713                 yaml_event_delete(&event);
1714         }
1715
1716 free_reply:
1717         return rc;
1718 }
1719
1720 static int ptl_yaml_route(char *nw, char *gws, int hops, int prio, bool enable,
1721                           time_t notify_time, int flags, int version)
1722 {
1723         struct nl_sock *sk = NULL;
1724         const char *msg = NULL;
1725         yaml_emitter_t output;
1726         yaml_parser_t reply;
1727         yaml_event_t event;
1728         int rc;
1729
1730         sk = nl_socket_alloc();
1731         if (!sk)
1732                 return -EOPNOTSUPP;
1733
1734         /* Setup parser to receive Netlink packets */
1735         rc = yaml_parser_initialize(&reply);
1736         if (rc == 0) {
1737                 nl_socket_free(sk);
1738                 return -EOPNOTSUPP;
1739         }
1740
1741         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1742         if (rc == 0) {
1743                 msg = yaml_parser_get_reader_error(&reply);
1744                 goto free_reply;
1745         }
1746
1747         /* Create Netlink emitter to send request to kernel */
1748         rc = yaml_emitter_initialize(&output);
1749         if (rc == 0) {
1750                 msg = "failed to initialize emitter";
1751                 goto free_reply;
1752         }
1753
1754         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1755                                              version, LNET_CMD_ROUTES, flags);
1756         if (rc == 0)
1757                 goto emitter_error;
1758
1759         yaml_emitter_open(&output);
1760         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1761         rc = yaml_emitter_emit(&output, &event);
1762         if (rc == 0)
1763                 goto emitter_error;
1764
1765         yaml_mapping_start_event_initialize(&event, NULL,
1766                                             (yaml_char_t *)YAML_MAP_TAG,
1767                                             1, YAML_ANY_MAPPING_STYLE);
1768         rc = yaml_emitter_emit(&output, &event);
1769         if (rc == 0)
1770                 goto emitter_error;
1771
1772         yaml_scalar_event_initialize(&event, NULL,
1773                                      (yaml_char_t *)YAML_STR_TAG,
1774                                      (yaml_char_t *)"route",
1775                                      strlen("route"), 1, 0,
1776                                      YAML_PLAIN_SCALAR_STYLE);
1777         rc = yaml_emitter_emit(&output, &event);
1778         if (rc == 0)
1779                 goto emitter_error;
1780
1781         if (nw || gws) {
1782                 yaml_sequence_start_event_initialize(&event, NULL,
1783                                                      (yaml_char_t *)YAML_SEQ_TAG,
1784                                                      1,
1785                                                      YAML_BLOCK_SEQUENCE_STYLE);
1786                 rc = yaml_emitter_emit(&output, &event);
1787                 if (rc == 0)
1788                         goto emitter_error;
1789
1790                 yaml_mapping_start_event_initialize(&event, NULL,
1791                                                     (yaml_char_t *)YAML_MAP_TAG, 1,
1792                                                     YAML_BLOCK_MAPPING_STYLE);
1793                 rc = yaml_emitter_emit(&output, &event);
1794                 if (rc == 0)
1795                         goto emitter_error;
1796
1797                 if (nw) {
1798                         yaml_scalar_event_initialize(&event, NULL,
1799                                                      (yaml_char_t *)YAML_STR_TAG,
1800                                                      (yaml_char_t *)"net",
1801                                                      strlen("net"), 1, 0,
1802                                                      YAML_PLAIN_SCALAR_STYLE);
1803                         rc = yaml_emitter_emit(&output, &event);
1804                         if (rc == 0)
1805                                 goto emitter_error;
1806
1807                         yaml_scalar_event_initialize(&event, NULL,
1808                                                      (yaml_char_t *)YAML_STR_TAG,
1809                                                      (yaml_char_t *)nw,
1810                                                      strlen(nw), 1, 0,
1811                                                      YAML_PLAIN_SCALAR_STYLE);
1812                         rc = yaml_emitter_emit(&output, &event);
1813                         if (rc == 0)
1814                                 goto emitter_error;
1815                 }
1816
1817                 if (gws) {
1818                         yaml_scalar_event_initialize(&event, NULL,
1819                                                      (yaml_char_t *)YAML_STR_TAG,
1820                                                      (yaml_char_t *)"gateway",
1821                                                      strlen("gateway"), 1, 0,
1822                                                      YAML_PLAIN_SCALAR_STYLE);
1823                         rc = yaml_emitter_emit(&output, &event);
1824                         if (rc == 0)
1825                                 goto emitter_error;
1826
1827                         yaml_scalar_event_initialize(&event, NULL,
1828                                                      (yaml_char_t *)YAML_STR_TAG,
1829                                                      (yaml_char_t *)gws,
1830                                                      strlen(gws), 1, 0,
1831                                                      YAML_PLAIN_SCALAR_STYLE);
1832                         rc = yaml_emitter_emit(&output, &event);
1833                         if (rc == 0)
1834                                 goto emitter_error;
1835                 }
1836
1837                 if (notify_time) {
1838                         char when[INT_STRING_LEN];
1839
1840                         yaml_scalar_event_initialize(&event, NULL,
1841                                                      (yaml_char_t *)YAML_STR_TAG,
1842                                                      (yaml_char_t *)"notify_time",
1843                                                      strlen("notify_time"), 1, 0,
1844                                                      YAML_PLAIN_SCALAR_STYLE);
1845                         rc = yaml_emitter_emit(&output, &event);
1846                         if (rc == 0)
1847                                 goto emitter_error;
1848
1849                         snprintf(when, sizeof(when), "%ld", notify_time);
1850                         yaml_scalar_event_initialize(&event, NULL,
1851                                                      (yaml_char_t *)YAML_INT_TAG,
1852                                                      (yaml_char_t *)when,
1853                                                      strlen(when), 1, 0,
1854                                                      YAML_PLAIN_SCALAR_STYLE);
1855                         rc = yaml_emitter_emit(&output, &event);
1856                         if (rc == 0)
1857                                 goto emitter_error;
1858                 }
1859
1860                 yaml_scalar_event_initialize(&event, NULL,
1861                                              (yaml_char_t *)YAML_STR_TAG,
1862                                              (yaml_char_t *)"state",
1863                                              strlen("state"), 1, 0,
1864                                              YAML_PLAIN_SCALAR_STYLE);
1865                 rc = yaml_emitter_emit(&output, &event);
1866                 if (rc == 0)
1867                         goto emitter_error;
1868
1869                 if (enable)
1870                         yaml_scalar_event_initialize(&event, NULL,
1871                                                      (yaml_char_t *)YAML_STR_TAG,
1872                                                      (yaml_char_t *)"up",
1873                                                      strlen("up"), 1, 0,
1874                                                      YAML_PLAIN_SCALAR_STYLE);
1875                 else
1876                         yaml_scalar_event_initialize(&event, NULL,
1877                                                      (yaml_char_t *)YAML_STR_TAG,
1878                                                      (yaml_char_t *)"down",
1879                                                      strlen("down"), 1, 0,
1880                                                      YAML_PLAIN_SCALAR_STYLE);
1881
1882                 rc = yaml_emitter_emit(&output, &event);
1883                 if (rc == 0)
1884                         goto emitter_error;
1885
1886                 yaml_mapping_end_event_initialize(&event);
1887                 rc = yaml_emitter_emit(&output, &event);
1888                 if (rc == 0)
1889                         goto emitter_error;
1890
1891                 yaml_sequence_end_event_initialize(&event);
1892                 rc = yaml_emitter_emit(&output, &event);
1893                 if (rc == 0)
1894                         goto emitter_error;
1895         } else {
1896                 yaml_scalar_event_initialize(&event, NULL,
1897                                              (yaml_char_t *)YAML_STR_TAG,
1898                                              (yaml_char_t *)"",
1899                                              strlen(""), 1, 0,
1900                                              YAML_PLAIN_SCALAR_STYLE);
1901                 rc = yaml_emitter_emit(&output, &event);
1902                 if (rc == 0)
1903                         goto emitter_error;
1904         }
1905
1906         yaml_mapping_end_event_initialize(&event);
1907         rc = yaml_emitter_emit(&output, &event);
1908         if (rc == 0)
1909                 goto emitter_error;
1910
1911         yaml_document_end_event_initialize(&event, 0);
1912         rc = yaml_emitter_emit(&output, &event);
1913         if (rc == 0)
1914                 goto emitter_error;
1915
1916         rc = yaml_emitter_close(&output);
1917 emitter_error:
1918         if (rc == 0) {
1919                 yaml_emitter_log_error(&output, stderr);
1920                 rc = -EINVAL;
1921         } else {
1922                 if (flags != NLM_F_DUMP) {
1923                         yaml_document_t errmsg;
1924
1925                         rc = yaml_parser_load(&reply, &errmsg);
1926                         if (rc == 1) {
1927                                 yaml_emitter_t debug;
1928
1929                                 rc = yaml_emitter_initialize(&debug);
1930                                 if (rc == 1) {
1931                                         yaml_emitter_set_indent(&debug,
1932                                                                 LNET_DEFAULT_INDENT);
1933                                         yaml_emitter_set_output_file(&debug,
1934                                                                      stdout);
1935                                         rc = yaml_emitter_dump(&debug,
1936                                                                &errmsg);
1937                                 } else if (rc == 0) {
1938                                         yaml_emitter_log_error(&debug, stderr);
1939                                         rc = -EINVAL;
1940                                 }
1941                                 yaml_emitter_delete(&debug);
1942                         }
1943                         yaml_document_delete(&errmsg);
1944                 } else {
1945                         rc = ptl_yaml_route_display(&reply);
1946                 }
1947                 if (rc == 0)
1948                         msg = yaml_parser_get_reader_error(&reply);
1949         }
1950         yaml_emitter_delete(&output);
1951 free_reply:
1952         if (msg)
1953                 fprintf(stdout, "%s\n", msg);
1954         yaml_parser_delete(&reply);
1955         nl_socket_free(sk);
1956
1957         return rc == 1 ? 0 : rc;
1958 }
1959
1960 int
1961 jt_ptl_add_route(int argc, char **argv)
1962 {
1963         struct lnet_ioctl_config_data data;
1964         lnet_nid_t gateway_nid;
1965         __u32 hops = LNET_UNDEFINED_HOPS;
1966         unsigned int priority = 0;
1967         char *end;
1968         int rc;
1969
1970         if (argc < 2 || argc > 4) {
1971                 fprintf(stderr, "usage: %s gateway [hopcount [priority]]\n",
1972                         argv[0]);
1973                 return -1;
1974         }
1975
1976         if (g_net_is_set(argv[0]) == 0)
1977                 return -1;
1978
1979         gateway_nid = libcfs_str2nid(argv[1]);
1980         if (gateway_nid == LNET_NID_ANY) {
1981                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
1982                 return -1;
1983         }
1984
1985         if (argc > 2) {
1986                 hops = strtol(argv[2], &end, 0);
1987                 if (hops == 0 || hops >= 256 ||
1988                     (end && *end != 0)) {
1989                         fprintf(stderr, "Can't parse hopcount \"%s\"\n",
1990                                 argv[2]);
1991                         return -1;
1992                 }
1993                 if (argc == 4) {
1994                         priority = strtoul(argv[3], &end, 0);
1995                         if (end && *end != 0) {
1996                                 fprintf(stderr,
1997                                         "Can't parse priority \"%s\"\n",
1998                                         argv[3]);
1999                                 return -1;
2000                         }
2001                 }
2002         }
2003
2004         rc = ptl_yaml_route(libcfs_net2str(g_net), argv[1], hops,
2005                             priority, false, 0, NLM_F_CREATE, LNET_GENL_VERSION);
2006         if (rc <= 0) {
2007                 if (rc == -EOPNOTSUPP)
2008                         goto old_api;
2009                 return rc;
2010         }
2011 old_api:
2012         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2013         data.cfg_net = g_net;
2014         data.cfg_config_u.cfg_route.rtr_hop = hops;
2015         data.cfg_nid = gateway_nid;
2016         data.cfg_config_u.cfg_route.rtr_priority = priority;
2017
2018         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_ROUTE, &data);
2019         if (rc != 0) {
2020                 fprintf(stderr, "IOC_LIBCFS_ADD_ROUTE failed: %s\n",
2021                         strerror(errno));
2022                 return -1;
2023         }
2024
2025         return 0;
2026 }
2027
2028 int
2029 jt_ptl_del_route(int argc, char **argv)
2030 {
2031         struct lnet_ioctl_config_data data;
2032         lnet_nid_t nid;
2033         int rc;
2034
2035         if (argc != 2) {
2036                 fprintf(stderr, "usage: %s gatewayNID\n", argv[0]);
2037                 return 0;
2038         }
2039
2040         if (libcfs_str2anynid(&nid, argv[1]) == 0) {
2041                 fprintf(stderr, "Can't parse gateway NID \"%s\"\n", argv[1]);
2042                 return -1;
2043         }
2044
2045         rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
2046                             -1, -1, false, 0, 0, LNET_GENL_VERSION);
2047         if (rc <= 0) {
2048                 if (rc == -EOPNOTSUPP)
2049                         goto old_api;
2050                 return rc;
2051         }
2052 old_api:
2053         LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2054         data.cfg_net = g_net_set ? g_net : LNET_NET_ANY;
2055         data.cfg_nid = nid;
2056
2057         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_ROUTE, &data);
2058         if (rc != 0) {
2059                 fprintf(stderr, "IOC_LIBCFS_DEL_ROUTE (%s) failed: %s\n",
2060                         libcfs_nid2str(nid), strerror(errno));
2061                 return -1;
2062         }
2063
2064         return 0;
2065 }
2066
2067 int
2068 jt_ptl_notify_router(int argc, char **argv)
2069 {
2070         struct libcfs_ioctl_data data;
2071         int enable;
2072         lnet_nid_t nid;
2073         int rc;
2074         struct timeval now;
2075         time_t when;
2076
2077         if (argc < 3) {
2078                 fprintf(stderr, "usage: %s targetNID <up/down> [<time>]\n",
2079                         argv[0]);
2080                 return 0;
2081         }
2082
2083         nid = libcfs_str2nid(argv[1]);
2084         if (nid == LNET_NID_ANY) {
2085                 fprintf(stderr, "Can't parse target NID \"%s\"\n", argv[1]);
2086                 return -1;
2087         }
2088
2089         if (lnet_parse_bool (&enable, argv[2]) != 0) {
2090                 fprintf(stderr, "Can't parse boolean %s\n", argv[2]);
2091                 return -1;
2092         }
2093
2094         gettimeofday(&now, NULL);
2095
2096         if (argc < 4) {
2097                 when = now.tv_sec;
2098         } else if (lnet_parse_time(&when, argv[3]) != 0) {
2099                 fprintf(stderr,
2100                         "Can't parse time %s\n Please specify either 'YYYY-MM-DD-HH:MM:SS'\n or an absolute unix time in seconds\n",
2101                         argv[3]);
2102                 return -1;
2103         } else if (when > now.tv_sec) {
2104                 fprintf(stderr, "%s specifies a time in the future\n",
2105                         argv[3]);
2106                 return -1;
2107         }
2108
2109         rc = ptl_yaml_route(g_net_set ? libcfs_net2str(g_net) : NULL, argv[1],
2110                             -1, -1, enable, when, NLM_F_REPLACE, LNET_GENL_VERSION);
2111         if (rc <= 0) {
2112                 if (rc == -EOPNOTSUPP)
2113                         goto old_api;
2114                 return rc;
2115         }
2116 old_api:
2117         LIBCFS_IOC_INIT(data);
2118         data.ioc_nid = nid;
2119         data.ioc_flags = enable;
2120         /* Yeuch; 'cept I need a __u64 on 64 bit machines... */
2121         data.ioc_u64[0] = (__u64)when;
2122
2123         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_NOTIFY_ROUTER, &data);
2124         if (rc != 0) {
2125                 fprintf(stderr, "IOC_LIBCFS_NOTIFY_ROUTER (%s) failed: %s\n",
2126                         libcfs_nid2str(nid), strerror(errno));
2127                 return -1;
2128         }
2129
2130         return 0;
2131 }
2132
2133 int
2134 jt_ptl_print_routes(int argc, char **argv)
2135 {
2136         struct lnet_ioctl_config_data  data;
2137         int rc;
2138         int index;
2139         __u32 net;
2140         lnet_nid_t nid;
2141         int hops;
2142         int alive;
2143         unsigned int pri;
2144
2145         rc = ptl_yaml_route(NULL, NULL, -1, -1, false, 0, NLM_F_DUMP,
2146                             LNET_GENL_VERSION);
2147         if (rc <= 0) {
2148                 if (rc == -EOPNOTSUPP)
2149                         goto old_api;
2150                 return rc;
2151         }
2152 old_api:
2153         for (index = 0; ; index++) {
2154                 LIBCFS_IOC_INIT_V2(data, cfg_hdr);
2155                 data.cfg_count = index;
2156
2157                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_ROUTE, &data);
2158                 if (rc != 0)
2159                         break;
2160
2161                 net     = data.cfg_net;
2162                 hops    = data.cfg_config_u.cfg_route.rtr_hop;
2163                 nid     = data.cfg_nid;
2164                 alive   = data.cfg_config_u.cfg_route.rtr_flags & LNET_RT_ALIVE;
2165                 pri     = data.cfg_config_u.cfg_route.rtr_priority;
2166
2167                 printf("net %18s hops %d gw %32s %s pri %u\n",
2168                        libcfs_net2str(net), hops,
2169                        libcfs_nid2str(nid), alive ? "up" : "down", pri);
2170         }
2171
2172         if (errno != ENOENT)
2173                 fprintf(stderr, "Error getting routes: %s: check dmesg.\n",
2174                         strerror(errno));
2175
2176         return 0;
2177 }
2178
2179 static int
2180 fault_attr_nid_parse(char *str, lnet_nid_t *nid_p)
2181 {
2182         lnet_nid_t nid;
2183         __u32 net;
2184         int rc = 0;
2185
2186         /* NB: can't support range ipaddress except * and *@net */
2187         if (strlen(str) > 2 && str[0] == '*' && str[1] == '@') {
2188                 net = libcfs_str2net(str + 2);
2189                 if (net == LNET_NET_ANY)
2190                         goto failed;
2191
2192                 nid = LNET_MKNID(net, LNET_NIDADDR(LNET_NID_ANY));
2193         } else {
2194                 rc = libcfs_str2anynid(&nid, str);
2195                 if (!rc)
2196                         goto failed;
2197         }
2198
2199         *nid_p = nid;
2200         return 0;
2201 failed:
2202         fprintf(stderr, "Invalid NID : %s\n", str);
2203         return -1;
2204 }
2205
2206 static int
2207 fault_attr_msg_parse(char *msg_str, __u32 *mask_p)
2208 {
2209         if (!strcasecmp(msg_str, "put")) {
2210                 *mask_p |= LNET_PUT_BIT;
2211                 return 0;
2212
2213         } else if (!strcasecmp(msg_str, "ack")) {
2214                 *mask_p |= LNET_ACK_BIT;
2215                 return 0;
2216
2217         } else if (!strcasecmp(msg_str, "get")) {
2218                 *mask_p |= LNET_GET_BIT;
2219                 return 0;
2220
2221         } else if (!strcasecmp(msg_str, "reply")) {
2222                 *mask_p |= LNET_REPLY_BIT;
2223                 return 0;
2224         }
2225
2226         fprintf(stderr, "unknown message type %s\n", msg_str);
2227         return -1;
2228 }
2229
2230 static int
2231 fault_attr_ptl_parse(char *ptl_str, __u64 *mask_p)
2232 {
2233         unsigned long rc = strtoul(optarg, NULL, 0);
2234
2235         if (rc >= 64) {
2236                 fprintf(stderr, "invalid portal: %lu\n", rc);
2237                 return -1;
2238         }
2239
2240         *mask_p |= (1ULL << rc);
2241         return 0;
2242 }
2243
2244 static int
2245 fault_attr_health_error_parse(char *error, __u32 *mask)
2246 {
2247         if (!strcasecmp(error, "local_interrupt")) {
2248                 *mask |= HSTATUS_LOCAL_INTERRUPT_BIT;
2249                 return 0;
2250         }
2251         if (!strcasecmp(error, "local_dropped")) {
2252                 *mask |= HSTATUS_LOCAL_DROPPED_BIT;
2253                 return 0;
2254         }
2255         if (!strcasecmp(error, "local_aborted")) {
2256                 *mask |= HSTATUS_LOCAL_ABORTED_BIT;
2257                 return 0;
2258         }
2259         if (!strcasecmp(error, "local_no_route")) {
2260                 *mask |= HSTATUS_LOCAL_NO_ROUTE_BIT;
2261                 return 0;
2262         }
2263         if (!strcasecmp(error, "local_error")) {
2264                 *mask |= HSTATUS_LOCAL_ERROR_BIT;
2265                 return 0;
2266         }
2267         if (!strcasecmp(error, "local_timeout")) {
2268                 *mask |= HSTATUS_LOCAL_TIMEOUT_BIT;
2269                 return 0;
2270         }
2271         if (!strcasecmp(error, "remote_error")) {
2272                 *mask |= HSTATUS_REMOTE_ERROR_BIT;
2273                 return 0;
2274         }
2275         if (!strcasecmp(error, "remote_dropped")) {
2276                 *mask |= HSTATUS_REMOTE_DROPPED_BIT;
2277                 return 0;
2278         }
2279         if (!strcasecmp(error, "remote_timeout")) {
2280                 *mask |= HSTATUS_REMOTE_TIMEOUT_BIT;
2281                 return 0;
2282         }
2283         if (!strcasecmp(error, "network_timeout")) {
2284                 *mask |= HSTATUS_NETWORK_TIMEOUT_BIT;
2285                 return 0;
2286         }
2287         if (!strcasecmp(error, "random")) {
2288                 *mask = HSTATUS_RANDOM;
2289                 return 0;
2290         }
2291
2292         return -1;
2293 }
2294
2295 static int
2296 fault_simul_rule_add(__u32 opc, char *name, int argc, char **argv)
2297 {
2298         struct libcfs_ioctl_data  data = { { 0 } };
2299         struct lnet_fault_attr    attr;
2300         char *optstr;
2301         int rc;
2302
2303         static const struct option opts[] = {
2304         { .name = "source",   .has_arg = required_argument, .val = 's' },
2305         { .name = "dest",     .has_arg = required_argument, .val = 'd' },
2306         { .name = "rate",     .has_arg = required_argument, .val = 'r' },
2307         { .name = "interval", .has_arg = required_argument, .val = 'i' },
2308         { .name = "random",   .has_arg = no_argument,       .val = 'n' },
2309         { .name = "latency",  .has_arg = required_argument, .val = 'l' },
2310         { .name = "portal",   .has_arg = required_argument, .val = 'p' },
2311         { .name = "message",  .has_arg = required_argument, .val = 'm' },
2312         { .name = "health_error",  .has_arg = required_argument, .val = 'e' },
2313         { .name = "local_nid",  .has_arg = required_argument, .val = 'o' },
2314         { .name = "drop_all",  .has_arg = no_argument, .val = 'x' },
2315         { .name = NULL } };
2316
2317         if (argc == 1) {
2318                 fprintf(stderr,
2319                         "Failed, please provide source, destination and rate of rule\n");
2320                 return -1;
2321         }
2322
2323         optstr = opc == LNET_CTL_DROP_ADD ? "s:d:o:r:i:p:m:e:nx" : "s:d:o:r:l:p:m:";
2324         memset(&attr, 0, sizeof(attr));
2325         while (1) {
2326                 int c = getopt_long(argc, argv, optstr, opts, NULL);
2327
2328                 if (c == -1)
2329                         break;
2330
2331                 switch (c) {
2332                 case 'o':
2333                         rc = fault_attr_nid_parse(optarg, &attr.fa_local_nid);
2334                         if (rc != 0)
2335                                 goto getopt_failed;
2336                         break;
2337                 case 's': /* source NID/NET */
2338                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
2339                         if (rc != 0)
2340                                 goto getopt_failed;
2341                         break;
2342
2343                 case 'd': /* dest NID/NET */
2344                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
2345                         if (rc != 0)
2346                                 goto getopt_failed;
2347                         break;
2348
2349                 case 'r': /* drop rate */
2350                         if (opc == LNET_CTL_DROP_ADD)
2351                                 attr.u.drop.da_rate = strtoul(optarg, NULL, 0);
2352                         else
2353                                 attr.u.delay.la_rate = strtoul(optarg, NULL, 0);
2354                         break;
2355
2356                 case 'e':
2357                         if (opc == LNET_CTL_DROP_ADD) {
2358                                 rc = fault_attr_health_error_parse(optarg,
2359                                                                    &attr.u.drop.da_health_error_mask);
2360                                 if (rc)
2361                                         goto getopt_failed;
2362                         }
2363                         break;
2364
2365                 case 'x':
2366                         if (opc == LNET_CTL_DROP_ADD)
2367                                 attr.u.drop.da_drop_all = true;
2368                         break;
2369
2370                 case 'n':
2371                         if (opc == LNET_CTL_DROP_ADD)
2372                                 attr.u.drop.da_random = true;
2373                         break;
2374
2375                 case 'i': /* time interval (# seconds) for message drop */
2376                         if (opc == LNET_CTL_DROP_ADD)
2377                                 attr.u.drop.da_interval = strtoul(optarg,
2378                                                                   NULL, 0);
2379                         else
2380                                 attr.u.delay.la_interval = strtoul(optarg,
2381                                                                    NULL, 0);
2382                         break;
2383
2384                 case 'l': /* seconds to wait before activating rule */
2385                         attr.u.delay.la_latency = strtoul(optarg, NULL, 0);
2386                         break;
2387
2388                 case 'p': /* portal to filter */
2389                         rc = fault_attr_ptl_parse(optarg, &attr.fa_ptl_mask);
2390                         if (rc != 0)
2391                                 goto getopt_failed;
2392                         break;
2393
2394                 case 'm': /* message types to filter */
2395                         rc = fault_attr_msg_parse(optarg, &attr.fa_msg_mask);
2396                         if (rc != 0)
2397                                 goto getopt_failed;
2398                         break;
2399
2400                 default:
2401                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
2402                                 argv[0], argv[optind - 1]);
2403                         goto getopt_failed;
2404                 }
2405         }
2406         optind = 1;
2407
2408         if (opc == LNET_CTL_DROP_ADD) {
2409                 /* NB: drop rate and interval are exclusive to each other */
2410                 if (!((attr.u.drop.da_rate == 0) ^
2411                       (attr.u.drop.da_interval == 0))) {
2412                         fprintf(stderr,
2413                                 "please provide either drop rate or interval but not both at the same time.\n");
2414                         return -1;
2415                 }
2416
2417                 if (attr.u.drop.da_random &&
2418                     attr.u.drop.da_interval == 0) {
2419                         fprintf(stderr,
2420                                 "please provide an interval to randomize\n");
2421                         return -1;
2422                 }
2423         } else if (opc == LNET_CTL_DELAY_ADD) {
2424                 if (!((attr.u.delay.la_rate == 0) ^
2425                       (attr.u.delay.la_interval == 0))) {
2426                         fprintf(stderr,
2427                                 "please provide either delay rate or interval but not both at the same time.\n");
2428                         return -1;
2429                 }
2430
2431                 if (attr.u.delay.la_latency == 0) {
2432                         fprintf(stderr, "latency cannot be zero\n");
2433                         return -1;
2434                 }
2435         }
2436
2437         if (attr.fa_src == 0 || attr.fa_dst == 0) {
2438                 fprintf(stderr,
2439                         "Please provide both source and destination of %s rule\n",
2440                         name);
2441                 return -1;
2442         }
2443
2444         if (attr.fa_local_nid == 0)
2445                 attr.fa_local_nid = LNET_NID_ANY;
2446
2447         data.ioc_flags = opc;
2448         data.ioc_inllen1 = sizeof(attr);
2449         data.ioc_inlbuf1 = (char *)&attr;
2450         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2451                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
2452                 return -1;
2453         }
2454
2455         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2456         if (rc != 0) {
2457                 fprintf(stderr, "add %s rule %s->%s failed: %s\n",
2458                         name, libcfs_nid2str(attr.fa_src),
2459                         libcfs_nid2str(attr.fa_dst), strerror(errno));
2460                 return -1;
2461         }
2462
2463         printf("Added %s rule %s->%s (1/%d)\n",
2464                name, libcfs_nid2str(attr.fa_src), libcfs_nid2str(attr.fa_dst),
2465                opc == LNET_CTL_DROP_ADD ?
2466                attr.u.drop.da_rate : attr.u.delay.la_rate);
2467         return 0;
2468
2469 getopt_failed:
2470         optind = 1;
2471         return -1;
2472 }
2473
2474 int
2475 jt_ptl_drop_add(int argc, char **argv)
2476 {
2477         return fault_simul_rule_add(LNET_CTL_DROP_ADD, "drop", argc, argv);
2478 }
2479
2480 int
2481 jt_ptl_delay_add(int argc, char **argv)
2482 {
2483         return fault_simul_rule_add(LNET_CTL_DELAY_ADD, "delay", argc, argv);
2484 }
2485
2486 static int
2487 fault_simul_rule_del(__u32 opc, char *name, int argc, char **argv)
2488 {
2489         struct libcfs_ioctl_data data = { { 0 } };
2490         struct lnet_fault_attr   attr;
2491         bool all = false;
2492         int rc;
2493
2494         static const struct option opts[] = {
2495                 { .name = "source", .has_arg = required_argument, .val = 's' },
2496                 { .name = "dest",   .has_arg = required_argument, .val = 'd' },
2497                 { .name = "all",    .has_arg = no_argument,       .val = 'a' },
2498                 { .name = NULL } };
2499
2500         if (argc == 1) {
2501                 fprintf(stderr,
2502                         "Failed, please provide source and destination of rule\n");
2503                 return -1;
2504         }
2505
2506         memset(&attr, 0, sizeof(attr));
2507         while (1) {
2508                 int c = getopt_long(argc, argv, "s:d:a", opts, NULL);
2509
2510                 if (c == -1 || all)
2511                         break;
2512
2513                 switch (c) {
2514                 case 's':
2515                         rc = fault_attr_nid_parse(optarg, &attr.fa_src);
2516                         if (rc != 0)
2517                                 goto getopt_failed;
2518                         break;
2519                 case 'd':
2520                         rc = fault_attr_nid_parse(optarg, &attr.fa_dst);
2521                         if (rc != 0)
2522                                 goto getopt_failed;
2523                         break;
2524                 case 'a':
2525                         attr.fa_src = 0;
2526                         attr.fa_dst = 0;
2527                         all = true;
2528
2529                         break;
2530                 default:
2531                         fprintf(stderr, "error: %s: option '%s' unrecognized\n",
2532                                 argv[0], argv[optind - 1]);
2533                         goto getopt_failed;
2534                 }
2535         }
2536         optind = 1;
2537
2538         data.ioc_flags = opc;
2539         data.ioc_inllen1 = sizeof(attr);
2540         data.ioc_inlbuf1 = (char *)&attr;
2541         if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2542                 fprintf(stderr, "libcfs_ioctl_pack failed\n");
2543                 return -1;
2544         }
2545
2546         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2547         if (rc != 0) {
2548                 fprintf(stderr, "remove %s rule %s->%s failed: %s\n", name,
2549                         all ? "all" : libcfs_nid2str(attr.fa_src),
2550                         all ? "all" : libcfs_nid2str(attr.fa_dst),
2551                         strerror(errno));
2552                 return -1;
2553         }
2554
2555         libcfs_ioctl_unpack(&data, ioc_buf);
2556         printf("Removed %d %s rules\n", data.ioc_count, name);
2557         return 0;
2558
2559 getopt_failed:
2560         optind = 1;
2561         return -1;
2562 }
2563
2564 int
2565 jt_ptl_drop_del(int argc, char **argv)
2566 {
2567         return fault_simul_rule_del(LNET_CTL_DROP_DEL, "drop", argc, argv);
2568 }
2569
2570 int
2571 jt_ptl_delay_del(int argc, char **argv)
2572 {
2573         return fault_simul_rule_del(LNET_CTL_DELAY_DEL, "delay", argc, argv);
2574 }
2575
2576 static int
2577 fault_simul_rule_reset(__u32 opc, char *name, int argc, char **argv)
2578 {
2579         struct libcfs_ioctl_data   data = { { 0 } };
2580         int                        rc;
2581
2582         LIBCFS_IOC_INIT(data);
2583         data.ioc_flags = opc;
2584
2585         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, &data);
2586         if (rc != 0) {
2587                 fprintf(stderr, "failed to reset %s stats: %s\n",
2588                         name, strerror(errno));
2589                 return -1;
2590         }
2591         return 0;
2592 }
2593
2594 int
2595 jt_ptl_drop_reset(int argc, char **argv)
2596 {
2597         return fault_simul_rule_reset(LNET_CTL_DROP_RESET, "drop", argc, argv);
2598 }
2599
2600 int
2601 jt_ptl_delay_reset(int argc, char **argv)
2602 {
2603         return fault_simul_rule_reset(LNET_CTL_DELAY_RESET, "delay",
2604                                       argc, argv);
2605 }
2606
2607 static int
2608 fault_simul_rule_list(__u32 opc, char *name, int argc, char **argv)
2609 {
2610         struct libcfs_ioctl_data data = { { 0 } };
2611         struct lnet_fault_attr   attr;
2612         struct lnet_fault_stat   stat;
2613         int pos;
2614
2615         printf("LNet %s rules:\n", name);
2616         for (pos = 0;; pos++) {
2617                 int rc;
2618
2619                 memset(&attr, 0, sizeof(attr));
2620                 memset(&stat, 0, sizeof(stat));
2621
2622                 data.ioc_count = pos;
2623                 data.ioc_flags = opc;
2624                 data.ioc_inllen1 = sizeof(attr);
2625                 data.ioc_inlbuf1 = (char *)&attr;
2626                 data.ioc_inllen2 = sizeof(stat);
2627                 data.ioc_inlbuf2 = (char *)&stat;
2628                 if (libcfs_ioctl_pack(&data, &ioc_buf, IOC_BUF_SIZE) != 0) {
2629                         fprintf(stderr, "libcfs_ioctl_pack failed\n");
2630                         return -1;
2631                 }
2632
2633                 rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_LNET_FAULT, ioc_buf);
2634                 if (rc != 0)
2635                         break;
2636
2637                 libcfs_ioctl_unpack(&data, ioc_buf);
2638
2639                 if (opc == LNET_CTL_DROP_LIST) {
2640                         printf("%s->%s (1/%d | %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
2641                                libcfs_nid2str(attr.fa_src),
2642                                libcfs_nid2str(attr.fa_dst),
2643                                attr.u.drop.da_rate, attr.u.drop.da_interval,
2644                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
2645                                (uintmax_t)stat.u.drop.ds_dropped,
2646                                (uintmax_t)stat.fs_count,
2647                                (uintmax_t)stat.fs_put,
2648                                (uintmax_t)stat.fs_ack,
2649                                (uintmax_t)stat.fs_get,
2650                                (uintmax_t)stat.fs_reply);
2651
2652                 } else if (opc == LNET_CTL_DELAY_LIST) {
2653                         printf("%s->%s (1/%d | %d, latency %d) ptl %#jx, msg %x, %ju/%ju, PUT %ju, ACK %ju, GET %ju, REP %ju\n",
2654                                libcfs_nid2str(attr.fa_src),
2655                                libcfs_nid2str(attr.fa_dst),
2656                                attr.u.delay.la_rate, attr.u.delay.la_interval,
2657                                attr.u.delay.la_latency,
2658                                (uintmax_t)attr.fa_ptl_mask, attr.fa_msg_mask,
2659                                (uintmax_t)stat.u.delay.ls_delayed,
2660                                (uintmax_t)stat.fs_count,
2661                                (uintmax_t)stat.fs_put,
2662                                (uintmax_t)stat.fs_ack,
2663                                (uintmax_t)stat.fs_get,
2664                                (uintmax_t)stat.fs_reply);
2665                 }
2666         }
2667         printf("found total %d\n", pos);
2668
2669         return 0;
2670 }
2671
2672 int
2673 jt_ptl_drop_list(int argc, char **argv)
2674 {
2675         return fault_simul_rule_list(LNET_CTL_DROP_LIST, "drop", argc, argv);
2676 }
2677
2678 int
2679 jt_ptl_delay_list(int argc, char **argv)
2680 {
2681         return fault_simul_rule_list(LNET_CTL_DELAY_LIST, "delay", argc, argv);
2682 }
2683
2684 double
2685 get_cycles_per_usec()
2686 {
2687         FILE *f = fopen("/proc/cpuinfo", "r");
2688         double mhz;
2689         char line[64];
2690
2691         if (f) {
2692                 while (fgets(line, sizeof(line), f))
2693                         if (sscanf(line, "cpu MHz : %lf", &mhz) == 1) {
2694                                 fclose(f);
2695                                 return mhz;
2696                         }
2697                 fclose(f);
2698         }
2699
2700         fprintf(stderr, "Can't read/parse /proc/cpuinfo\n");
2701         return 1000.0;
2702 }
2703
2704 int jt_ptl_testprotocompat(int argc, char **argv)
2705 {
2706         struct libcfs_ioctl_data  data;
2707         int rc;
2708         int flags;
2709         char *end;
2710
2711         if (argc < 2)  {
2712                 fprintf(stderr, "usage: %s <number>\n", argv[0]);
2713                 return 0;
2714         }
2715
2716         flags = strtol(argv[1], &end, 0);
2717         if (flags < 0 || *end != 0) {
2718                 fprintf(stderr, "Can't parse flags '%s'\n", argv[1]);
2719                 return -1;
2720         }
2721
2722         LIBCFS_IOC_INIT(data);
2723         data.ioc_flags = flags;
2724         rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_TESTPROTOCOMPAT, &data);
2725
2726         if (rc != 0) {
2727                 fprintf(stderr, "test proto compat %x failed: %s\n",
2728                         flags, strerror(errno));
2729                 return -1;
2730         }
2731
2732         printf("test proto compat %x OK\n", flags);
2733         return 0;
2734 }