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