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