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