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