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