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