Whamcloud - gitweb
bce3e9063513c87b196bdf67c86b67ac6773d782
[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, false);
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                                   false);
898
899         if (rc != LUSTRE_CFG_RC_NO_ERR)
900                 cYAML_print_tree2file(stderr, err_rc);
901         else if (show_rc)
902                 cYAML_print_tree(show_rc);
903
904         cYAML_free_tree(err_rc);
905         cYAML_free_tree(show_rc);
906
907         return rc;
908 }
909
910 static int jt_show_routing(int argc, char **argv)
911 {
912         struct cYAML *err_rc = NULL, *show_rc = NULL;
913         int rc;
914
915         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
916         if (rc)
917                 return rc;
918
919         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
920
921         if (rc != LUSTRE_CFG_RC_NO_ERR)
922                 cYAML_print_tree2file(stderr, err_rc);
923         else if (show_rc)
924                 cYAML_print_tree(show_rc);
925
926         cYAML_free_tree(err_rc);
927         cYAML_free_tree(show_rc);
928
929         return rc;
930 }
931
932 static int jt_show_stats(int argc, char **argv)
933 {
934         int rc;
935         struct cYAML *show_rc = NULL, *err_rc = NULL;
936
937         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
938         if (rc)
939                 return rc;
940
941         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
942
943         if (rc != LUSTRE_CFG_RC_NO_ERR)
944                 cYAML_print_tree2file(stderr, err_rc);
945         else if (show_rc)
946                 cYAML_print_tree(show_rc);
947
948         cYAML_free_tree(err_rc);
949         cYAML_free_tree(show_rc);
950
951         return rc;
952 }
953
954 static int jt_show_global(int argc, char **argv)
955 {
956         int rc;
957         struct cYAML *show_rc = NULL, *err_rc = NULL;
958
959         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
960         if (rc)
961                 return rc;
962
963         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
964         if (rc != LUSTRE_CFG_RC_NO_ERR) {
965                 cYAML_print_tree2file(stderr, err_rc);
966                 goto out;
967         }
968
969         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
970         if (rc != LUSTRE_CFG_RC_NO_ERR) {
971                 cYAML_print_tree2file(stderr, err_rc);
972                 goto out;
973         }
974
975         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
976         if (rc != LUSTRE_CFG_RC_NO_ERR) {
977                 cYAML_print_tree2file(stderr, err_rc);
978                 goto out;
979         }
980
981         if (show_rc)
982                 cYAML_print_tree(show_rc);
983
984 out:
985         cYAML_free_tree(err_rc);
986         cYAML_free_tree(show_rc);
987
988         return rc;
989 }
990
991 static int jt_lnet(int argc, char **argv)
992 {
993         int rc;
994
995         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
996         if (rc)
997                 return rc;
998
999         return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
1000 }
1001
1002 static int jt_route(int argc, char **argv)
1003 {
1004         int rc;
1005
1006         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
1007         if (rc)
1008                 return rc;
1009
1010         return Parser_execarg(argc - 1, &argv[1], route_cmds);
1011 }
1012
1013 static int jt_net(int argc, char **argv)
1014 {
1015         int rc;
1016
1017         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
1018         if (rc)
1019                 return rc;
1020
1021         return Parser_execarg(argc - 1, &argv[1], net_cmds);
1022 }
1023
1024 static int jt_routing(int argc, char **argv)
1025 {
1026         int rc;
1027
1028         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
1029         if (rc)
1030                 return rc;
1031
1032         return Parser_execarg(argc - 1, &argv[1], routing_cmds);
1033 }
1034
1035 static int jt_stats(int argc, char **argv)
1036 {
1037         int rc;
1038
1039         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
1040         if (rc)
1041                 return rc;
1042
1043         return Parser_execarg(argc - 1, &argv[1], stats_cmds);
1044 }
1045
1046 static int jt_global(int argc, char **argv)
1047 {
1048         int rc;
1049
1050         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
1051         if (rc)
1052                 return rc;
1053
1054         return Parser_execarg(argc - 1, &argv[1], global_cmds);
1055 }
1056
1057 static int jt_peers(int argc, char **argv)
1058 {
1059         int rc;
1060
1061         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
1062         if (rc)
1063                 return rc;
1064
1065         return Parser_execarg(argc - 1, &argv[1], peer_cmds);
1066 }
1067
1068 static int jt_set(int argc, char **argv)
1069 {
1070         int rc;
1071
1072         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
1073         if (rc)
1074                 return rc;
1075
1076         return Parser_execarg(argc - 1, &argv[1], set_cmds);
1077 }
1078
1079 static int jt_import(int argc, char **argv)
1080 {
1081         char *file = NULL;
1082         struct cYAML *err_rc = NULL;
1083         struct cYAML *show_rc = NULL;
1084         int rc = 0, return_rc = 0, opt, opt_found = 0;
1085         char cmd = 'a';
1086
1087         const char *const short_options = "adseh";
1088         static const struct option long_options[] = {
1089                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
1090                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
1091                 { .name = "show", .has_arg = no_argument, .val = 's' },
1092                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
1093                 { .name = "help", .has_arg = no_argument, .val = 'h' },
1094                 { .name = NULL } };
1095
1096         while ((opt = getopt_long(argc, argv, short_options,
1097                                    long_options, NULL)) != -1) {
1098                 opt_found = 1;
1099                 switch (opt) {
1100                 case 'a':
1101                         cmd = opt;
1102                         break;
1103                 case 'd':
1104                 case 's':
1105                         cmd = opt;
1106                         break;
1107                 case 'e':
1108                         cmd = opt;
1109                         break;
1110                 case 'h':
1111                         printf("import FILE\n"
1112                                "import < FILE : import a file\n"
1113                                "\t--add: add configuration\n"
1114                                "\t--del: delete configuration\n"
1115                                "\t--show: show configuration\n"
1116                                "\t--exec: execute command\n"
1117                                "\t--help: display this help\n"
1118                                "If no command option is given then --add"
1119                                " is assumed by default\n");
1120                         return 0;
1121                 default:
1122                         return 0;
1123                 }
1124         }
1125
1126         /* grab the file name if one exists */
1127         if (opt_found && argc == 3)
1128                 file = argv[2];
1129         else if (!opt_found && argc == 2)
1130                 file = argv[1];
1131
1132         switch (cmd) {
1133         case 'a':
1134                 rc = lustre_yaml_config(file, &err_rc);
1135                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
1136                 cYAML_print_tree(show_rc);
1137                 cYAML_free_tree(show_rc);
1138                 break;
1139         case 'd':
1140                 rc = lustre_yaml_del(file, &err_rc);
1141                 break;
1142         case 's':
1143                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
1144                 cYAML_print_tree(show_rc);
1145                 cYAML_free_tree(show_rc);
1146                 break;
1147         case 'e':
1148                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
1149                 cYAML_print_tree(show_rc);
1150                 cYAML_free_tree(show_rc);
1151                 break;
1152         }
1153
1154         if (rc || return_rc) {
1155                 cYAML_print_tree2file(stderr, err_rc);
1156                 cYAML_free_tree(err_rc);
1157         }
1158
1159         return rc;
1160 }
1161
1162 static int jt_export(int argc, char **argv)
1163 {
1164         struct cYAML *show_rc = NULL;
1165         struct cYAML *err_rc = NULL;
1166         int rc;
1167         FILE *f = NULL;
1168         int opt;
1169         bool backup = false;
1170         char *file = NULL;
1171
1172         const char *const short_options = "bh";
1173         static const struct option long_options[] = {
1174                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
1175                 { .name = "help", .has_arg = no_argument, .val = 'h' },
1176                 { .name = NULL } };
1177
1178         while ((opt = getopt_long(argc, argv, short_options,
1179                                    long_options, NULL)) != -1) {
1180                 switch (opt) {
1181                 case 'b':
1182                         backup = true;
1183                         break;
1184                 case 'h':
1185                 default:
1186                         printf("export > FILE.yaml : export configuration\n"
1187                                "\t--help: display this help\n");
1188                         return 0;
1189                 }
1190         }
1191
1192         if (backup && argc >= 3)
1193                 file = argv[2];
1194         else if (!backup && argc >= 2)
1195                 file = argv[1];
1196         else
1197                 f = stdout;
1198
1199         if (file) {
1200                 f = fopen(file, "w");
1201                 if (f == NULL)
1202                         return -1;
1203         }
1204
1205         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
1206         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1207                 cYAML_print_tree2file(stderr, err_rc);
1208                 cYAML_free_tree(err_rc);
1209                 err_rc = NULL;
1210         }
1211
1212         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
1213                                     &err_rc, backup);
1214         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1215                 cYAML_print_tree2file(stderr, err_rc);
1216                 cYAML_free_tree(err_rc);
1217                 err_rc = NULL;
1218         }
1219
1220         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
1221         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1222                 cYAML_print_tree2file(stderr, err_rc);
1223                 cYAML_free_tree(err_rc);
1224                 err_rc = NULL;
1225         }
1226
1227         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
1228         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1229                 cYAML_print_tree2file(stderr, err_rc);
1230                 cYAML_free_tree(err_rc);
1231                 err_rc = NULL;
1232         }
1233
1234         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
1235         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1236                 cYAML_print_tree2file(stderr, err_rc);
1237                 cYAML_free_tree(err_rc);
1238                 err_rc = NULL;
1239         }
1240
1241         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
1242         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1243                 cYAML_print_tree2file(stderr, err_rc);
1244                 cYAML_free_tree(err_rc);
1245                 err_rc = NULL;
1246         }
1247
1248         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
1249         if (rc != LUSTRE_CFG_RC_NO_ERR) {
1250                 cYAML_print_tree2file(stderr, err_rc);
1251                 cYAML_free_tree(err_rc);
1252                 err_rc = NULL;
1253         }
1254
1255         if (show_rc != NULL) {
1256                 cYAML_print_tree2file(f, show_rc);
1257                 cYAML_free_tree(show_rc);
1258         }
1259
1260         if (argc >= 2)
1261                 fclose(f);
1262
1263         return 0;
1264 }
1265
1266 static int jt_add_peer_nid(int argc, char **argv)
1267 {
1268         char *prim_nid = NULL;
1269         char **nids = NULL, **nids2 = NULL;
1270         int size = 0;
1271         struct cYAML *err_rc = NULL;
1272         int rc = LUSTRE_CFG_RC_NO_ERR, opt, i;
1273         bool non_mr = false;
1274
1275         const char *const short_opts = "k:mn:";
1276         const struct option long_opts[] = {
1277         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
1278         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
1279         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1280         { .name = NULL } };
1281
1282         rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
1283         if (rc)
1284                 return rc;
1285
1286         while ((opt = getopt_long(argc, argv, short_opts,
1287                                   long_opts, NULL)) != -1) {
1288                 switch (opt) {
1289                 case 'k':
1290                         prim_nid = optarg;
1291                         break;
1292                 case 'n':
1293                         size = lustre_lnet_parse_nids(optarg, nids, size,
1294                                                       &nids2);
1295                         if (nids2 == NULL)
1296                                 goto failed;
1297                         nids = nids2;
1298                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1299                         break;
1300                 case 'm':
1301                         non_mr = true;
1302                         break;
1303                 default:
1304                         return 0;
1305                 }
1306         }
1307
1308         rc = lustre_lnet_config_peer_nid(prim_nid, nids, size,
1309                                          !non_mr, -1, &err_rc);
1310
1311 failed:
1312         if (nids) {
1313                 /* free the array of nids */
1314                 for (i = 0; i < size; i++)
1315                         free(nids[i]);
1316                 free(nids);
1317         }
1318
1319         if (rc != LUSTRE_CFG_RC_NO_ERR)
1320                 cYAML_print_tree2file(stderr, err_rc);
1321
1322         cYAML_free_tree(err_rc);
1323
1324         return rc;
1325 }
1326
1327 static int jt_del_peer_nid(int argc, char **argv)
1328 {
1329         char *prim_nid = NULL;
1330         char **nids = NULL, **nids2 = NULL;
1331         struct cYAML *err_rc = NULL;
1332         int rc = LUSTRE_CFG_RC_NO_ERR, opt, i, size = 0;
1333
1334         const char *const short_opts = "k:n:";
1335         const struct option long_opts[] = {
1336         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
1337         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1338         { .name = NULL } };
1339
1340         rc = check_cmd(peer_cmds, "peer", "del", 2, argc, argv);
1341         if (rc)
1342                 return rc;
1343
1344         while ((opt = getopt_long(argc, argv, short_opts,
1345                                   long_opts, NULL)) != -1) {
1346                 switch (opt) {
1347                 case 'k':
1348                         prim_nid = optarg;
1349                         break;
1350                 case 'n':
1351                         size = lustre_lnet_parse_nids(optarg, nids, size,
1352                                                       &nids2);
1353                         if (nids2 == NULL)
1354                                 goto failed;
1355                         nids = nids2;
1356                         rc = LUSTRE_CFG_RC_OUT_OF_MEM;
1357                         break;
1358                 default:
1359                         return 0;
1360                 }
1361         }
1362
1363         rc = lustre_lnet_del_peer_nid(prim_nid, nids, size, -1, &err_rc);
1364
1365 failed:
1366         if (nids) {
1367                 for (i = 0; i < size; i++)
1368                         free(nids[i]);
1369                 free(nids);
1370         }
1371
1372         if (rc != LUSTRE_CFG_RC_NO_ERR)
1373                 cYAML_print_tree2file(stderr, err_rc);
1374
1375         cYAML_free_tree(err_rc);
1376
1377         return rc;
1378 }
1379
1380 static int jt_show_peer(int argc, char **argv)
1381 {
1382         char *nid = NULL;
1383         int rc, opt;
1384         struct cYAML *err_rc = NULL, *show_rc = NULL;
1385         long int detail = 0;
1386
1387         const char *const short_opts = "hn:v::";
1388         const struct option long_opts[] = {
1389         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
1390         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
1391         { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
1392         { .name = NULL } };
1393
1394         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
1395         if (rc)
1396                 return rc;
1397
1398         while ((opt = getopt_long(argc, argv, short_opts,
1399                                   long_opts, NULL)) != -1) {
1400                 switch (opt) {
1401                 case 'n':
1402                         nid = optarg;
1403                         break;
1404                 case 'v':
1405                         if ((!optarg) && (argv[optind] != NULL) &&
1406                             (argv[optind][0] != '-')) {
1407                                 if (parse_long(argv[optind++], &detail) != 0)
1408                                         detail = 1;
1409                         } else {
1410                                 detail = 1;
1411                         }
1412                         break;
1413                 default:
1414                         return 0;
1415                 }
1416         }
1417
1418         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
1419                                    false);
1420
1421         if (rc != LUSTRE_CFG_RC_NO_ERR)
1422                 cYAML_print_tree2file(stderr, err_rc);
1423         else if (show_rc)
1424                 cYAML_print_tree(show_rc);
1425
1426         cYAML_free_tree(err_rc);
1427         cYAML_free_tree(show_rc);
1428
1429         return rc;
1430 }
1431
1432 static int jt_list_peer(int argc, char **argv)
1433 {
1434         int rc;
1435         struct cYAML *err_rc = NULL, *list_rc = NULL;
1436
1437         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
1438         if (rc)
1439                 return rc;
1440
1441         rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
1442
1443         if (rc != LUSTRE_CFG_RC_NO_ERR)
1444                 cYAML_print_tree2file(stderr, err_rc);
1445         else if (list_rc)
1446                 cYAML_print_tree(list_rc);
1447
1448         cYAML_free_tree(err_rc);
1449         cYAML_free_tree(list_rc);
1450
1451         return rc;
1452 }
1453
1454 static int jt_ping(int argc, char **argv)
1455 {
1456         struct cYAML *err_rc = NULL;
1457         struct cYAML *show_rc = NULL;
1458         int timeout = 1000;
1459         int rc = 0, opt;
1460
1461         const char *const short_options = "ht:";
1462         const struct option long_options[] = {
1463         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
1464         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
1465         { .name = NULL } };
1466
1467         while ((opt = getopt_long(argc, argv, short_options,
1468                                   long_options, NULL)) != -1) {
1469                 switch (opt) {
1470                 case 't':
1471                         timeout = 1000 * atol(optarg);
1472                         break;
1473                 case 'h':
1474                         printf("ping nid[,nid,...]\n"
1475                                "\t --timeout: ping timeout\n"
1476                                "\t --help: display this help\n");
1477                         return 0;
1478                 default:
1479                         return 0;
1480                 }
1481         }
1482
1483         for (; optind < argc; optind++)
1484                 rc = lustre_lnet_ping_nid(argv[optind], timeout, -1, &show_rc, &err_rc);
1485
1486         if (show_rc)
1487                 cYAML_print_tree(show_rc);
1488
1489         if (err_rc)
1490                 cYAML_print_tree2file(stderr, err_rc);
1491
1492         cYAML_free_tree(err_rc);
1493         cYAML_free_tree(show_rc);
1494
1495         return rc;
1496 }
1497
1498 static int jt_discover(int argc, char **argv)
1499 {
1500         struct cYAML *err_rc = NULL;
1501         struct cYAML *show_rc = NULL;
1502         int force = 0;
1503         int rc = 0, opt;
1504
1505         const char *const short_options = "fh";
1506         const struct option long_options[] = {
1507                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
1508                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
1509                 { .name = NULL } };
1510
1511         while ((opt = getopt_long(argc, argv, short_options,
1512                                   long_options, NULL)) != -1) {
1513                 switch (opt) {
1514                 case 'f':
1515                         force = 1;
1516                         break;
1517                 case 'h':
1518                         printf("discover nid[,nid,...]\n"
1519                                "\t --force: force discovery\n"
1520                                "\t --help: display this help\n");
1521                         return 0;
1522                 default:
1523                         return 0;
1524                 }
1525         }
1526
1527         for (; optind < argc; optind++)
1528                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
1529                                               &err_rc);
1530
1531         if (show_rc)
1532                 cYAML_print_tree(show_rc);
1533
1534         if (err_rc)
1535                 cYAML_print_tree2file(stderr, err_rc);
1536
1537         cYAML_free_tree(err_rc);
1538         cYAML_free_tree(show_rc);
1539
1540         return rc;
1541 }
1542
1543 static int lnetctl_list_commands(int argc, char **argv)
1544 {
1545         char buffer[81] = ""; /* 80 printable chars + terminating NUL */
1546
1547         Parser_list_commands(cmd_list, buffer, sizeof(buffer), NULL, 0, 4);
1548
1549         return 0;
1550 }
1551
1552 int main(int argc, char **argv)
1553 {
1554         int rc = 0;
1555         struct cYAML *err_rc = NULL;
1556
1557         rc = lustre_lnet_config_lib_init();
1558         if (rc < 0) {
1559                 cYAML_build_error(-1, -1, "lnetctl", "startup",
1560                                   "cannot register LNet device", &err_rc);
1561                 cYAML_print_tree2file(stderr, err_rc);
1562                 return rc;
1563         }
1564
1565         Parser_init("lnetctl > ", cmd_list);
1566         if (argc > 1) {
1567                 rc = Parser_execarg(argc - 1, &argv[1], cmd_list);
1568                 goto errorout;
1569         }
1570
1571         Parser_commands();
1572
1573 errorout:
1574         return rc;
1575 }