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