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