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