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