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