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