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