Whamcloud - gitweb
LU-8056 llite: use inode_lock to access i_mutex
[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, 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 <libcfs/util/ioctl.h>
31 #include <libcfs/util/parser.h>
32 #include <lnet/lnetctl.h>
33 #include "cyaml/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_net(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_net(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_credits(int argc, char **argv);
51 static int jt_set_tiny(int argc, char **argv);
52 static int jt_set_small(int argc, char **argv);
53 static int jt_set_large(int argc, char **argv);
54
55 command_t lnet_cmds[] = {
56         {"configure", jt_config_lnet, 0, "configure lnet\n"
57          "\t--all: load NI configuration from module parameters\n"},
58         {"unconfigure", jt_unconfig_lnet, 0, "unconfigure lnet\n"},
59         { 0, 0, 0, NULL }
60 };
61
62 command_t route_cmds[] = {
63         {"add", jt_add_route, 0, "add a route\n"
64          "\t--net: net name (e.g. tcp0)\n"
65          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
66          "\t--hop: number to final destination (1 < hops < 255)\n"
67          "\t--priority: priority of route (0 - highest prio\n"},
68         {"del", jt_del_route, 0, "delete a route\n"
69          "\t--net: net name (e.g. tcp0)\n"
70          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"},
71         {"show", jt_show_route, 0, "show routes\n"
72          "\t--net: net name (e.g. tcp0) to filter on\n"
73          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
74          "\t--hop: number to final destination (1 < hops < 255) to filter on\n"
75          "\t--priority: priority of route (0 - highest prio to filter on\n"
76          "\t--verbose: display detailed output per route\n"},
77         { 0, 0, 0, NULL }
78 };
79
80 command_t net_cmds[] = {
81         {"add", jt_add_net, 0, "add a network\n"
82          "\t--net: net name (e.g. tcp0)\n"
83          "\t--if: physical interface (e.g. eth0)\n"
84          "\t--ip2net: specify networks based on IP address patterns\n"
85          "\t--peer-timeout: time to wait before declaring a peer dead\n"
86          "\t--peer-credits: define the max number of inflight messages\n"
87          "\t--peer-buffer-credits: the number of buffer credits per peer\n"
88          "\t--credits: Network Interface credits\n"
89          "\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"},
90         {"del", jt_del_net, 0, "delete a network\n"
91          "\t--net: net name (e.g. tcp0)\n"},
92         {"show", jt_show_net, 0, "show networks\n"
93          "\t--net: net name (e.g. tcp0) to filter on\n"
94          "\t--verbose: display detailed output per network\n"},
95         { 0, 0, 0, NULL }
96 };
97
98 command_t routing_cmds[] = {
99         {"show", jt_show_routing, 0, "show routing information\n"},
100         { 0, 0, 0, NULL }
101 };
102
103 command_t stats_cmds[] = {
104         {"show", jt_show_stats, 0, "show LNET statistics\n"},
105         { 0, 0, 0, NULL }
106 };
107
108 command_t credits_cmds[] = {
109         {"show", jt_show_peer_credits, 0, "show peer credits\n"},
110         { 0, 0, 0, NULL }
111 };
112
113 command_t set_cmds[] = {
114         {"tiny_buffers", jt_set_tiny, 0, "set tiny routing buffers\n"
115          "\tVALUE must be greater than 0\n"},
116         {"small_buffers", jt_set_small, 0, "set small routing buffers\n"
117          "\tVALUE must be greater than 0\n"},
118         {"large_buffers", jt_set_large, 0, "set large routing buffers\n"
119          "\tVALUE must be greater than 0\n"},
120         {"routing", jt_set_routing, 0, "enable/disable routing\n"
121          "\t0 - disable routing\n"
122          "\t1 - enable routing\n"},
123         { 0, 0, 0, NULL }
124 };
125
126 static inline void print_help(const command_t cmds[], const char *cmd_type,
127                               const char *pc_name)
128 {
129         const command_t *cmd;
130
131         for (cmd = cmds; cmd->pc_name; cmd++) {
132                 if (pc_name != NULL &&
133                     strcmp(cmd->pc_name, pc_name) == 0) {
134                         printf("%s %s: %s\n", cmd_type, cmd->pc_name,
135                                cmd->pc_help);
136                         return;
137                 } else if (pc_name != NULL) {
138                         continue;
139                 }
140                 printf("%s %s: %s\n", cmd_type, cmd->pc_name, cmd->pc_help);
141         }
142 }
143
144 static int parse_long(const char *number, long int *value)
145 {
146         char *end;
147
148         *value = strtol(number,  &end, 0);
149         if (end != NULL && *end != 0)
150                 return -1;
151
152         return 0;
153 }
154
155 static int handle_help(const command_t *cmd_list, const char *cmd,
156                        const char *sub_cmd, int argc, char **argv)
157 {
158         int opt;
159         int rc = -1;
160         optind = 0;
161         opterr = 0;
162
163         const char *const short_options = "h";
164         const struct option long_options[] = {
165                 { "help", 0, NULL, 'h' },
166                 { NULL, 0, NULL, 0 },
167         };
168
169         while ((opt = getopt_long(argc, argv, short_options,
170                                   long_options, NULL)) != -1) {
171                 switch (opt) {
172                 case 'h':
173                         print_help(cmd_list, cmd, sub_cmd);
174                         rc = 0;
175                         break;
176                 default:
177                         rc = -1;
178                         break;
179                 }
180         }
181
182         opterr = 1;
183         optind = 0;
184         return rc;
185 }
186
187 static int jt_set_tiny(int argc, char **argv)
188 {
189         long int value;
190         int rc;
191         struct cYAML *err_rc = NULL;
192
193         if (handle_help(set_cmds, "set", "tiny_buffers", argc, argv) == 0)
194                 return 0;
195
196         rc = parse_long(argv[1], &value);
197         if (rc != 0) {
198                 cYAML_build_error(-1, -1, "parser", "set",
199                                   "cannot parse tiny_buffers value", &err_rc);
200                 cYAML_print_tree2file(stderr, err_rc);
201                 cYAML_free_tree(err_rc);
202                 return -1;
203         }
204
205         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
206         if (rc != LUSTRE_CFG_RC_NO_ERR)
207                 cYAML_print_tree2file(stderr, err_rc);
208
209         cYAML_free_tree(err_rc);
210
211         return rc;
212 }
213
214 static int jt_set_small(int argc, char **argv)
215 {
216         long int value;
217         int rc;
218         struct cYAML *err_rc = NULL;
219
220         if (handle_help(set_cmds, "set", "small_buffers", argc, argv) == 0)
221                 return 0;
222
223         rc = parse_long(argv[1], &value);
224         if (rc != 0) {
225                 cYAML_build_error(-1, -1, "parser", "set",
226                                   "cannot parse small_buffers value", &err_rc);
227                 cYAML_print_tree2file(stderr, err_rc);
228                 cYAML_free_tree(err_rc);
229                 return -1;
230         }
231
232         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
233         if (rc != LUSTRE_CFG_RC_NO_ERR)
234                 cYAML_print_tree2file(stderr, err_rc);
235
236         cYAML_free_tree(err_rc);
237
238         return rc;
239 }
240
241 static int jt_set_large(int argc, char **argv)
242 {
243         long int value;
244         int rc;
245         struct cYAML *err_rc = NULL;
246
247         if (handle_help(set_cmds, "set", "large_buffers", argc, argv) == 0)
248                 return 0;
249
250         rc = parse_long(argv[1], &value);
251         if (rc != 0) {
252                 cYAML_build_error(-1, -1, "parser", "set",
253                                   "cannot parse large_buffers value", &err_rc);
254                 cYAML_print_tree2file(stderr, err_rc);
255                 cYAML_free_tree(err_rc);
256                 return -1;
257         }
258
259         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
260         if (rc != LUSTRE_CFG_RC_NO_ERR)
261                 cYAML_print_tree2file(stderr, err_rc);
262
263         cYAML_free_tree(err_rc);
264
265         return rc;
266 }
267
268 static int jt_set_routing(int argc, char **argv)
269 {
270         long int value;
271         struct cYAML *err_rc = NULL;
272         int rc;
273
274         if (handle_help(set_cmds, "set", "routing", argc, argv) == 0)
275                 return 0;
276
277         rc = parse_long(argv[1], &value);
278         if (rc != 0 || (value != 0 && value != 1)) {
279                 cYAML_build_error(-1, -1, "parser", "set",
280                                   "cannot parse routing value.\n"
281                                   "must be 0 for disable or 1 for enable",
282                                   &err_rc);
283                 cYAML_print_tree2file(stderr, err_rc);
284                 cYAML_free_tree(err_rc);
285                 return -1;
286         }
287
288         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
289
290         if (rc != LUSTRE_CFG_RC_NO_ERR)
291                 cYAML_print_tree2file(stderr, err_rc);
292
293         cYAML_free_tree(err_rc);
294
295         return rc;
296 }
297
298 static int jt_config_lnet(int argc, char **argv)
299 {
300         struct cYAML *err_rc = NULL;
301         bool load_mod_params = false;
302         int rc, opt;
303
304         const char *const short_options = "ah";
305         const struct option long_options[] = {
306                 { "all", 0, NULL, 'a' },
307                 { "help", 0, NULL, 'h' },
308                 { NULL, 0, NULL, 0 },
309         };
310
311         while ((opt = getopt_long(argc, argv, short_options,
312                                    long_options, NULL)) != -1) {
313                 switch (opt) {
314                 case 'a':
315                         load_mod_params = true;
316                         break;
317                 case 'h':
318                         print_help(lnet_cmds, "lnet", "configure");
319                         return 0;
320                 default:
321                         return 0;
322                 }
323         }
324
325         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
326                                           -1, &err_rc);
327
328         if (rc != LUSTRE_CFG_RC_NO_ERR)
329                 cYAML_print_tree2file(stderr, err_rc);
330
331         cYAML_free_tree(err_rc);
332
333         return rc;
334 }
335
336 static int jt_unconfig_lnet(int argc, char **argv)
337 {
338         struct cYAML *err_rc = NULL;
339         int rc;
340
341         if (handle_help(lnet_cmds, "lnet", "unconfigure", argc, argv) == 0)
342                 return 0;
343
344         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
345
346         if (rc != LUSTRE_CFG_RC_NO_ERR)
347                 cYAML_print_tree2file(stderr, err_rc);
348
349         cYAML_free_tree(err_rc);
350
351         return rc;
352 }
353 static int jt_add_route(int argc, char **argv)
354 {
355         char *network = NULL, *gateway = NULL;
356         long int hop = -1, prio = -1;
357         struct cYAML *err_rc = NULL;
358         int rc, opt;
359
360         const char *const short_options = "n:g:c:p:h";
361         const struct option long_options[] = {
362                 { "net", 1, NULL, 'n' },
363                 { "gateway", 1, NULL, 'g' },
364                 { "hop-count", 1, NULL, 'c' },
365                 { "priority", 1, NULL, 'p' },
366                 { "help", 0, NULL, 'h' },
367                 { NULL, 0, NULL, 0 },
368         };
369
370         while ((opt = getopt_long(argc, argv, short_options,
371                                    long_options, NULL)) != -1) {
372                 switch (opt) {
373                 case 'n':
374                         network = optarg;
375                         break;
376                 case 'g':
377                         gateway = optarg;
378                         break;
379                 case 'c':
380                         rc = parse_long(optarg, &hop);
381                         if (rc != 0) {
382                                 /* ignore option */
383                                 hop = -1;
384                                 continue;
385                         }
386                         break;
387                 case 'p':
388                         rc = parse_long(optarg, &prio);
389                         if (rc != 0) {
390                                 /* ingore option */
391                                 prio = -1;
392                                 continue;
393                         }
394                         break;
395                 case 'h':
396                         print_help(route_cmds, "route", "add");
397                         return 0;
398                 default:
399                         return 0;
400                 }
401         }
402
403         rc = lustre_lnet_config_route(network, gateway, hop, prio, -1, &err_rc);
404
405         if (rc != LUSTRE_CFG_RC_NO_ERR)
406                 cYAML_print_tree2file(stderr, err_rc);
407
408         cYAML_free_tree(err_rc);
409
410         return rc;
411 }
412
413 static int jt_add_net(int argc, char **argv)
414 {
415         char *network = NULL, *intf = NULL, *ip2net = NULL, *cpt = NULL;
416         long int pto = -1, pc = -1, pbc = -1, cre = -1;
417         struct cYAML *err_rc = NULL;
418         int rc, opt;
419
420         const char *const short_options = "n:i:p:t:c:b:r:s:h";
421         const struct option long_options[] = {
422                 { "net", 1, NULL, 'n' },
423                 { "if", 1, NULL, 'i' },
424                 { "ip2net", 1, NULL, 'p' },
425                 { "peer-timeout", 1, NULL, 't' },
426                 { "peer-credits", 1, NULL, 'c' },
427                 { "peer-buffer-credits", 1, NULL, 'b' },
428                 { "credits", 1, NULL, 'r' },
429                 { "cpt", 1, NULL, 's' },
430                 { "help", 0, NULL, 'h' },
431                 { NULL, 0, NULL, 0 },
432         };
433
434         while ((opt = getopt_long(argc, argv, short_options,
435                                    long_options, NULL)) != -1) {
436                 switch (opt) {
437                 case 'n':
438                         network = optarg;
439                         break;
440                 case 'i':
441                         intf = optarg;
442                         break;
443                 case 'p':
444                         ip2net = optarg;
445                         break;
446                 case 't':
447                         rc = parse_long(optarg, &pto);
448                         if (rc != 0) {
449                                 /* ignore option */
450                                 pto = -1;
451                                 continue;
452                         }
453                         break;
454                 case 'c':
455                         rc = parse_long(optarg, &pc);
456                         if (rc != 0) {
457                                 /* ignore option */
458                                 pc = -1;
459                                 continue;
460                         }
461                         break;
462                 case 'b':
463                         rc = parse_long(optarg, &pbc);
464                         if (rc != 0) {
465                                 /* ignore option */
466                                 pbc = -1;
467                                 continue;
468                         }
469                         break;
470                 case 'r':
471                         rc = parse_long(optarg, &cre);
472                         if (rc != 0) {
473                                 /* ignore option */
474                                 cre = -1;
475                                 continue;
476                         }
477                         break;
478                 case 's':
479                         cpt = optarg;
480                         break;
481                 case 'h':
482                         print_help(net_cmds, "net", "add");
483                         return 0;
484                 default:
485                         return 0;
486                 }
487         }
488
489         rc = lustre_lnet_config_net(network, intf, ip2net, pto, pc, pbc,
490                                     cre, cpt, -1, NULL, &err_rc);
491
492         if (rc != LUSTRE_CFG_RC_NO_ERR)
493                 cYAML_print_tree2file(stderr, err_rc);
494
495         cYAML_free_tree(err_rc);
496
497         return rc;
498 }
499
500 static int jt_del_route(int argc, char **argv)
501 {
502         char *network = NULL, *gateway = NULL;
503         struct cYAML *err_rc = NULL;
504         int rc, opt;
505
506         const char *const short_options = "n:g:h";
507         const struct option long_options[] = {
508                 { "net", 1, NULL, 'n' },
509                 { "gateway", 1, NULL, 'g' },
510                 { "help", 0, NULL, 'h' },
511                 { NULL, 0, NULL, 0 },
512         };
513
514         while ((opt = getopt_long(argc, argv, short_options,
515                                    long_options, NULL)) != -1) {
516                 switch (opt) {
517                 case 'n':
518                         network = optarg;
519                         break;
520                 case 'g':
521                         gateway = optarg;
522                         break;
523                 case 'h':
524                         print_help(route_cmds, "route", "del");
525                         return 0;
526                 default:
527                         return 0;
528                 }
529         }
530
531         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
532
533         if (rc != LUSTRE_CFG_RC_NO_ERR)
534                 cYAML_print_tree2file(stderr, err_rc);
535
536         cYAML_free_tree(err_rc);
537
538         return rc;
539 }
540
541 static int jt_del_net(int argc, char **argv)
542 {
543         char *network = NULL;
544         struct cYAML *err_rc = NULL;
545         int rc, opt;
546
547         const char *const short_options = "n:h";
548         const struct option long_options[] = {
549                 { "net", 1, NULL, 'n' },
550                 { "help", 0, NULL, 'h' },
551                 { NULL, 0, NULL, 0 },
552         };
553
554         while ((opt = getopt_long(argc, argv, short_options,
555                                    long_options, NULL)) != -1) {
556                 switch (opt) {
557                 case 'n':
558                         network = optarg;
559                         break;
560                 case 'h':
561                         print_help(net_cmds, "net", "del");
562                         return 0;
563                 default:
564                         return 0;
565                 }
566         }
567
568         rc = lustre_lnet_del_net(network, -1, &err_rc);
569
570         if (rc != LUSTRE_CFG_RC_NO_ERR)
571                 cYAML_print_tree2file(stderr, err_rc);
572
573         cYAML_free_tree(err_rc);
574
575         return rc;
576 }
577
578 static int jt_show_route(int argc, char **argv)
579 {
580         char *network = NULL, *gateway = NULL;
581         long int hop = -1, prio = -1;
582         int detail = 0, rc, opt;
583         struct cYAML *err_rc = NULL, *show_rc = NULL;
584
585         const char *const short_options = "n:g:h:p:vh";
586         const struct option long_options[] = {
587                 { "net", 1, NULL, 'n' },
588                 { "gateway", 1, NULL, 'g' },
589                 { "hop-count", 1, NULL, 'c' },
590                 { "priority", 1, NULL, 'p' },
591                 { "verbose", 0, NULL, 'v' },
592                 { "help", 0, NULL, 'h' },
593                 { NULL, 0, NULL, 0 },
594         };
595
596         while ((opt = getopt_long(argc, argv, short_options,
597                                    long_options, NULL)) != -1) {
598                 switch (opt) {
599                 case 'n':
600                         network = optarg;
601                         break;
602                 case 'g':
603                         gateway = optarg;
604                         break;
605                 case 'c':
606                         rc = parse_long(optarg, &hop);
607                         if (rc != 0) {
608                                 /* ignore option */
609                                 hop = -1;
610                                 continue;
611                         }
612                         break;
613                 case 'p':
614                         rc = parse_long(optarg, &prio);
615                         if (rc != 0) {
616                                 /* ignore option */
617                                 prio = -1;
618                                 continue;
619                         }
620                         break;
621                 case 'v':
622                         detail = 1;
623                         break;
624                 case 'h':
625                         print_help(route_cmds, "route", "show");
626                         return 0;
627                 default:
628                         return 0;
629                 }
630         }
631
632         rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
633                                     &show_rc, &err_rc);
634
635         if (rc != LUSTRE_CFG_RC_NO_ERR)
636                 cYAML_print_tree2file(stderr, err_rc);
637         else if (show_rc)
638                 cYAML_print_tree(show_rc);
639
640         cYAML_free_tree(err_rc);
641         cYAML_free_tree(show_rc);
642
643         return rc;
644 }
645
646 static int jt_show_net(int argc, char **argv)
647 {
648         char *network = NULL;
649         int detail = 0, rc, opt;
650         struct cYAML *err_rc = NULL, *show_rc = NULL;
651
652         const char *const short_options = "n:vh";
653         const struct option long_options[] = {
654                 { "net", 1, NULL, 'n' },
655                 { "verbose", 0, NULL, 'v' },
656                 { "help", 0, NULL, 'h' },
657                 { NULL, 0, NULL, 0 },
658         };
659
660         while ((opt = getopt_long(argc, argv, short_options,
661                                    long_options, NULL)) != -1) {
662                 switch (opt) {
663                 case 'n':
664                         network = optarg;
665                         break;
666                 case 'v':
667                         detail = 1;
668                         break;
669                 case 'h':
670                         print_help(net_cmds, "net", "show");
671                         return 0;
672                 default:
673                         return 0;
674                 }
675         }
676
677         rc = lustre_lnet_show_net(network, detail, -1, &show_rc, &err_rc);
678
679         if (rc != LUSTRE_CFG_RC_NO_ERR)
680                 cYAML_print_tree2file(stderr, err_rc);
681         else if (show_rc)
682                 cYAML_print_tree(show_rc);
683
684         cYAML_free_tree(err_rc);
685         cYAML_free_tree(show_rc);
686
687         return rc;
688 }
689
690 static int jt_show_routing(int argc, char **argv)
691 {
692         struct cYAML *err_rc = NULL, *show_rc = NULL;
693         int rc;
694
695         if (handle_help(routing_cmds, "routing", "show", argc, argv) == 0)
696                 return 0;
697
698         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc);
699
700         if (rc != LUSTRE_CFG_RC_NO_ERR)
701                 cYAML_print_tree2file(stderr, err_rc);
702         else if (show_rc)
703                 cYAML_print_tree(show_rc);
704
705         cYAML_free_tree(err_rc);
706         cYAML_free_tree(show_rc);
707
708         return rc;
709 }
710
711 static int jt_show_stats(int argc, char **argv)
712 {
713         int rc;
714         struct cYAML *show_rc = NULL, *err_rc = NULL;
715
716         if (handle_help(stats_cmds, "stats", "show", argc, argv) == 0)
717                 return 0;
718
719         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
720
721         if (rc != LUSTRE_CFG_RC_NO_ERR)
722                 cYAML_print_tree2file(stderr, err_rc);
723         else if (show_rc)
724                 cYAML_print_tree(show_rc);
725
726         cYAML_free_tree(err_rc);
727         cYAML_free_tree(show_rc);
728
729         return rc;
730 }
731
732 static int jt_show_peer_credits(int argc, char **argv)
733 {
734         int rc;
735         struct cYAML *show_rc = NULL, *err_rc = NULL;
736
737         if (handle_help(credits_cmds, "peer_credits", "show", argc, argv) == 0)
738                 return 0;
739
740         rc = lustre_lnet_show_peer_credits(-1, &show_rc, &err_rc);
741
742         if (rc != LUSTRE_CFG_RC_NO_ERR)
743                 cYAML_print_tree2file(stderr, err_rc);
744         else if (show_rc)
745                 cYAML_print_tree(show_rc);
746
747         cYAML_free_tree(err_rc);
748         cYAML_free_tree(show_rc);
749
750         return rc;
751 }
752
753 static inline int jt_lnet(int argc, char **argv)
754 {
755         if (argc < 2)
756                 return CMD_HELP;
757
758         if (argc == 2 &&
759             handle_help(lnet_cmds, "lnet", NULL, argc, argv) == 0)
760                 return 0;
761
762         return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
763 }
764
765 static inline int jt_route(int argc, char **argv)
766 {
767         if (argc < 2)
768                 return CMD_HELP;
769
770         if (argc == 2 &&
771             handle_help(route_cmds, "route", NULL, argc, argv) == 0)
772                 return 0;
773
774         return Parser_execarg(argc - 1, &argv[1], route_cmds);
775 }
776
777 static inline int jt_net(int argc, char **argv)
778 {
779         if (argc < 2)
780                 return CMD_HELP;
781
782         if (argc == 2 &&
783             handle_help(net_cmds, "net", NULL, argc, argv) == 0)
784                 return 0;
785
786         return Parser_execarg(argc - 1, &argv[1], net_cmds);
787 }
788
789 static inline int jt_routing(int argc, char **argv)
790 {
791         if (argc < 2)
792                 return CMD_HELP;
793
794         if (argc == 2 &&
795             handle_help(routing_cmds, "routing", NULL, argc, argv) == 0)
796                 return 0;
797
798         return Parser_execarg(argc - 1, &argv[1], routing_cmds);
799 }
800
801 static inline int jt_stats(int argc, char **argv)
802 {
803         if (argc < 2)
804                 return CMD_HELP;
805
806         if (argc == 2 &&
807             handle_help(stats_cmds, "stats", NULL, argc, argv) == 0)
808                 return 0;
809
810         return Parser_execarg(argc - 1, &argv[1], stats_cmds);
811 }
812
813 static inline int jt_peer_credits(int argc, char **argv)
814 {
815         if (argc < 2)
816                 return CMD_HELP;
817
818         if (argc == 2 &&
819             handle_help(credits_cmds, "peer_credits", NULL, argc, argv) == 0)
820                 return 0;
821
822         return Parser_execarg(argc - 1, &argv[1], credits_cmds);
823 }
824
825 static inline int jt_set(int argc, char **argv)
826 {
827         if (argc < 2)
828                 return CMD_HELP;
829
830         if (argc == 2  &&
831             handle_help(set_cmds, "set", NULL, argc, argv) == 0)
832                 return 0;
833
834         return Parser_execarg(argc - 1, &argv[1], set_cmds);
835 }
836
837 static int jt_import(int argc, char **argv)
838 {
839         char *file = NULL;
840         struct cYAML *err_rc = NULL;
841         struct cYAML *show_rc = NULL;
842         int rc = 0, opt, opt_found = 0;
843         char cmd = 'a';
844
845         const char *const short_options = "adsh";
846         const struct option long_options[] = {
847                 { "add", 0, NULL, 'a' },
848                 { "del", 0, NULL, 'd' },
849                 { "show", 0, NULL, 's' },
850                 { "help", 0, NULL, 'h' },
851                 { NULL, 0, NULL, 0 },
852         };
853
854         while ((opt = getopt_long(argc, argv, short_options,
855                                    long_options, NULL)) != -1) {
856                 opt_found = 1;
857                 switch (opt) {
858                 case 'a':
859                 case 'd':
860                 case 's':
861                         cmd = opt;
862                         break;
863                 case 'h':
864                         printf("import FILE\n"
865                                "import < FILE : import a file\n"
866                                "\t--add: add configuration\n"
867                                "\t--del: delete configuration\n"
868                                "\t--show: show configuration\n"
869                                "\t--help: display this help\n"
870                                "If no command option is given then --add"
871                                " is assumed by default\n");
872                         return 0;
873                 default:
874                         return 0;
875                 }
876         }
877
878         /* grab the file name if one exists */
879         if (opt_found && argc == 3)
880                 file = argv[2];
881         else if (!opt_found && argc == 2)
882                 file = argv[1];
883
884         switch (cmd) {
885         case 'a':
886                 rc = lustre_yaml_config(file, &err_rc);
887                 break;
888         case 'd':
889                 rc = lustre_yaml_del(file, &err_rc);
890                 break;
891         case 's':
892                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
893                 cYAML_print_tree(show_rc);
894                 cYAML_free_tree(show_rc);
895                 break;
896         }
897
898         if (rc != LUSTRE_CFG_RC_NO_ERR)
899                 cYAML_print_tree2file(stderr, err_rc);
900
901         cYAML_free_tree(err_rc);
902
903         return rc;
904 }
905
906 static int jt_export(int argc, char **argv)
907 {
908         struct cYAML *show_rc = NULL;
909         struct cYAML *err_rc = NULL;
910         int rc, opt;
911         FILE *f = NULL;
912
913         const char *const short_options = "h";
914         const struct option long_options[] = {
915                 { "help", 0, NULL, 'h' },
916                 { NULL, 0, NULL, 0 },
917         };
918
919         while ((opt = getopt_long(argc, argv, short_options,
920                                    long_options, NULL)) != -1) {
921                 switch (opt) {
922                 case 'h':
923                         printf("export FILE\n"
924                                "export > FILE : export configuration\n"
925                                "\t--help: display this help\n");
926                         return 0;
927                 default:
928                         return 0;
929                 }
930         }
931
932         if (argc >= 2) {
933                 f = fopen(argv[1], "w");
934                 if (f == NULL)
935                         return -1;
936         } else
937                 f = stdout;
938
939         rc = lustre_lnet_show_net(NULL, 1, -1, &show_rc, &err_rc);
940         if (rc != LUSTRE_CFG_RC_NO_ERR) {
941                 cYAML_print_tree2file(stderr, err_rc);
942                 cYAML_free_tree(err_rc);
943         }
944
945         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
946                                     &err_rc);
947         if (rc != LUSTRE_CFG_RC_NO_ERR) {
948                 cYAML_print_tree2file(stderr, err_rc);
949                 cYAML_free_tree(err_rc);
950         }
951
952         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc);
953         if (rc != LUSTRE_CFG_RC_NO_ERR) {
954                 cYAML_print_tree2file(stderr, err_rc);
955                 cYAML_free_tree(err_rc);
956         }
957
958         if (show_rc != NULL) {
959                 cYAML_print_tree2file(f, show_rc);
960                 cYAML_free_tree(show_rc);
961         }
962
963         if (argc >= 2)
964                 fclose(f);
965
966         return 0;
967 }
968
969 command_t list[] = {
970         {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
971         {"route", jt_route, 0, "route {add | del | show | help}"},
972         {"net", jt_net, 0, "net {add | del | show | help}"},
973         {"routing", jt_routing, 0, "routing {show | help}"},
974         {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
975                            " | routing}"},
976         {"import", jt_import, 0, "import {--add | --del | --show | "
977                                  "--help} FILE.yaml"},
978         {"export", jt_export, 0, "export {--help} FILE.yaml"},
979         {"stats", jt_stats, 0, "stats {show | help}"},
980         {"peer_credits", jt_peer_credits, 0, "peer_credits {show | help}"},
981         {"help", Parser_help, 0, "help"},
982         {"exit", Parser_quit, 0, "quit"},
983         {"quit", Parser_quit, 0, "quit"},
984         { 0, 0, 0, NULL }
985 };
986
987 int main(int argc, char **argv)
988 {
989         int rc = 0;
990         struct cYAML *err_rc = NULL;
991
992         rc = lustre_lnet_config_lib_init();
993         if (rc < 0) {
994                 cYAML_build_error(-1, -1, "lnetctl", "startup",
995                                   "cannot register LNet device", &err_rc);
996                 cYAML_print_tree2file(stderr, err_rc);
997                 return rc;
998         }
999
1000         Parser_init("lnetctl > ", list);
1001         if (argc > 1) {
1002                 rc = Parser_execarg(argc - 1, &argv[1], list);
1003                 goto errorout;
1004         }
1005
1006         Parser_commands();
1007
1008 errorout:
1009         return rc;
1010 }