Whamcloud - gitweb
LU-11894 lnet: check for asymmetrical route messages
[fs/lustre-release.git] / lnet / utils / lnetctl.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of the
9  * License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * LGPL HEADER END
20  *
21  * Copyright (c) 2014, 2017, Intel Corporation.
22  *
23  * Author:
24  *   Amir Shehata <amir.shehata@intel.com>
25  */
26 #include <getopt.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <libcfs/util/ioctl.h>
32 #include <libcfs/util/parser.h>
33 #include <cyaml.h>
34 #include "lnetconfig/liblnetconfig.h"
35
36 #define LNET_CONFIGURE          true
37 #define LNET_UNCONFIGURE        false
38
39 static int jt_config_lnet(int argc, char **argv);
40 static int jt_unconfig_lnet(int argc, char **argv);
41 static int jt_add_route(int argc, char **argv);
42 static int jt_add_ni(int argc, char **argv);
43 static int jt_set_routing(int argc, char **argv);
44 static int jt_del_route(int argc, char **argv);
45 static int jt_del_ni(int argc, char **argv);
46 static int jt_show_route(int argc, char **argv);
47 static int jt_show_net(int argc, char **argv);
48 static int jt_show_routing(int argc, char **argv);
49 static int jt_show_stats(int argc, char **argv);
50 static int jt_show_peer(int argc, char **argv);
51 static int jt_show_recovery(int argc, char **argv);
52 static int jt_show_global(int argc, char **argv);
53 static int jt_set_tiny(int argc, char **argv);
54 static int jt_set_small(int argc, char **argv);
55 static int jt_set_large(int argc, char **argv);
56 static int jt_set_numa(int argc, char **argv);
57 static int jt_set_retry_count(int argc, char **argv);
58 static int jt_set_transaction_to(int argc, char **argv);
59 static int jt_set_recov_intrv(int argc, char **argv);
60 static int jt_set_hsensitivity(int argc, char **argv);
61 static int jt_add_peer_nid(int argc, char **argv);
62 static int jt_del_peer_nid(int argc, char **argv);
63 static int jt_set_max_intf(int argc, char **argv);
64 static int jt_set_discovery(int argc, char **argv);
65 static int jt_set_drop_asym_route(int argc, char **argv);
66 static int jt_list_peer(int argc, char **argv);
67 /*static int jt_show_peer(int argc, char **argv);*/
68 static int lnetctl_list_commands(int argc, char **argv);
69 static int jt_import(int argc, char **argv);
70 static int jt_export(int argc, char **argv);
71 static int jt_ping(int argc, char **argv);
72 static int jt_discover(int argc, char **argv);
73 static int jt_lnet(int argc, char **argv);
74 static int jt_route(int argc, char **argv);
75 static int jt_net(int argc, char **argv);
76 static int jt_routing(int argc, char **argv);
77 static int jt_set(int argc, char **argv);
78 static int jt_debug(int argc, char **argv);
79 static int jt_stats(int argc, char **argv);
80 static int jt_global(int argc, char **argv);
81 static int jt_peers(int argc, char **argv);
82 static int jt_set_ni_value(int argc, char **argv);
83 static int jt_set_peer_ni_value(int argc, char **argv);
84
85 command_t cmd_list[] = {
86         {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
87         {"route", jt_route, 0, "route {add | del | show | help}"},
88         {"net", jt_net, 0, "net {add | del | show | help}"},
89         {"routing", jt_routing, 0, "routing {show | help}"},
90         {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
91                            " | routing | numa_range | max_interfaces"
92                            " | discovery}"},
93         {"import", jt_import, 0, "import FILE.yaml"},
94         {"export", jt_export, 0, "export FILE.yaml"},
95         {"stats", jt_stats, 0, "stats {show | help}"},
96         {"debug", jt_debug, 0, "debug recovery {local | peer}"},
97         {"global", jt_global, 0, "global {show | help}"},
98         {"peer", jt_peers, 0, "peer {add | del | show | help}"},
99         {"ping", jt_ping, 0, "ping nid,[nid,...]"},
100         {"discover", jt_discover, 0, "discover nid[,nid,...]"},
101         {"help", Parser_help, 0, "help"},
102         {"exit", Parser_quit, 0, "quit"},
103         {"quit", Parser_quit, 0, "quit"},
104         {"--list-commands", lnetctl_list_commands, 0, "list commands"},
105         { 0, 0, 0, NULL }
106 };
107
108 command_t lnet_cmds[] = {
109         {"configure", jt_config_lnet, 0, "configure lnet\n"
110          "\t--all: load NI configuration from module parameters\n"},
111         {"unconfigure", jt_unconfig_lnet, 0, "unconfigure lnet\n"},
112         { 0, 0, 0, NULL }
113 };
114
115 command_t route_cmds[] = {
116         {"add", jt_add_route, 0, "add a route\n"
117          "\t--net: net name (e.g. tcp0)\n"
118          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
119          "\t--hop: number to final destination (1 < hops < 255)\n"
120          "\t--priority: priority of route (0 - highest prio\n"},
121         {"del", jt_del_route, 0, "delete a route\n"
122          "\t--net: net name (e.g. tcp0)\n"
123          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"},
124         {"show", jt_show_route, 0, "show routes\n"
125          "\t--net: net name (e.g. tcp0) to filter on\n"
126          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
127          "\t--hop: number to final destination (1 < hops < 255) to filter on\n"
128          "\t--priority: priority of route (0 - highest prio to filter on\n"
129          "\t--verbose: display detailed output per route\n"},
130         { 0, 0, 0, NULL }
131 };
132
133 command_t net_cmds[] = {
134         {"add", jt_add_ni, 0, "add a network\n"
135          "\t--net: net name (e.g. tcp0)\n"
136          "\t--if: physical interface (e.g. eth0)\n"
137          "\t--ip2net: specify networks based on IP address patterns\n"
138          "\t--peer-timeout: time to wait before declaring a peer dead\n"
139          "\t--peer-credits: define the max number of inflight messages\n"
140          "\t--peer-buffer-credits: the number of buffer credits per peer\n"
141          "\t--credits: Network Interface credits\n"
142          "\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"},
143         {"del", jt_del_ni, 0, "delete a network\n"
144          "\t--net: net name (e.g. tcp0)\n"
145          "\t--if: physical interface (e.g. eth0)\n"},
146         {"show", jt_show_net, 0, "show networks\n"
147          "\t--net: net name (e.g. tcp0) to filter on\n"
148          "\t--verbose: display detailed output per network."
149                        " Optional argument of '2' outputs more stats\n"},
150         {"set", jt_set_ni_value, 0, "set local NI specific parameter\n"
151          "\t--nid: NI NID to set the\n"
152          "\t--health: specify health value to set\n"
153          "\t--all: set all NIs value to the one specified\n"},
154         { 0, 0, 0, NULL }
155 };
156
157 command_t routing_cmds[] = {
158         {"show", jt_show_routing, 0, "show routing information\n"},
159         { 0, 0, 0, NULL }
160 };
161
162 command_t stats_cmds[] = {
163         {"show", jt_show_stats, 0, "show LNET statistics\n"},
164         { 0, 0, 0, NULL }
165 };
166
167 command_t debug_cmds[] = {
168         {"recovery", jt_show_recovery, 0, "list recovery queues\n"
169                 "\t--local : list local recovery queue\n"
170                 "\t--peer : list peer recovery queue\n"},
171         { 0, 0, 0, NULL }
172 };
173
174 command_t global_cmds[] = {
175         {"show", jt_show_global, 0, "show global variables\n"},
176         { 0, 0, 0, NULL }
177 };
178
179 command_t set_cmds[] = {
180         {"tiny_buffers", jt_set_tiny, 0, "set tiny routing buffers\n"
181          "\tVALUE must be greater than 0\n"},
182         {"small_buffers", jt_set_small, 0, "set small routing buffers\n"
183          "\tVALUE must be greater than 0\n"},
184         {"large_buffers", jt_set_large, 0, "set large routing buffers\n"
185          "\tVALUE must be greater than 0\n"},
186         {"routing", jt_set_routing, 0, "enable/disable routing\n"
187          "\t0 - disable routing\n"
188          "\t1 - enable routing\n"},
189         {"numa_range", jt_set_numa, 0, "set NUMA range for NI selection\n"
190          "\tVALUE must be at least 0\n"},
191         {"max_interfaces", jt_set_max_intf, 0, "set the default value for "
192                 "max interfaces\n"
193          "\tValue must be greater than 16\n"},
194         {"discovery", jt_set_discovery, 0, "enable/disable peer discovery\n"
195          "\t0 - disable peer discovery\n"
196          "\t1 - enable peer discovery (default)\n"},
197         {"drop_asym_route", jt_set_drop_asym_route, 0,
198          "drop/accept asymmetrical route messages\n"
199          "\t0 - accept asymmetrical route messages (default)\n"
200          "\t1 - drop asymmetrical route messages\n"},
201         {"retry_count", jt_set_retry_count, 0, "number of retries\n"
202          "\t0 - turn of retries\n"
203          "\t>0 - number of retries\n"},
204         {"transaction_timeout", jt_set_transaction_to, 0, "Message/Response timeout\n"
205          "\t>0 - timeout in seconds\n"},
206         {"health_sensitivity", jt_set_hsensitivity, 0, "sensitivity to failure\n"
207          "\t0 - turn off health evaluation\n"
208          "\t>0 - sensitivity value not more than 1000\n"},
209         {"recovery_interval", jt_set_recov_intrv, 0, "interval to ping in seconds (at least 1)\n"
210          "\t>0 - time in seconds between pings\n"},
211         { 0, 0, 0, NULL }
212 };
213
214 command_t peer_cmds[] = {
215         {"add", jt_add_peer_nid, 0, "add a peer NID\n"
216          "\t--prim_nid: Primary NID of the peer. If not provided then the first\n"
217          "\t            NID in the list becomes the Primary NID of a newly created\n"
218          "\t            peer. \n"
219          "\t--nid: one or more peer NIDs\n"
220          "\t--non_mr: create this peer as not Multi-Rail capable\n"
221          "\t--ip2nets: specify a range of nids per peer"},
222         {"del", jt_del_peer_nid, 0, "delete a peer NID\n"
223          "\t--prim_nid: Primary NID of the peer.\n"
224          "\t--nid: list of NIDs to remove. If none provided,\n"
225          "\t       peer is deleted\n"
226          "\t--ip2nets: specify a range of nids per peer"},
227         {"show", jt_show_peer, 0, "show peer information\n"
228          "\t--nid: NID of peer to filter on.\n"
229          "\t--verbose: display detailed output per peer."
230                        " Optional argument of '2' outputs more stats\n"},
231         {"list", jt_list_peer, 0, "list all peers\n"},
232         {"set", jt_set_peer_ni_value, 0, "set peer ni specific parameter\n"
233          "\t--nid: Peer NI NID to set the\n"
234          "\t--health: specify health value to set\n"
235          "\t--all: set all peer_nis values to the one specified\n"},
236         { 0, 0, 0, NULL }
237 };
238
239 static inline void print_help(const command_t cmds[], const char *cmd_type,
240                               const char *pc_name)
241 {
242         const command_t *cmd;
243
244         for (cmd = cmds; cmd->pc_name; cmd++) {
245                 if (pc_name != NULL &&
246                     strcmp(cmd->pc_name, pc_name) == 0) {
247                         printf("%s %s: %s\n", cmd_type, cmd->pc_name,
248                                cmd->pc_help);
249                         return;
250                 } else if (pc_name != NULL) {
251                         continue;
252                 }
253                 printf("%s %s: %s\n", cmd_type, cmd->pc_name, cmd->pc_help);
254         }
255 }
256
257 static int parse_long(const char *number, long int *value)
258 {
259         char *end;
260
261         if (!number)
262                 return -1;
263
264         *value = strtol(number,  &end, 0);
265         if (end != NULL && *end != 0)
266                 return -1;
267
268         return 0;
269 }
270
271 static int check_cmd(const command_t *cmd_list, const char *cmd,
272                      const char *sub_cmd, const int min_args,
273                      int argc, char **argv)
274 {
275         int opt;
276         int rc = 0;
277         optind = 0;
278         opterr = 0;
279
280         const char *const short_options = "h";
281         static const struct option long_options[] = {
282                 { .name = "help", .has_arg = no_argument, .val = 'h' },
283                 { .name = NULL }
284         };
285
286         if (argc < min_args) {
287                 print_help(cmd_list, cmd, sub_cmd);
288                 rc = -1;
289                 goto out;
290         } else if (argc > 2) {
291                 return 0;
292         }
293
294         while ((opt = getopt_long(argc, argv, short_options,
295                                   long_options, NULL)) != -1) {
296                 switch (opt) {
297                 case 'h':
298                         print_help(cmd_list, cmd, sub_cmd);
299                         rc = 1;
300                         break;
301                 default:
302                         rc = 0;
303                         break;
304                 }
305         }
306
307 out:
308         opterr = 1;
309         optind = 0;
310         return rc;
311 }
312
313 static int jt_set_max_intf(int argc, char **argv)
314 {
315         long int value;
316         int rc;
317         struct cYAML *err_rc = NULL;
318
319         rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
320         if (rc)
321                 return rc;
322
323         rc = parse_long(argv[1], &value);
324         if (rc != 0) {
325                 cYAML_build_error(-1, -1, "parser", "set",
326                                   "cannot parse max_interfaces value", &err_rc);
327                 cYAML_print_tree2file(stderr, err_rc);
328                 cYAML_free_tree(err_rc);
329                 return -1;
330         }
331
332         rc = lustre_lnet_config_max_intf(value, -1, &err_rc);
333         if (rc != LUSTRE_CFG_RC_NO_ERR)
334                 cYAML_print_tree2file(stderr, err_rc);
335
336         cYAML_free_tree(err_rc);
337
338         return rc;
339 }
340
341 static int jt_set_numa(int argc, char **argv)
342 {
343         long int value;
344         int rc;
345         struct cYAML *err_rc = NULL;
346
347         rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
348         if (rc)
349                 return rc;
350
351         rc = parse_long(argv[1], &value);
352         if (rc != 0) {
353                 cYAML_build_error(-1, -1, "parser", "set",
354                                   "cannot parse numa_range value", &err_rc);
355                 cYAML_print_tree2file(stderr, err_rc);
356                 cYAML_free_tree(err_rc);
357                 return -1;
358         }
359
360         rc = lustre_lnet_config_numa_range(value, -1, &err_rc);
361         if (rc != LUSTRE_CFG_RC_NO_ERR)
362                 cYAML_print_tree2file(stderr, err_rc);
363
364         cYAML_free_tree(err_rc);
365
366         return rc;
367 }
368
369 static int jt_set_recov_intrv(int argc, char **argv)
370 {
371         long int value;
372         int rc;
373         struct cYAML *err_rc = NULL;
374
375         rc = check_cmd(set_cmds, "set", "recovery_interval", 2, argc, argv);
376         if (rc)
377                 return rc;
378
379         rc = parse_long(argv[1], &value);
380         if (rc != 0) {
381                 cYAML_build_error(-1, -1, "parser", "set",
382                                   "cannot parse recovery interval value", &err_rc);
383                 cYAML_print_tree2file(stderr, err_rc);
384                 cYAML_free_tree(err_rc);
385                 return -1;
386         }
387
388         rc = lustre_lnet_config_recov_intrv(value, -1, &err_rc);
389         if (rc != LUSTRE_CFG_RC_NO_ERR)
390                 cYAML_print_tree2file(stderr, err_rc);
391
392         cYAML_free_tree(err_rc);
393
394         return rc;
395 }
396
397 static int jt_set_hsensitivity(int argc, char **argv)
398 {
399         long int value;
400         int rc;
401         struct cYAML *err_rc = NULL;
402
403         rc = check_cmd(set_cmds, "set", "health_sensitivity", 2, argc, argv);
404         if (rc)
405                 return rc;
406
407         rc = parse_long(argv[1], &value);
408         if (rc != 0) {
409                 cYAML_build_error(-1, -1, "parser", "set",
410                                   "cannot parse health sensitivity value", &err_rc);
411                 cYAML_print_tree2file(stderr, err_rc);
412                 cYAML_free_tree(err_rc);
413                 return -1;
414         }
415
416         rc = lustre_lnet_config_hsensitivity(value, -1, &err_rc);
417         if (rc != LUSTRE_CFG_RC_NO_ERR)
418                 cYAML_print_tree2file(stderr, err_rc);
419
420         cYAML_free_tree(err_rc);
421
422         return rc;
423 }
424
425 static int jt_set_transaction_to(int argc, char **argv)
426 {
427         long int value;
428         int rc;
429         struct cYAML *err_rc = NULL;
430
431         rc = check_cmd(set_cmds, "set", "transaction_timeout", 2, argc, argv);
432         if (rc)
433                 return rc;
434
435         rc = parse_long(argv[1], &value);
436         if (rc != 0) {
437                 cYAML_build_error(-1, -1, "parser", "set",
438                                   "cannot parse transaction timeout value", &err_rc);
439                 cYAML_print_tree2file(stderr, err_rc);
440                 cYAML_free_tree(err_rc);
441                 return -1;
442         }
443
444         rc = lustre_lnet_config_transaction_to(value, -1, &err_rc);
445         if (rc != LUSTRE_CFG_RC_NO_ERR)
446                 cYAML_print_tree2file(stderr, err_rc);
447
448         cYAML_free_tree(err_rc);
449
450         return rc;
451 }
452
453 static int jt_set_retry_count(int argc, char **argv)
454 {
455         long int value;
456         int rc;
457         struct cYAML *err_rc = NULL;
458
459         rc = check_cmd(set_cmds, "set", "retry_count", 2, argc, argv);
460         if (rc)
461                 return rc;
462
463         rc = parse_long(argv[1], &value);
464         if (rc != 0) {
465                 cYAML_build_error(-1, -1, "parser", "set",
466                                   "cannot parse retry_count value", &err_rc);
467                 cYAML_print_tree2file(stderr, err_rc);
468                 cYAML_free_tree(err_rc);
469                 return -1;
470         }
471
472         rc = lustre_lnet_config_retry_count(value, -1, &err_rc);
473         if (rc != LUSTRE_CFG_RC_NO_ERR)
474                 cYAML_print_tree2file(stderr, err_rc);
475
476         cYAML_free_tree(err_rc);
477
478         return rc;
479 }
480
481 static int jt_set_discovery(int argc, char **argv)
482 {
483         long int value;
484         int rc;
485         struct cYAML *err_rc = NULL;
486
487         rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
488         if (rc)
489                 return rc;
490
491         rc = parse_long(argv[1], &value);
492         if (rc != 0) {
493                 cYAML_build_error(-1, -1, "parser", "set",
494                                   "cannot parse discovery value", &err_rc);
495                 cYAML_print_tree2file(stderr, err_rc);
496                 cYAML_free_tree(err_rc);
497                 return -1;
498         }
499
500         rc = lustre_lnet_config_discovery(value, -1, &err_rc);
501         if (rc != LUSTRE_CFG_RC_NO_ERR)
502                 cYAML_print_tree2file(stderr, err_rc);
503
504         cYAML_free_tree(err_rc);
505
506         return rc;
507 }
508
509 static int jt_set_drop_asym_route(int argc, char **argv)
510 {
511         long int value;
512         int rc;
513         struct cYAML *err_rc = NULL;
514
515         rc = check_cmd(set_cmds, "set", "drop_asym_route", 2, argc, argv);
516         if (rc)
517                 return rc;
518
519         rc = parse_long(argv[1], &value);
520         if (rc != 0) {
521                 cYAML_build_error(-1, -1, "parser", "set",
522                                   "cannot parse drop_asym_route value",
523                                   &err_rc);
524                 cYAML_print_tree2file(stderr, err_rc);
525                 cYAML_free_tree(err_rc);
526                 return -1;
527         }
528
529         rc = lustre_lnet_config_drop_asym_route(value, -1, &err_rc);
530         if (rc != LUSTRE_CFG_RC_NO_ERR)
531                 cYAML_print_tree2file(stderr, err_rc);
532
533         cYAML_free_tree(err_rc);
534
535         return rc;
536 }
537
538 static int jt_set_tiny(int argc, char **argv)
539 {
540         long int value;
541         int rc;
542         struct cYAML *err_rc = NULL;
543
544         rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
545         if (rc)
546                 return rc;
547
548         rc = parse_long(argv[1], &value);
549         if (rc != 0) {
550                 cYAML_build_error(-1, -1, "parser", "set",
551                                   "cannot parse tiny_buffers value", &err_rc);
552                 cYAML_print_tree2file(stderr, err_rc);
553                 cYAML_free_tree(err_rc);
554                 return -1;
555         }
556
557         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
558         if (rc != LUSTRE_CFG_RC_NO_ERR)
559                 cYAML_print_tree2file(stderr, err_rc);
560
561         cYAML_free_tree(err_rc);
562
563         return rc;
564 }
565
566 static int jt_set_small(int argc, char **argv)
567 {
568         long int value;
569         int rc;
570         struct cYAML *err_rc = NULL;
571
572         rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
573         if (rc)
574                 return rc;
575
576         rc = parse_long(argv[1], &value);
577         if (rc != 0) {
578                 cYAML_build_error(-1, -1, "parser", "set",
579                                   "cannot parse small_buffers value", &err_rc);
580                 cYAML_print_tree2file(stderr, err_rc);
581                 cYAML_free_tree(err_rc);
582                 return -1;
583         }
584
585         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
586         if (rc != LUSTRE_CFG_RC_NO_ERR)
587                 cYAML_print_tree2file(stderr, err_rc);
588
589         cYAML_free_tree(err_rc);
590
591         return rc;
592 }
593
594 static int jt_set_large(int argc, char **argv)
595 {
596         long int value;
597         int rc;
598         struct cYAML *err_rc = NULL;
599
600         rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
601         if (rc)
602                 return rc;
603
604         rc = parse_long(argv[1], &value);
605         if (rc != 0) {
606                 cYAML_build_error(-1, -1, "parser", "set",
607                                   "cannot parse large_buffers value", &err_rc);
608                 cYAML_print_tree2file(stderr, err_rc);
609                 cYAML_free_tree(err_rc);
610                 return -1;
611         }
612
613         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
614         if (rc != LUSTRE_CFG_RC_NO_ERR)
615                 cYAML_print_tree2file(stderr, err_rc);
616
617         cYAML_free_tree(err_rc);
618
619         return rc;
620 }
621
622 static int jt_set_routing(int argc, char **argv)
623 {
624         long int value;
625         struct cYAML *err_rc = NULL;
626         int rc;
627
628         rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
629         if (rc)
630                 return rc;
631
632         rc = parse_long(argv[1], &value);
633         if (rc != 0 || (value != 0 && value != 1)) {
634                 cYAML_build_error(-1, -1, "parser", "set",
635                                   "cannot parse routing value.\n"
636                                   "must be 0 for disable or 1 for enable",
637                                   &err_rc);
638                 cYAML_print_tree2file(stderr, err_rc);
639                 cYAML_free_tree(err_rc);
640                 return -1;
641         }
642
643         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
644
645         if (rc != LUSTRE_CFG_RC_NO_ERR)
646                 cYAML_print_tree2file(stderr, err_rc);
647
648         cYAML_free_tree(err_rc);
649
650         return rc;
651 }
652
653 static int jt_config_lnet(int argc, char **argv)
654 {
655         struct cYAML *err_rc = NULL;
656         bool load_mod_params = false;
657         int rc, opt;
658
659         const char *const short_options = "a";
660         static const struct option long_options[] = {
661                 { .name = "all",  .has_arg = no_argument, .val = 'a' },
662                 { .name = NULL }
663         };
664
665         rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
666         if (rc)
667                 return rc;
668
669         while ((opt = getopt_long(argc, argv, short_options,
670                                    long_options, NULL)) != -1) {
671                 switch (opt) {
672                 case 'a':
673                         load_mod_params = true;
674                         break;
675                 default:
676                         return 0;
677                 }
678         }
679
680         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
681                                           -1, &err_rc);
682
683         if (rc != LUSTRE_CFG_RC_NO_ERR)
684                 cYAML_print_tree2file(stderr, err_rc);
685
686         cYAML_free_tree(err_rc);
687
688         return rc;
689 }
690
691 static int jt_unconfig_lnet(int argc, char **argv)
692 {
693         struct cYAML *err_rc = NULL;
694         int rc;
695
696         rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
697         if (rc)
698                 return rc;
699
700         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
701
702         if (rc != LUSTRE_CFG_RC_NO_ERR)
703                 cYAML_print_tree2file(stderr, err_rc);
704
705         cYAML_free_tree(err_rc);
706
707         return rc;
708 }
709 static int jt_add_route(int argc, char **argv)
710 {
711         char *network = NULL, *gateway = NULL;
712         long int hop = -1, prio = -1;
713         struct cYAML *err_rc = NULL;
714         int rc, opt;
715
716         const char *const short_options = "n:g:c:p:";
717         static const struct option long_options[] = {
718         { .name = "net",       .has_arg = required_argument, .val = 'n' },
719         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
720         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
721         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
722         { .name = NULL } };
723
724         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
725         if (rc)
726                 return rc;
727
728         while ((opt = getopt_long(argc, argv, short_options,
729                                    long_options, NULL)) != -1) {
730                 switch (opt) {
731                 case 'n':
732                         network = optarg;
733                         break;
734                 case 'g':
735                         gateway = optarg;
736                         break;
737                 case 'c':
738                         rc = parse_long(optarg, &hop);
739                         if (rc != 0) {
740                                 /* ignore option */
741                                 hop = -1;
742                                 continue;
743                         }
744                         break;
745                 case 'p':
746                         rc = parse_long(optarg, &prio);
747                         if (rc != 0) {
748                                 /* ingore option */
749                                 prio = -1;
750                                 continue;
751                         }
752                         break;
753                 case '?':
754                         print_help(route_cmds, "route", "add");
755                 default:
756                         return 0;
757                 }
758         }
759
760         rc = lustre_lnet_config_route(network, gateway, hop, prio, -1, &err_rc);
761
762         if (rc != LUSTRE_CFG_RC_NO_ERR)
763                 cYAML_print_tree2file(stderr, err_rc);
764
765         cYAML_free_tree(err_rc);
766
767         return rc;
768 }
769
770 static int jt_add_ni(int argc, char **argv)
771 {
772         char *ip2net = NULL;
773         long int pto = -1, pc = -1, pbc = -1, cre = -1;
774         struct cYAML *err_rc = NULL;
775         int rc, opt, cpt_rc = -1;
776         struct lnet_dlc_network_descr nw_descr;
777         struct cfs_expr_list *global_cpts = NULL;
778         struct lnet_ioctl_config_lnd_tunables tunables;
779         bool found = false;
780
781         memset(&tunables, 0, sizeof(tunables));
782         lustre_lnet_init_nw_descr(&nw_descr);
783
784         const char *const short_options = "n:i:p:t:c:b:r:s:";
785         static const struct option long_options[] = {
786         { .name = "net",          .has_arg = required_argument, .val = 'n' },
787         { .name = "if",           .has_arg = required_argument, .val = 'i' },
788         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
789         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
790         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
791         { .name = "peer-buffer-credits",
792                                   .has_arg = required_argument, .val = 'b' },
793         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
794         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
795         { .name = NULL } };
796
797         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
798         if (rc)
799                 return rc;
800
801         while ((opt = getopt_long(argc, argv, short_options,
802                                    long_options, NULL)) != -1) {
803                 switch (opt) {
804                 case 'n':
805                         nw_descr.nw_id = libcfs_str2net(optarg);
806                         break;
807                 case 'i':
808                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
809                         if (rc != 0) {
810                                 cYAML_build_error(-1, -1, "ni", "add",
811                                                 "bad interface list",
812                                                 &err_rc);
813                                 goto failed;
814                         }
815                         break;
816                 case 'p':
817                         ip2net = optarg;
818                         break;
819                 case 't':
820                         rc = parse_long(optarg, &pto);
821                         if (rc != 0) {
822                                 /* ignore option */
823                                 pto = -1;
824                                 continue;
825                         }
826                         break;
827                 case 'c':
828                         rc = parse_long(optarg, &pc);
829                         if (rc != 0) {
830                                 /* ignore option */
831                                 pc = -1;
832                                 continue;
833                         }
834                         break;
835                 case 'b':
836                         rc = parse_long(optarg, &pbc);
837                         if (rc != 0) {
838                                 /* ignore option */
839                                 pbc = -1;
840                                 continue;
841                         }
842                         break;
843                 case 'r':
844                         rc = parse_long(optarg, &cre);
845                         if (rc != 0) {
846                                 /* ignore option */
847                                 cre = -1;
848                                 continue;
849                         }
850                         break;
851                 case 's':
852                         cpt_rc = cfs_expr_list_parse(optarg,
853                                                      strlen(optarg), 0,
854                                                      UINT_MAX, &global_cpts);
855                         break;
856                 case '?':
857                         print_help(net_cmds, "net", "add");
858                 default:
859                         return 0;
860                 }
861         }
862
863         if (pto > 0 || pc > 0 || pbc > 0 || cre > 0) {
864                 tunables.lt_cmn.lct_peer_timeout = pto;
865                 tunables.lt_cmn.lct_peer_tx_credits = pc;
866                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
867                 tunables.lt_cmn.lct_max_tx_credits = cre;
868                 found = true;
869         }
870
871         rc = lustre_lnet_config_ni(&nw_descr,
872                                    (cpt_rc == 0) ? global_cpts: NULL,
873                                    ip2net, (found) ? &tunables : NULL,
874                                    -1, &err_rc);
875
876         if (global_cpts != NULL)
877                 cfs_expr_list_free(global_cpts);
878
879 failed:
880         if (rc != LUSTRE_CFG_RC_NO_ERR)
881                 cYAML_print_tree2file(stderr, err_rc);
882
883         cYAML_free_tree(err_rc);
884
885         return rc;
886 }
887
888 static int jt_del_route(int argc, char **argv)
889 {
890         char *network = NULL, *gateway = NULL;
891         struct cYAML *err_rc = NULL;
892         int rc, opt;
893
894         const char *const short_options = "n:g:";
895         static const struct option long_options[] = {
896                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
897                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
898                 { .name = NULL } };
899
900         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
901         if (rc)
902                 return rc;
903
904         while ((opt = getopt_long(argc, argv, short_options,
905                                    long_options, NULL)) != -1) {
906                 switch (opt) {
907                 case 'n':
908                         network = optarg;
909                         break;
910                 case 'g':
911                         gateway = optarg;
912                         break;
913                 case '?':
914                         print_help(route_cmds, "route", "del");
915                 default:
916                         return 0;
917                 }
918         }
919
920         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
921
922         if (rc != LUSTRE_CFG_RC_NO_ERR)
923                 cYAML_print_tree2file(stderr, err_rc);
924
925         cYAML_free_tree(err_rc);
926
927         return rc;
928 }
929
930 static int jt_del_ni(int argc, char **argv)
931 {
932         struct cYAML *err_rc = NULL;
933         int rc, opt;
934         struct lnet_dlc_network_descr nw_descr;
935
936         lustre_lnet_init_nw_descr(&nw_descr);
937
938         const char *const short_options = "n:i:";
939         static const struct option long_options[] = {
940         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
941         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
942         { .name = NULL } };
943
944         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
945         if (rc)
946                 return rc;
947
948         while ((opt = getopt_long(argc, argv, short_options,
949                                    long_options, NULL)) != -1) {
950                 switch (opt) {
951                 case 'n':
952                         nw_descr.nw_id = libcfs_str2net(optarg);
953                         break;
954                 case 'i':
955                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
956                         if (rc != 0) {
957                                 cYAML_build_error(-1, -1, "ni", "add",
958                                                 "bad interface list",
959                                                 &err_rc);
960                                 goto out;
961                         }
962                         break;
963                 case '?':
964                         print_help(net_cmds, "net", "del");
965                 default:
966                         return 0;
967                 }
968         }
969
970         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
971
972 out:
973         if (rc != LUSTRE_CFG_RC_NO_ERR)
974                 cYAML_print_tree2file(stderr, err_rc);
975
976         cYAML_free_tree(err_rc);
977
978         return rc;
979 }
980
981 static int jt_show_route(int argc, char **argv)
982 {
983         char *network = NULL, *gateway = NULL;
984         long int hop = -1, prio = -1;
985         int detail = 0, rc, opt;
986         struct cYAML *err_rc = NULL, *show_rc = NULL;
987
988         const char *const short_options = "n:g:h:p:v";
989         static const struct option long_options[] = {
990         { .name = "net",       .has_arg = required_argument, .val = 'n' },
991         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
992         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
993         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
994         { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
995         { .name = NULL } };
996
997         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
998         if (rc)
999                 return rc;
1000
1001         while ((opt = getopt_long(argc, argv, short_options,
1002                                    long_options, NULL)) != -1) {
1003                 switch (opt) {
1004                 case 'n':
1005                         network = optarg;
1006                         break;
1007                 case 'g':
1008                         gateway = optarg;
1009                         break;
1010                 case 'c':
1011                         rc = parse_long(optarg, &hop);
1012                         if (rc != 0) {
1013                                 /* ignore option */
1014                                 hop = -1;
1015                                 continue;
1016                         }
1017                         break;
1018                 case 'p':
1019                         rc = parse_long(optarg, &prio);
1020                         if (rc != 0) {
1021                                 /* ignore option */
1022                                 prio = -1;
1023                                 continue;
1024                         }
1025                         break;
1026                 case 'v':
1027                         detail = 1;
1028                         break;
1029                 case '?':
1030                         print_help(route_cmds, "route", "show");
1031                 default:
1032                         return 0;
1033                 }
1034         }
1035
1036         rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
1037                                     &show_rc, &err_rc, false);
1038
1039         if (rc != LUSTRE_CFG_RC_NO_ERR)
1040                 cYAML_print_tree2file(stderr, err_rc);
1041         else if (show_rc)
1042                 cYAML_print_tree(show_rc);
1043
1044         cYAML_free_tree(err_rc);
1045         cYAML_free_tree(show_rc);
1046
1047         return rc;
1048 }
1049
1050 static int set_value_helper(int argc, char **argv,
1051                             int (*cb)(int, bool, char*, int, struct cYAML**))
1052 {
1053         char *nid = NULL;
1054         long int healthv = -1;
1055         bool all = false;
1056         int rc, opt;
1057         struct cYAML *err_rc = NULL;
1058
1059         const char *const short_options = "t:n:a";
1060         static const struct option long_options[] = {
1061                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
1062                 { .name = "health", .has_arg = required_argument, .val = 't' },
1063                 { .name = "all", .has_arg = no_argument, .val = 'a' },
1064                 { .name = NULL } };
1065
1066         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
1067         if (rc)
1068                 return rc;
1069
1070         while ((opt = getopt_long(argc, argv, short_options,
1071                                    long_options, NULL)) != -1) {
1072                 switch (opt) {
1073                 case 'n':
1074                         nid = optarg;
1075                         break;
1076                 case 't':
1077                         if (parse_long(optarg, &healthv) != 0)
1078                                 healthv = -1;
1079                         break;
1080                 case 'a':
1081                         all = true;
1082                         break;
1083                 default:
1084                         return 0;
1085                 }
1086         }
1087
1088         rc = cb(healthv, all, nid, -1, &err_rc);
1089
1090         if (rc != LUSTRE_CFG_RC_NO_ERR)
1091                 cYAML_print_tree2file(stderr, err_rc);
1092
1093         cYAML_free_tree(err_rc);
1094
1095         return rc;
1096 }
1097
1098 static int jt_set_ni_value(int argc, char **argv)
1099 {
1100         return set_value_helper(argc, argv, lustre_lnet_config_ni_healthv);
1101 }
1102
1103 static int jt_set_peer_ni_value(int argc, char **argv)
1104 {
1105         return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
1106 }
1107
1108 static int jt_show_recovery(int argc, char **argv)
1109 {
1110         int rc, opt;
1111         struct cYAML *err_rc = NULL, *show_rc = NULL;
1112
1113         const char *const short_options = "lp";
1114         static const struct option long_options[] = {
1115                 { .name = "local", .has_arg = no_argument, .val = 'l' },
1116                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
1117                 { .name = NULL } };
1118
1119         rc = check_cmd(debug_cmds, "recovery", NULL, 0, argc, argv);
1120         if (rc)
1121                 return rc;
1122
1123         while ((opt = getopt_long(argc, argv, short_options,
1124                                    long_options, NULL)) != -1) {
1125                 switch (opt) {
1126                 case 'l':
1127                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
1128                         break;
1129                 case 'p':
1130                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
1131                         break;
1132                 default:
1133                         return 0;
1134                 }
1135         }
1136
1137         if (rc != LUSTRE_CFG_RC_NO_ERR)
1138                 cYAML_print_tree2file(stderr, err_rc);
1139         else if (show_rc)
1140                 cYAML_print_tree(show_rc);
1141
1142         cYAML_free_tree(err_rc);
1143         cYAML_free_tree(show_rc);
1144
1145         return rc;
1146 }
1147
1148 static int jt_show_net(int argc, char **argv)
1149 {
1150         char *network = NULL;
1151         int rc, opt;
1152         struct cYAML *err_rc = NULL, *show_rc = NULL;
1153         long int detail = 0;
1154
1155         const char *const short_options = "n:v";
1156         static const struct option long_options[] = {
1157                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
1158                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
1159                 { .name = NULL } };
1160
1161         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
1162         if (rc)
1163                 return rc;
1164
1165         while ((opt = getopt_long(argc, argv, short_options,
1166                                    long_options, NULL)) != -1) {
1167                 switch (opt) {
1168                 case 'n':
1169                         network = optarg;
1170                         break;
1171                 case 'v':
1172                         if ((!optarg) && (argv[optind] != NULL) &&
1173                             (argv[optind][0] != '-')) {
1174                                 if (parse_long(argv[optind++], &detail) != 0)
1175                                         detail = 1;
1176                         } else {
1177                                 detail = 1;
1178                         }
1179                         break;
1180                 case '?':
1181                         print_help(net_cmds, "net", "show");
1182                 default:
1183                         return 0;
1184                 }
1185         }
1186
1187         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
1188                                   false);
1189
1190         if (rc != LUSTRE_CFG_RC_NO_ERR)
1191                 cYAML_print_tree2file(stderr, err_rc);
1192         else if (show_rc)
1193                 cYAML_print_tree(show_rc);
1194
1195         cYAML_free_tree(err_rc);
1196         cYAML_free_tree(show_rc);
1197
1198         return rc;
1199 }
1200
1201 static int jt_show_routing(int argc, char **argv)
1202 {
1203         struct cYAML *err_rc = NULL, *show_rc = NULL;
1204         int rc;
1205
1206         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
1207         if (rc)
1208                 return rc;
1209
1210         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
1211
1212         if (rc != LUSTRE_CFG_RC_NO_ERR)
1213                 cYAML_print_tree2file(stderr, err_rc);
1214         else if (show_rc)
1215                 cYAML_print_tree(show_rc);
1216
1217         cYAML_free_tree(err_rc);
1218         cYAML_free_tree(show_rc);
1219
1220         return rc;
1221 }
1222
1223 static int jt_show_stats(int argc, char **argv)
1224 {
1225         int rc;
1226         struct cYAML *show_rc = NULL, *err_rc = NULL;
1227
1228         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
1229         if (rc)
1230                 return rc;
1231
1232         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
1233
1234         if (rc != LUSTRE_CFG_RC_NO_ERR)
1235                 cYAML_print_tree2file(stderr, err_rc);
1236         else if (show_rc)
1237                 cYAML_print_tree(show_rc);
1238
1239         cYAML_free_tree(err_rc);
1240         cYAML_free_tree(show_rc);
1241
1242         return rc;
1243 }
1244
1245 static int jt_show_global(int argc, char **argv)
1246 {
1247         int rc;
1248         struct cYAML *show_rc = NULL, *err_rc = NULL;
1249
1250         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
1251         if (rc)
1252                 return rc;
1253
1254         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
1255         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1256                 cYAML_print_tree2file(stderr, err_rc);
1257                 goto out;
1258         }
1259
1260         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
1261         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1262                 cYAML_print_tree2file(stderr, err_rc);
1263                 goto out;
1264         }
1265
1266         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
1267         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1268                 cYAML_print_tree2file(stderr, err_rc);
1269                 goto out;
1270         }
1271
1272         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
1273         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1274                 cYAML_print_tree2file(stderr, err_rc);
1275                 goto out;
1276         }
1277
1278         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
1279         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1280                 cYAML_print_tree2file(stderr, err_rc);
1281                 goto out;
1282         }
1283
1284         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
1285         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1286                 cYAML_print_tree2file(stderr, err_rc);
1287                 goto out;
1288         }
1289
1290         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
1291         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1292                 cYAML_print_tree2file(stderr, err_rc);
1293                 goto out;
1294         }
1295
1296         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
1297         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1298                 cYAML_print_tree2file(stderr, err_rc);
1299                 goto out;
1300         }
1301
1302         if (show_rc)
1303                 cYAML_print_tree(show_rc);
1304
1305 out:
1306         cYAML_free_tree(err_rc);
1307         cYAML_free_tree(show_rc);
1308
1309         return rc;
1310 }
1311
1312 static int jt_lnet(int argc, char **argv)
1313 {
1314         int rc;
1315
1316         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
1317         if (rc)
1318                 return rc;
1319
1320         return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
1321 }
1322
1323 static int jt_route(int argc, char **argv)
1324 {
1325         int rc;
1326
1327         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
1328         if (rc)
1329                 return rc;
1330
1331         return Parser_execarg(argc - 1, &argv[1], route_cmds);
1332 }
1333
1334 static int jt_net(int argc, char **argv)
1335 {
1336         int rc;
1337
1338         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
1339         if (rc)
1340                 return rc;
1341
1342         return Parser_execarg(argc - 1, &argv[1], net_cmds);
1343 }
1344
1345 static int jt_routing(int argc, char **argv)
1346 {
1347         int rc;
1348
1349         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
1350         if (rc)
1351                 return rc;
1352
1353         return Parser_execarg(argc - 1, &argv[1], routing_cmds);
1354 }
1355
1356 static int jt_stats(int argc, char **argv)
1357 {
1358         int rc;
1359
1360         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
1361         if (rc)
1362                 return rc;
1363
1364         return Parser_execarg(argc - 1, &argv[1], stats_cmds);
1365 }
1366
1367 static int jt_debug(int argc, char **argv)
1368 {
1369         int rc;
1370
1371         rc = check_cmd(debug_cmds, "recovery", NULL, 2, argc, argv);
1372         if (rc)
1373                 return rc;
1374
1375         return Parser_execarg(argc - 1, &argv[1], debug_cmds);
1376 }
1377
1378 static int jt_global(int argc, char **argv)
1379 {
1380         int rc;
1381
1382         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
1383         if (rc)
1384                 return rc;
1385
1386         return Parser_execarg(argc - 1, &argv[1], global_cmds);
1387 }
1388
1389 static int jt_peers(int argc, char **argv)
1390 {
1391         int rc;
1392
1393         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
1394         if (rc)
1395                 return rc;
1396
1397         return Parser_execarg(argc - 1, &argv[1], peer_cmds);
1398 }
1399
1400 static int jt_set(int argc, char **argv)
1401 {
1402         int rc;
1403
1404         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
1405         if (rc)
1406                 return rc;
1407
1408         return Parser_execarg(argc - 1, &argv[1], set_cmds);
1409 }
1410
1411 static int jt_import(int argc, char **argv)
1412 {
1413         char *file = NULL;
1414         struct cYAML *err_rc = NULL;
1415         struct cYAML *show_rc = NULL;
1416         int rc = 0, return_rc = 0, opt, opt_found = 0;
1417         char cmd = 'a';
1418
1419         const char *const short_options = "adseh";
1420         static const struct option long_options[] = {
1421                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
1422                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
1423                 { .name = "show", .has_arg = no_argument, .val = 's' },
1424                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
1425                 { .name = "help", .has_arg = no_argument, .val = 'h' },
1426                 { .name = NULL } };
1427
1428         while ((opt = getopt_long(argc, argv, short_options,
1429                                    long_options, NULL)) != -1) {
1430                 opt_found = 1;
1431                 switch (opt) {
1432                 case 'a':
1433                         cmd = opt;
1434                         break;
1435                 case 'd':
1436                 case 's':
1437                         cmd = opt;
1438                         break;
1439                 case 'e':
1440                         cmd = opt;
1441                         break;
1442                 case 'h':
1443                         printf("import FILE\n"
1444                                "import < FILE : import a file\n"
1445                                "\t--add: add configuration\n"
1446                                "\t--del: delete configuration\n"
1447                                "\t--show: show configuration\n"
1448                                "\t--exec: execute command\n"
1449                                "\t--help: display this help\n"
1450                                "If no command option is given then --add"
1451                                " is assumed by default\n");
1452                         return 0;
1453                 default:
1454                         return 0;
1455                 }
1456         }
1457
1458         /* grab the file name if one exists */
1459         if (opt_found && argc == 3)
1460                 file = argv[2];
1461         else if (!opt_found && argc == 2)
1462                 file = argv[1];
1463
1464         switch (cmd) {
1465         case 'a':
1466                 rc = lustre_yaml_config(file, &err_rc);
1467                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
1468                 cYAML_print_tree(show_rc);
1469                 cYAML_free_tree(show_rc);
1470                 break;
1471         case 'd':
1472                 rc = lustre_yaml_del(file, &err_rc);
1473                 break;
1474         case 's':
1475                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
1476                 cYAML_print_tree(show_rc);
1477                 cYAML_free_tree(show_rc);
1478                 break;
1479         case 'e':
1480                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
1481                 cYAML_print_tree(show_rc);
1482                 cYAML_free_tree(show_rc);
1483                 break;
1484         }
1485
1486         if (rc || return_rc) {
1487                 cYAML_print_tree2file(stderr, err_rc);
1488                 cYAML_free_tree(err_rc);
1489         }
1490
1491         return rc;
1492 }
1493
1494 static int jt_export(int argc, char **argv)
1495 {
1496         struct cYAML *show_rc = NULL;
1497         struct cYAML *err_rc = NULL;
1498         int rc;
1499         FILE *f = NULL;
1500         int opt;
1501         bool backup = false;
1502         char *file = NULL;
1503
1504         const char *const short_options = "bh";
1505         static const struct option long_options[] = {
1506                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
1507                 { .name = "help", .has_arg = no_argument, .val = 'h' },
1508                 { .name = NULL } };
1509
1510         while ((opt = getopt_long(argc, argv, short_options,
1511                                    long_options, NULL)) != -1) {
1512                 switch (opt) {
1513                 case 'b':
1514                         backup = true;
1515                         break;
1516                 case 'h':
1517                 default:
1518                         printf("export > FILE.yaml : export configuration\n"
1519                                "\t--backup: export only what's necessary for reconfig\n"
1520                                "\t--help: display this help\n");
1521                         return 0;
1522                 }
1523         }
1524
1525         if (backup && argc >= 3)
1526                 file = argv[2];
1527         else if (!backup && argc >= 2)
1528                 file = argv[1];
1529         else
1530                 f = stdout;
1531
1532         if (file) {
1533                 f = fopen(file, "w");
1534                 if (f == NULL)
1535                         return -1;
1536         }
1537
1538         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
1539         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1540                 cYAML_print_tree2file(stderr, err_rc);
1541                 cYAML_free_tree(err_rc);
1542                 err_rc = NULL;
1543         }
1544
1545         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
1546                                     &err_rc, backup);
1547         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1548                 cYAML_print_tree2file(stderr, err_rc);
1549                 cYAML_free_tree(err_rc);
1550                 err_rc = NULL;
1551         }
1552
1553         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
1554         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1555                 cYAML_print_tree2file(stderr, err_rc);
1556                 cYAML_free_tree(err_rc);
1557                 err_rc = NULL;
1558         }
1559
1560         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
1561         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1562                 cYAML_print_tree2file(stderr, err_rc);
1563                 cYAML_free_tree(err_rc);
1564                 err_rc = NULL;
1565         }
1566
1567         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
1568         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1569                 cYAML_print_tree2file(stderr, err_rc);
1570                 cYAML_free_tree(err_rc);
1571                 err_rc = NULL;
1572         }
1573
1574         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
1575         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1576                 cYAML_print_tree2file(stderr, err_rc);
1577                 cYAML_free_tree(err_rc);
1578                 err_rc = NULL;
1579         }
1580
1581         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
1582         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1583                 cYAML_print_tree2file(stderr, err_rc);
1584                 cYAML_free_tree(err_rc);
1585                 err_rc = NULL;
1586         }
1587
1588         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
1589         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1590                 cYAML_print_tree2file(stderr, err_rc);
1591                 cYAML_free_tree(err_rc);
1592                 err_rc = NULL;
1593         }
1594
1595         if (show_rc != NULL) {
1596                 cYAML_print_tree2file(f, show_rc);
1597                 cYAML_free_tree(show_rc);
1598         }
1599
1600         if (argc >= 2)
1601                 fclose(f);
1602
1603         return 0;
1604 }
1605
1606 static int jt_add_peer_nid(int argc, char **argv)
1607 {
1608         char *prim_nid = NULL;
1609         char **nids = NULL, **nids2 = NULL;
1610         int size = 0;
1611         struct cYAML *err_rc = NULL;
1612         int rc = LUSTRE_CFG_RC_NO_ERR, opt, i;
1613         bool non_mr = false;
1614         bool ip2nets = false, nid_list = false, prim_nid_present = false;
1615
1616         const char *const short_opts = "k:mn:";
1617         const struct option long_opts[] = {
1618         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
1619         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
1620         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1621         { .name = "ip2nets",    .has_arg = required_argument,   .val = 'i' },
1622         { .name = NULL } };
1623
1624         rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
1625         if (rc)
1626                 return rc;
1627
1628         while ((opt = getopt_long(argc, argv, short_opts,
1629                                   long_opts, NULL)) != -1) {
1630                 switch (opt) {
1631                 case 'k':
1632                         prim_nid_present = true;
1633                         if (ip2nets) {
1634                                 cYAML_build_error(-1, -1, "peer", "add",
1635                                                 "ip2nets can not be specified"
1636                                                 " along side prim_nid parameter.",
1637                                                 &err_rc);
1638                                 goto failed;
1639                         }
1640                         prim_nid = optarg;
1641                         break;
1642                 case 'i':
1643                 case 'n':
1644                         if (opt == 'i')
1645                                 ip2nets = true;
1646
1647                         if (opt == 'n')
1648                                 nid_list = true;
1649
1650                         if (ip2nets && (nid_list || prim_nid_present)) {
1651                                 cYAML_build_error(-1, -1, "peer", "add",
1652                                                 "ip2nets can not be specified"
1653                                                 " along side nid or prim_nid"
1654                                                 " parameters", &err_rc);
1655                                 goto failed;
1656                         }
1657
1658                         size = lustre_lnet_parse_nids(optarg, nids, size,
1659                                                       &nids2);
1660                         if (nids2 == NULL)
1661                                 goto failed;
1662                         nids = nids2;
1663                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1664                         break;
1665                 case 'm':
1666                         non_mr = true;
1667                         break;
1668                 case '?':
1669                         print_help(peer_cmds, "peer", "add");
1670                 default:
1671                         return 0;
1672                 }
1673         }
1674
1675         for (; optind < argc; optind++) {
1676                 size = lustre_lnet_parse_nids(argv[optind], nids, size,
1677                                                 &nids2);
1678                 if (nids2 == NULL)
1679                         goto failed;
1680                 nids = nids2;
1681         }
1682
1683         rc = lustre_lnet_config_peer_nid(prim_nid, nids, size,
1684                                          !non_mr, ip2nets, -1, &err_rc);
1685
1686 failed:
1687         if (nids) {
1688                 /* free the array of nids */
1689                 for (i = 0; i < size; i++)
1690                         free(nids[i]);
1691                 free(nids);
1692         }
1693
1694         if (rc != LUSTRE_CFG_RC_NO_ERR)
1695                 cYAML_print_tree2file(stderr, err_rc);
1696
1697         cYAML_free_tree(err_rc);
1698
1699         return rc;
1700 }
1701
1702 static int jt_del_peer_nid(int argc, char **argv)
1703 {
1704         char *prim_nid = NULL;
1705         char **nids = NULL, **nids2 = NULL;
1706         struct cYAML *err_rc = NULL;
1707         int rc = LUSTRE_CFG_RC_NO_ERR, opt, i, size = 0;
1708         bool ip2nets = false, nid_list = false, prim_nid_present = false;
1709
1710         const char *const short_opts = "k:n:";
1711         const struct option long_opts[] = {
1712         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
1713         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1714         { .name = "ip2nets",    .has_arg = required_argument,   .val = 'i' },
1715         { .name = NULL } };
1716
1717         rc = check_cmd(peer_cmds, "peer", "del", 2, argc, argv);
1718         if (rc)
1719                 return rc;
1720
1721         while ((opt = getopt_long(argc, argv, short_opts,
1722                                   long_opts, NULL)) != -1) {
1723                 switch (opt) {
1724                 case 'k':
1725                         prim_nid_present = true;
1726                         if (ip2nets) {
1727                                 cYAML_build_error(-1, -1, "peer", "add",
1728                                                 "ip2nets can not be specified"
1729                                                 " along side prim_nid parameter.",
1730                                                 &err_rc);
1731                                 goto failed;
1732                         }
1733                         prim_nid = optarg;
1734                         break;
1735                 case 'i':
1736                 case 'n':
1737                         if (opt == 'i')
1738                                 ip2nets = true;
1739
1740                         if (opt == 'n')
1741                                 nid_list = true;
1742
1743                         if (ip2nets && (nid_list || prim_nid_present)) {
1744                                 cYAML_build_error(-1, -1, "peer", "add",
1745                                                 "ip2nets can not be specified"
1746                                                 " along side nid or prim_nid"
1747                                                 " parameters", &err_rc);
1748                                 goto failed;
1749                         }
1750                         size = lustre_lnet_parse_nids(optarg, nids, size,
1751                                                       &nids2);
1752                         if (nids2 == NULL)
1753                                 goto failed;
1754                         nids = nids2;
1755                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1756                         break;
1757                 case '?':
1758                         print_help(peer_cmds, "peer", "del");
1759                 default:
1760                         return 0;
1761                 }
1762         }
1763
1764         for (; optind < argc; optind++) {
1765                 size = lustre_lnet_parse_nids(argv[optind], nids, size,
1766                                                 &nids2);
1767                 if (nids2 == NULL)
1768                         goto failed;
1769                 nids = nids2;
1770         }
1771
1772         rc = lustre_lnet_del_peer_nid(prim_nid, nids, size, ip2nets, -1, &err_rc);
1773
1774 failed:
1775         if (nids) {
1776                 for (i = 0; i < size; i++)
1777                         free(nids[i]);
1778                 free(nids);
1779         }
1780
1781         if (rc != LUSTRE_CFG_RC_NO_ERR)
1782                 cYAML_print_tree2file(stderr, err_rc);
1783
1784         cYAML_free_tree(err_rc);
1785
1786         return rc;
1787 }
1788
1789 static int jt_show_peer(int argc, char **argv)
1790 {
1791         char *nid = NULL;
1792         int rc, opt;
1793         struct cYAML *err_rc = NULL, *show_rc = NULL;
1794         long int detail = 0;
1795
1796         const char *const short_opts = "hn:v::";
1797         const struct option long_opts[] = {
1798         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
1799         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1800         { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
1801         { .name = NULL } };
1802
1803         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
1804         if (rc)
1805                 return rc;
1806
1807         while ((opt = getopt_long(argc, argv, short_opts,
1808                                   long_opts, NULL)) != -1) {
1809                 switch (opt) {
1810                 case 'n':
1811                         nid = optarg;
1812                         break;
1813                 case 'v':
1814                         if ((!optarg) && (argv[optind] != NULL) &&
1815                             (argv[optind][0] != '-')) {
1816                                 if (parse_long(argv[optind++], &detail) != 0)
1817                                         detail = 1;
1818                         } else {
1819                                 detail = 1;
1820                         }
1821                         break;
1822                 case '?':
1823                         print_help(peer_cmds, "peer", "show");
1824                 default:
1825                         return 0;
1826                 }
1827         }
1828
1829         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
1830                                    false);
1831
1832         if (rc != LUSTRE_CFG_RC_NO_ERR)
1833                 cYAML_print_tree2file(stderr, err_rc);
1834         else if (show_rc)
1835                 cYAML_print_tree(show_rc);
1836
1837         cYAML_free_tree(err_rc);
1838         cYAML_free_tree(show_rc);
1839
1840         return rc;
1841 }
1842
1843 static int jt_list_peer(int argc, char **argv)
1844 {
1845         int rc;
1846         struct cYAML *err_rc = NULL, *list_rc = NULL;
1847
1848         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
1849         if (rc)
1850                 return rc;
1851
1852         rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
1853
1854         if (rc != LUSTRE_CFG_RC_NO_ERR)
1855                 cYAML_print_tree2file(stderr, err_rc);
1856         else if (list_rc)
1857                 cYAML_print_tree(list_rc);
1858
1859         cYAML_free_tree(err_rc);
1860         cYAML_free_tree(list_rc);
1861
1862         return rc;
1863 }
1864
1865 static int jt_ping(int argc, char **argv)
1866 {
1867         struct cYAML *err_rc = NULL;
1868         struct cYAML *show_rc = NULL;
1869         int timeout = 1000;
1870         int rc = 0, opt;
1871
1872         const char *const short_options = "ht:";
1873         const struct option long_options[] = {
1874         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
1875         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
1876         { .name = NULL } };
1877
1878         while ((opt = getopt_long(argc, argv, short_options,
1879                                   long_options, NULL)) != -1) {
1880                 switch (opt) {
1881                 case 't':
1882                         timeout = 1000 * atol(optarg);
1883                         break;
1884                 case 'h':
1885                         printf("ping nid[,nid,...]\n"
1886                                "\t --timeout: ping timeout\n"
1887                                "\t --help: display this help\n");
1888                         return 0;
1889                 default:
1890                         return 0;
1891                 }
1892         }
1893
1894         for (; optind < argc; optind++)
1895                 rc = lustre_lnet_ping_nid(argv[optind], timeout, -1, &show_rc, &err_rc);
1896
1897         if (show_rc)
1898                 cYAML_print_tree(show_rc);
1899
1900         if (err_rc)
1901                 cYAML_print_tree2file(stderr, err_rc);
1902
1903         cYAML_free_tree(err_rc);
1904         cYAML_free_tree(show_rc);
1905
1906         return rc;
1907 }
1908
1909 static int jt_discover(int argc, char **argv)
1910 {
1911         struct cYAML *err_rc = NULL;
1912         struct cYAML *show_rc = NULL;
1913         int force = 0;
1914         int rc = 0, opt;
1915
1916         const char *const short_options = "fh";
1917         const struct option long_options[] = {
1918                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
1919                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
1920                 { .name = NULL } };
1921
1922         while ((opt = getopt_long(argc, argv, short_options,
1923                                   long_options, NULL)) != -1) {
1924                 switch (opt) {
1925                 case 'f':
1926                         force = 1;
1927                         break;
1928                 case 'h':
1929                         printf("discover nid[,nid,...]\n"
1930                                "\t --force: force discovery\n"
1931                                "\t --help: display this help\n");
1932                         return 0;
1933                 default:
1934                         return 0;
1935                 }
1936         }
1937
1938         for (; optind < argc; optind++)
1939                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
1940                                               &err_rc);
1941
1942         if (show_rc)
1943                 cYAML_print_tree(show_rc);
1944
1945         if (err_rc)
1946                 cYAML_print_tree2file(stderr, err_rc);
1947
1948         cYAML_free_tree(err_rc);
1949         cYAML_free_tree(show_rc);
1950
1951         return rc;
1952 }
1953
1954 static int lnetctl_list_commands(int argc, char **argv)
1955 {
1956         char buffer[81] = ""; /* 80 printable chars + terminating NUL */
1957
1958         Parser_list_commands(cmd_list, buffer, sizeof(buffer), NULL, 0, 4);
1959
1960         return 0;
1961 }
1962
1963 int main(int argc, char **argv)
1964 {
1965         int rc = 0;
1966         struct cYAML *err_rc = NULL;
1967
1968         rc = lustre_lnet_config_lib_init();
1969         if (rc < 0) {
1970                 cYAML_build_error(-1, -1, "lnetctl", "startup",
1971                                   "cannot register LNet device", &err_rc);
1972                 cYAML_print_tree2file(stderr, err_rc);
1973                 return rc;
1974         }
1975
1976         Parser_init("lnetctl > ", cmd_list);
1977         if (argc > 1) {
1978                 rc = Parser_execarg(argc - 1, &argv[1], cmd_list);
1979                 goto errorout;
1980         }
1981
1982         Parser_commands();
1983
1984 errorout:
1985         return rc;
1986 }