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