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