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