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