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