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