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