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