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