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