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