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