Whamcloud - gitweb
2ee019f7a5f5cf6370c0589967b4c71efe67e126
[fs/lustre-release.git] / lnet / utils / lnetctl.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of the
9  * License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * LGPL HEADER END
20  *
21  * Copyright (c) 2014, 2017, Intel Corporation.
22  *
23  * Author:
24  *   Amir Shehata <amir.shehata@intel.com>
25  */
26 #include <getopt.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <libcfs/util/ioctl.h>
32 #include <libcfs/util/parser.h>
33 #include "lnetconfig/cyaml.h"
34 #include "lnetconfig/liblnetconfig.h"
35
36 #define LNET_CONFIGURE          true
37 #define LNET_UNCONFIGURE        false
38
39 static int jt_config_lnet(int argc, char **argv);
40 static int jt_unconfig_lnet(int argc, char **argv);
41 static int jt_add_route(int argc, char **argv);
42 static int jt_add_ni(int argc, char **argv);
43 static int jt_set_routing(int argc, char **argv);
44 static int jt_del_route(int argc, char **argv);
45 static int jt_del_ni(int argc, char **argv);
46 static int jt_show_route(int argc, char **argv);
47 static int jt_show_net(int argc, char **argv);
48 static int jt_show_routing(int argc, char **argv);
49 static int jt_show_stats(int argc, char **argv);
50 static int jt_show_peer(int argc, char **argv);
51 static int jt_show_recovery(int argc, char **argv);
52 static int jt_show_global(int argc, char **argv);
53 static int jt_show_udsp(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_set_retry_count(int argc, char **argv);
59 static int jt_set_transaction_to(int argc, char **argv);
60 static int jt_set_recov_intrv(int argc, char **argv);
61 static int jt_set_rtr_sensitivity(int argc, char **argv);
62 static int jt_set_hsensitivity(int argc, char **argv);
63 static int jt_set_max_recovery_ping_interval(int argc, char **argv);
64 static int jt_reset_stats(int argc, char **argv);
65 static int jt_add_peer_nid(int argc, char **argv);
66 static int jt_del_peer_nid(int argc, char **argv);
67 static int jt_set_max_intf(int argc, char **argv);
68 static int jt_set_discovery(int argc, char **argv);
69 static int jt_set_drop_asym_route(int argc, char **argv);
70 static int jt_list_peer(int argc, char **argv);
71 static int jt_add_udsp(int argc, char **argv);
72 static int jt_del_udsp(int argc, char **argv);
73 /*static int jt_show_peer(int argc, char **argv);*/
74 static int lnetctl_list_commands(int argc, char **argv);
75 static int jt_import(int argc, char **argv);
76 static int jt_export(int argc, char **argv);
77 static int jt_ping(int argc, char **argv);
78 static int jt_discover(int argc, char **argv);
79 static int jt_lnet(int argc, char **argv);
80 static int jt_route(int argc, char **argv);
81 static int jt_net(int argc, char **argv);
82 static int jt_routing(int argc, char **argv);
83 static int jt_set(int argc, char **argv);
84 static int jt_debug(int argc, char **argv);
85 static int jt_stats(int argc, char **argv);
86 static int jt_global(int argc, char **argv);
87 static int jt_peers(int argc, char **argv);
88 static int jt_set_ni_value(int argc, char **argv);
89 static int jt_set_peer_ni_value(int argc, char **argv);
90 static int jt_calc_service_id(int argc, char **argv);
91 static int jt_set_response_tracking(int argc, char **argv);
92 static int jt_set_recovery_limit(int argc, char **argv);
93 static int jt_udsp(int argc, char **argv);
94 static int jt_setup_mrrouting(int argc, char **argv);
95 static int jt_calc_cpt_of_nid(int argc, char **argv);
96 static int jt_show_peer_debug_info(int argc, char **argv);
97
98 command_t cmd_list[] = {
99         {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
100         {"route", jt_route, 0, "route {add | del | show | help}"},
101         {"net", jt_net, 0, "net {add | del | show | set | help}"},
102         {"routing", jt_routing, 0, "routing {show | help}"},
103         {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
104                            " | routing | numa_range | max_interfaces"
105                            " | discovery | drop_asym_route | retry_count"
106                            " | transaction_timeout | health_sensitivity"
107                            " | recovery_interval | router_sensitivity"
108                            " | response_tracking | recovery_limit}"},
109         {"import", jt_import, 0, "import FILE.yaml"},
110         {"export", jt_export, 0, "export FILE.yaml"},
111         {"stats", jt_stats, 0, "stats {show | help}"},
112         {"debug", jt_debug, 0, "debug {recovery {local | peer} | peer}"},
113         {"global", jt_global, 0, "global {show | help}"},
114         {"peer", jt_peers, 0, "peer {add | del | show | list | set | help}"},
115         {"ping", jt_ping, 0, "ping nid,[nid,...]"},
116         {"discover", jt_discover, 0, "discover nid[,nid,...]"},
117         {"service-id", jt_calc_service_id, 0, "Calculate IB Lustre service ID\n"},
118         {"udsp", jt_udsp, 0, "udsp {add | del | help}"},
119         {"setup-mrrouting", jt_setup_mrrouting, 0,
120          "setup linux routing tables\n"},
121         {"cpt-of-nid", jt_calc_cpt_of_nid, 0, "Calculate the CPT associated with NID\n"
122          "\t--nid: NID to calculate the CPT of\n"
123          "\t--ncpt: Number of CPTs to consider in the calculation\n"},
124         {"help", Parser_help, 0, "help"},
125         {"exit", Parser_quit, 0, "quit"},
126         {"quit", Parser_quit, 0, "quit"},
127         {"--list-commands", lnetctl_list_commands, 0, "list commands"},
128         { 0, 0, 0, NULL }
129 };
130
131 command_t lnet_cmds[] = {
132         {"configure", jt_config_lnet, 0, "configure lnet\n"
133          "\t--all: load NI configuration from module parameters\n"},
134         {"unconfigure", jt_unconfig_lnet, 0, "unconfigure lnet\n"},
135         { 0, 0, 0, NULL }
136 };
137
138 command_t route_cmds[] = {
139         {"add", jt_add_route, 0, "add a route\n"
140          "\t--net: net name (e.g. tcp0)\n"
141          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
142          "\t--hop: number to final destination (1 < hops < 255)\n"
143          "\t--priority: priority of route (0 - highest prio\n"
144          "\t--health_sensitivity: gateway health sensitivity (>= 1)\n"},
145         {"del", jt_del_route, 0, "delete a route\n"
146          "\t--net: net name (e.g. tcp0)\n"
147          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"},
148         {"show", jt_show_route, 0, "show routes\n"
149          "\t--net: net name (e.g. tcp0) to filter on\n"
150          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
151          "\t--hop: number to final destination (1 < hops < 255) to filter on\n"
152          "\t--priority: priority of route (0 - highest prio to filter on\n"
153          "\t--health_sensitivity: gateway health sensitivity (>= 1)\n"
154          "\t--verbose: display detailed output per route\n"},
155         { 0, 0, 0, NULL }
156 };
157
158 command_t net_cmds[] = {
159         {"add", jt_add_ni, 0, "add a network\n"
160          "\t--net: net name (e.g. tcp0)\n"
161          "\t--if: physical interface (e.g. eth0)\n"
162          "\t--ip2net: specify networks based on IP address patterns\n"
163          "\t--peer-timeout: time to wait before declaring a peer dead\n"
164          "\t--peer-credits: define the max number of inflight messages\n"
165          "\t--peer-buffer-credits: the number of buffer credits per peer\n"
166          "\t--credits: Network Interface credits\n"
167          "\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"
168          "\t--conns-per-peer: number of connections per peer\n"
169          "\t--skip-mr-route-setup: do not add linux route for the ni\n"
170          "\t--auth-key: Network authorization key (kfilnd only)\n"},
171         {"del", jt_del_ni, 0, "delete a network\n"
172          "\t--net: net name (e.g. tcp0)\n"
173          "\t--if: physical interface (e.g. eth0)\n"},
174         {"show", jt_show_net, 0, "show networks\n"
175          "\t--net: net name (e.g. tcp0) to filter on\n"
176          "\t--verbose: display detailed output per network."
177                        " Optional argument of '2' outputs more stats\n"},
178         {"set", jt_set_ni_value, 0, "set local NI specific parameter\n"
179          "\t--nid: NI NID to set the\n"
180          "\t--health: specify health value to set\n"
181          "\t--conns-per-peer: number of connections per peer\n"
182          "\t--all: set all NIs value to the one specified\n"},
183         { 0, 0, 0, NULL }
184 };
185
186 command_t routing_cmds[] = {
187         {"show", jt_show_routing, 0, "show routing information\n"},
188         { 0, 0, 0, NULL }
189 };
190
191 command_t stats_cmds[] = {
192         {"show", jt_show_stats, 0, "show LNET statistics\n"},
193         {"reset", jt_reset_stats, 0, "reset LNET statistics\n"},
194         { 0, 0, 0, NULL }
195 };
196
197 command_t debug_cmds[] = {
198         {"recovery", jt_show_recovery, 0, "list recovery queues\n"
199                 "\t--local : list local recovery queue\n"
200                 "\t--peer : list peer recovery queue\n"},
201         {"peer", jt_show_peer_debug_info, 0, "show peer debug info\n"
202                 "\t--nid: peer's NID\n"},
203         { 0, 0, 0, NULL }
204 };
205
206 command_t global_cmds[] = {
207         {"show", jt_show_global, 0, "show global variables\n"},
208         { 0, 0, 0, NULL }
209 };
210
211 command_t set_cmds[] = {
212         {"tiny_buffers", jt_set_tiny, 0, "set tiny routing buffers\n"
213          "\tVALUE must be greater than 0\n"},
214         {"small_buffers", jt_set_small, 0, "set small routing buffers\n"
215          "\tVALUE must be greater than 0\n"},
216         {"large_buffers", jt_set_large, 0, "set large routing buffers\n"
217          "\tVALUE must be greater than 0\n"},
218         {"routing", jt_set_routing, 0, "enable/disable routing\n"
219          "\t0 - disable routing\n"
220          "\t1 - enable routing\n"},
221         {"numa_range", jt_set_numa, 0, "set NUMA range for NI selection\n"
222          "\tVALUE must be at least 0\n"},
223         {"max_interfaces", jt_set_max_intf, 0, "set the default value for "
224                 "max interfaces\n"
225          "\tValue must be greater than 16\n"},
226         {"discovery", jt_set_discovery, 0, "enable/disable peer discovery\n"
227          "\t0 - disable peer discovery\n"
228          "\t1 - enable peer discovery (default)\n"},
229         {"drop_asym_route", jt_set_drop_asym_route, 0,
230          "drop/accept asymmetrical route messages\n"
231          "\t0 - accept asymmetrical route messages (default)\n"
232          "\t1 - drop asymmetrical route messages\n"},
233         {"retry_count", jt_set_retry_count, 0, "number of retries\n"
234          "\t0 - turn of retries\n"
235          "\t>0 - number of retries\n"},
236         {"transaction_timeout", jt_set_transaction_to, 0, "Message/Response timeout\n"
237          "\t>0 - timeout in seconds\n"},
238         {"health_sensitivity", jt_set_hsensitivity, 0, "sensitivity to failure\n"
239          "\t0 - turn off health evaluation\n"
240          "\t>0 - sensitivity value not more than 1000\n"},
241         {"recovery_interval", jt_set_recov_intrv, 0, "interval to ping in seconds (at least 1)\n"
242          "\t>0 - time in seconds between pings\n"},
243         {"router_sensitivity", jt_set_rtr_sensitivity, 0, "router sensitivity %\n"
244          "\t100 - router interfaces need to be fully healthy to be used\n"
245          "\t<100 - router interfaces can be used even if not healthy\n"},
246         {"response_tracking", jt_set_response_tracking, 0,
247          "Set the behavior of response tracking\n"
248          "\t0 - Only LNet pings and discovery pushes utilize response tracking\n"
249          "\t1 - GETs are eligible for response tracking\n"
250          "\t2 - PUTs are eligible for response tracking\n"
251          "\t3 - Both PUTs and GETs are eligible for response tracking (default)\n"
252          "\tNote: Regardless of the value of the response_tracking parameter LNet\n"
253          "\t      pings and discovery pushes always utilize response tracking\n"},
254         {"recovery_limit", jt_set_recovery_limit, 0,
255          "Set how long LNet will attempt to recover unhealthy interfaces.\n"
256          "\t0 - Recover indefinitely (default)\n"
257          "\t>0 - Recover for the specified number of seconds.\n"},
258         {"max_recovery_ping_interval", jt_set_max_recovery_ping_interval, 0,
259          "maximum recovery ping interval\n"
260          "\t>0 - maximum recovery ping interval in seconds\n"},
261         { 0, 0, 0, NULL }
262 };
263
264 command_t peer_cmds[] = {
265         {"add", jt_add_peer_nid, 0, "add a peer NID\n"
266          "\t--prim_nid: Primary NID of the peer.\n"
267          "\t--nid: one or more peer NIDs\n"
268          "\t--non_mr: create this peer as not Multi-Rail capable\n"
269          "\t--ip2nets: specify a range of nids per peer"},
270         {"del", jt_del_peer_nid, 0, "delete a peer NID\n"
271          "\t--prim_nid: Primary NID of the peer.\n"
272          "\t--nid: list of NIDs to remove. If none provided,\n"
273          "\t       peer is deleted\n"
274          "\t--ip2nets: specify a range of nids per peer"},
275         {"show", jt_show_peer, 0, "show peer information\n"
276          "\t--nid: NID of peer to filter on.\n"
277          "\t--verbose: display detailed output per peer."
278                        " Optional argument of '2' outputs more stats\n"},
279         {"list", jt_list_peer, 0, "list all peers\n"},
280         {"set", jt_set_peer_ni_value, 0, "set peer ni specific parameter\n"
281          "\t--nid: Peer NI NID to set the\n"
282          "\t--health: specify health value to set\n"
283          "\t--all: set all peer_nis values to the one specified\n"},
284         { 0, 0, 0, NULL }
285 };
286
287 command_t udsp_cmds[] = {
288         {"add", jt_add_udsp, 0, "add a udsp\n"
289          "\t--src: ip2nets syntax specifying the local NID to match\n"
290          "\t--dst: ip2nets syntax specifying the remote NID to match\n"
291          "\t--rte: ip2nets syntax specifying the router NID to match\n"
292          "\t--priority: priority value (0 - highest priority)\n"
293          "\t--idx: index of where to insert the rule.\n"
294          "\t       By default, appends to the end of the rule list.\n"},
295         {"del", jt_del_udsp, 0, "delete a udsp\n"
296         "\t--idx: index of the Policy.\n"},
297         {"show", jt_show_udsp, 0, "show udsps\n"
298          "\t --idx: index of the policy to show.\n"},
299         { 0, 0, 0, NULL }
300 };
301
302 static int parse_long(const char *number, long int *value)
303 {
304         char *end;
305
306         if (!number)
307                 return -1;
308
309         *value = strtol(number,  &end, 0);
310         if (end != NULL && *end != 0)
311                 return -1;
312
313         return 0;
314 }
315
316 static int jt_setup_mrrouting(int argc, char **argv)
317 {
318         int rc;
319         struct cYAML *err_rc = NULL;
320
321         rc = lustre_lnet_setup_mrrouting(&err_rc);
322
323         if (rc != LUSTRE_CFG_RC_NO_ERR)
324                 cYAML_print_tree2file(stderr, err_rc);
325
326         cYAML_free_tree(err_rc);
327
328         return rc;
329 }
330
331 static inline void print_help(const command_t cmds[], const char *cmd_type,
332                               const char *pc_name)
333 {
334         const command_t *cmd;
335
336         for (cmd = cmds; cmd->pc_name; cmd++) {
337                 if (pc_name != NULL &&
338                     strcmp(cmd->pc_name, pc_name) == 0) {
339                         printf("%s %s: %s\n", cmd_type, cmd->pc_name,
340                                cmd->pc_help);
341                         return;
342                 } else if (pc_name != NULL) {
343                         continue;
344                 }
345                 printf("%s %s: %s\n", cmd_type, cmd->pc_name, cmd->pc_help);
346         }
347 }
348
349 static int check_cmd(const command_t *cmd_list, const char *cmd,
350                      const char *sub_cmd, const int min_args,
351                      int argc, char **argv)
352 {
353         int opt;
354         int rc = 0;
355         optind = 0;
356         opterr = 0;
357
358         const char *const short_options = "h";
359         static const struct option long_options[] = {
360                 { .name = "help", .has_arg = no_argument, .val = 'h' },
361                 { .name = NULL }
362         };
363
364         if (argc < min_args) {
365                 print_help(cmd_list, cmd, sub_cmd);
366                 rc = -1;
367                 goto out;
368         } else if (argc > 2) {
369                 return 0;
370         }
371
372         while ((opt = getopt_long(argc, argv, short_options,
373                                   long_options, NULL)) != -1) {
374                 switch (opt) {
375                 case 'h':
376                         print_help(cmd_list, cmd, sub_cmd);
377                         rc = 1;
378                         break;
379                 default:
380                         rc = 0;
381                         break;
382                 }
383         }
384
385 out:
386         opterr = 1;
387         optind = 0;
388         return rc;
389 }
390
391 static int jt_set_response_tracking(int argc, char **argv)
392 {
393         long int value;
394         int rc;
395         struct cYAML *err_rc = NULL;
396
397         rc = check_cmd(set_cmds, "set", "response_tracking", 2, argc, argv);
398         if (rc)
399                 return rc;
400
401         rc = parse_long(argv[1], &value);
402         if (rc != 0) {
403                 cYAML_build_error(-1, -1, "parser", "set",
404                                   "cannot parse response_tracking value",
405                                   &err_rc);
406                 cYAML_print_tree2file(stderr, err_rc);
407                 cYAML_free_tree(err_rc);
408                 return -1;
409         }
410
411         rc = lustre_lnet_config_response_tracking(value, -1, &err_rc);
412         if (rc != LUSTRE_CFG_RC_NO_ERR)
413                 cYAML_print_tree2file(stderr, err_rc);
414
415         cYAML_free_tree(err_rc);
416
417         return rc;
418 }
419
420 static int jt_calc_service_id(int argc, char **argv)
421 {
422         int rc;
423         __u64 service_id;
424
425         rc = lustre_lnet_calc_service_id(&service_id);
426         if (rc != LUSTRE_CFG_RC_NO_ERR)
427                 return rc;
428
429         /* cYAML currently doesn't support printing hex values.
430          * Therefore just print it locally here
431          */
432         printf("service_id:\n    value: 0x%llx\n",
433                (unsigned long long)(service_id));
434
435         return rc;
436 }
437
438 static int jt_calc_cpt_of_nid(int argc, char **argv)
439 {
440         int rc, opt;
441         int cpt;
442         long int ncpts = -1;
443         char *nid = NULL;
444         struct cYAML *err_rc = NULL;
445         const char *const short_options = "n:c:h";
446         static const struct option long_options[] = {
447         { .name = "nid",       .has_arg = required_argument, .val = 'n' },
448         { .name = "ncpt",     .has_arg = required_argument, .val = 'c' },
449         { .name = NULL } };
450
451         rc = check_cmd(cmd_list, "", "cpt-of-nid", 0, argc, argv);
452         if (rc)
453                 return rc;
454
455         while ((opt = getopt_long(argc, argv, short_options,
456                                    long_options, NULL)) != -1) {
457                 switch (opt) {
458                 case 'n':
459                         nid = optarg;
460                         break;
461                 case 'c':
462                         rc = parse_long(optarg, &ncpts);
463                         if (rc != 0) {
464                                 cYAML_build_error(-1, -1, "cpt", "get",
465                                                 "cannot parse input", &err_rc);
466                                 cYAML_print_tree2file(stderr, err_rc);
467                                 cYAML_free_tree(err_rc);
468                                 return -1;
469                         }
470                         break;
471                 case '?':
472                         print_help(cmd_list, "", "cpt-of-nid");
473                 default:
474                         return 0;
475                 }
476         }
477
478         cpt = lustre_lnet_calc_cpt_of_nid(nid, ncpts);
479         if (cpt < 0)
480                 return -1;
481
482         printf("cpt:\n    value: %d\n", cpt);
483
484         return 0;
485 }
486
487 static int jt_set_recovery_limit(int argc, char **argv)
488 {
489         long int value;
490         int rc;
491         struct cYAML *err_rc = NULL;
492
493         rc = check_cmd(set_cmds, "set", "recovery_limit", 2, argc, argv);
494         if (rc)
495                 return rc;
496
497         rc = parse_long(argv[1], &value);
498         if (rc != 0) {
499                 cYAML_build_error(-1, -1, "parser", "set",
500                                   "cannot parse recovery_limit value",
501                                   &err_rc);
502                 cYAML_print_tree2file(stderr, err_rc);
503                 cYAML_free_tree(err_rc);
504                 return -1;
505         }
506
507         rc = lustre_lnet_config_recovery_limit(value, -1, &err_rc);
508         if (rc != LUSTRE_CFG_RC_NO_ERR)
509                 cYAML_print_tree2file(stderr, err_rc);
510
511         cYAML_free_tree(err_rc);
512
513         return rc;
514 }
515
516 static int jt_set_max_intf(int argc, char **argv)
517 {
518         long int value;
519         int rc;
520         struct cYAML *err_rc = NULL;
521
522         rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
523         if (rc)
524                 return rc;
525
526         rc = parse_long(argv[1], &value);
527         if (rc != 0) {
528                 cYAML_build_error(-1, -1, "parser", "set",
529                                   "cannot parse max_interfaces value", &err_rc);
530                 cYAML_print_tree2file(stderr, err_rc);
531                 cYAML_free_tree(err_rc);
532                 return -1;
533         }
534
535         rc = lustre_lnet_config_max_intf(value, -1, &err_rc);
536         if (rc != LUSTRE_CFG_RC_NO_ERR)
537                 cYAML_print_tree2file(stderr, err_rc);
538
539         cYAML_free_tree(err_rc);
540
541         return rc;
542 }
543
544 static int jt_set_numa(int argc, char **argv)
545 {
546         long int value;
547         int rc;
548         struct cYAML *err_rc = NULL;
549
550         rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
551         if (rc)
552                 return rc;
553
554         rc = parse_long(argv[1], &value);
555         if (rc != 0) {
556                 cYAML_build_error(-1, -1, "parser", "set",
557                                   "cannot parse numa_range value", &err_rc);
558                 cYAML_print_tree2file(stderr, err_rc);
559                 cYAML_free_tree(err_rc);
560                 return -1;
561         }
562
563         rc = lustre_lnet_config_numa_range(value, -1, &err_rc);
564         if (rc != LUSTRE_CFG_RC_NO_ERR)
565                 cYAML_print_tree2file(stderr, err_rc);
566
567         cYAML_free_tree(err_rc);
568
569         return rc;
570 }
571
572 static int jt_set_recov_intrv(int argc, char **argv)
573 {
574         long int value;
575         int rc;
576         struct cYAML *err_rc = NULL;
577
578         rc = check_cmd(set_cmds, "set", "recovery_interval", 2, argc, argv);
579         if (rc)
580                 return rc;
581
582         rc = parse_long(argv[1], &value);
583         if (rc != 0) {
584                 cYAML_build_error(-1, -1, "parser", "set",
585                                   "cannot parse recovery interval value", &err_rc);
586                 cYAML_print_tree2file(stderr, err_rc);
587                 cYAML_free_tree(err_rc);
588                 return -1;
589         }
590
591         rc = lustre_lnet_config_recov_intrv(value, -1, &err_rc);
592         if (rc != LUSTRE_CFG_RC_NO_ERR)
593                 cYAML_print_tree2file(stderr, err_rc);
594
595         cYAML_free_tree(err_rc);
596
597         return rc;
598 }
599
600 static int jt_set_rtr_sensitivity(int argc, char **argv)
601 {
602         long int value;
603         int rc;
604         struct cYAML *err_rc = NULL;
605
606         rc = check_cmd(set_cmds, "set", "router_sensitivity", 2, argc, argv);
607         if (rc)
608                 return rc;
609
610         rc = parse_long(argv[1], &value);
611         if (rc != 0) {
612                 cYAML_build_error(-1, -1, "parser", "set",
613                                   "cannot parse router sensitivity value", &err_rc);
614                 cYAML_print_tree2file(stderr, err_rc);
615                 cYAML_free_tree(err_rc);
616                 return -1;
617         }
618
619         rc = lustre_lnet_config_rtr_sensitivity(value, -1, &err_rc);
620         if (rc != LUSTRE_CFG_RC_NO_ERR)
621                 cYAML_print_tree2file(stderr, err_rc);
622
623         cYAML_free_tree(err_rc);
624
625         return rc;
626 }
627
628 static int jt_set_hsensitivity(int argc, char **argv)
629 {
630         long int value;
631         int rc;
632         struct cYAML *err_rc = NULL;
633
634         rc = check_cmd(set_cmds, "set", "health_sensitivity", 2, argc, argv);
635         if (rc)
636                 return rc;
637
638         rc = parse_long(argv[1], &value);
639         if (rc != 0) {
640                 cYAML_build_error(-1, -1, "parser", "set",
641                                   "cannot parse health sensitivity value", &err_rc);
642                 cYAML_print_tree2file(stderr, err_rc);
643                 cYAML_free_tree(err_rc);
644                 return -1;
645         }
646
647         rc = lustre_lnet_config_hsensitivity(value, -1, &err_rc);
648         if (rc != LUSTRE_CFG_RC_NO_ERR)
649                 cYAML_print_tree2file(stderr, err_rc);
650
651         cYAML_free_tree(err_rc);
652
653         return rc;
654 }
655
656 static int jt_reset_stats(int argc, char **argv)
657 {
658         int rc;
659         struct cYAML *err_rc = NULL;
660
661         rc = check_cmd(stats_cmds, "stats", "reset", 0, argc, argv);
662         if (rc)
663                 return rc;
664
665         rc = lustre_lnet_reset_stats(-1, &err_rc);
666         if (rc != LUSTRE_CFG_RC_NO_ERR)
667                 cYAML_print_tree2file(stderr, err_rc);
668
669         cYAML_free_tree(err_rc);
670
671         return rc;
672 }
673
674 static int jt_set_transaction_to(int argc, char **argv)
675 {
676         long int value;
677         int rc;
678         struct cYAML *err_rc = NULL;
679
680         rc = check_cmd(set_cmds, "set", "transaction_timeout", 2, argc, argv);
681         if (rc)
682                 return rc;
683
684         rc = parse_long(argv[1], &value);
685         if (rc != 0) {
686                 cYAML_build_error(-1, -1, "parser", "set",
687                                   "cannot parse transaction timeout value", &err_rc);
688                 cYAML_print_tree2file(stderr, err_rc);
689                 cYAML_free_tree(err_rc);
690                 return -1;
691         }
692
693         rc = lustre_lnet_config_transaction_to(value, -1, &err_rc);
694         if (rc != LUSTRE_CFG_RC_NO_ERR)
695                 cYAML_print_tree2file(stderr, err_rc);
696
697         cYAML_free_tree(err_rc);
698
699         return rc;
700 }
701
702 static int jt_set_retry_count(int argc, char **argv)
703 {
704         long int value;
705         int rc;
706         struct cYAML *err_rc = NULL;
707
708         rc = check_cmd(set_cmds, "set", "retry_count", 2, argc, argv);
709         if (rc)
710                 return rc;
711
712         rc = parse_long(argv[1], &value);
713         if (rc != 0) {
714                 cYAML_build_error(-1, -1, "parser", "set",
715                                   "cannot parse retry_count value", &err_rc);
716                 cYAML_print_tree2file(stderr, err_rc);
717                 cYAML_free_tree(err_rc);
718                 return -1;
719         }
720
721         rc = lustre_lnet_config_retry_count(value, -1, &err_rc);
722         if (rc != LUSTRE_CFG_RC_NO_ERR)
723                 cYAML_print_tree2file(stderr, err_rc);
724
725         cYAML_free_tree(err_rc);
726
727         return rc;
728 }
729
730 static int jt_set_discovery(int argc, char **argv)
731 {
732         long int value;
733         int rc;
734         struct cYAML *err_rc = NULL;
735
736         rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
737         if (rc)
738                 return rc;
739
740         rc = parse_long(argv[1], &value);
741         if (rc != 0) {
742                 cYAML_build_error(-1, -1, "parser", "set",
743                                   "cannot parse discovery value", &err_rc);
744                 cYAML_print_tree2file(stderr, err_rc);
745                 cYAML_free_tree(err_rc);
746                 return -1;
747         }
748
749         rc = lustre_lnet_config_discovery(value, -1, &err_rc);
750         if (rc != LUSTRE_CFG_RC_NO_ERR)
751                 cYAML_print_tree2file(stderr, err_rc);
752
753         cYAML_free_tree(err_rc);
754
755         return rc;
756 }
757
758 static int jt_set_drop_asym_route(int argc, char **argv)
759 {
760         long int value;
761         int rc;
762         struct cYAML *err_rc = NULL;
763
764         rc = check_cmd(set_cmds, "set", "drop_asym_route", 2, argc, argv);
765         if (rc)
766                 return rc;
767
768         rc = parse_long(argv[1], &value);
769         if (rc != 0) {
770                 cYAML_build_error(-1, -1, "parser", "set",
771                                   "cannot parse drop_asym_route value",
772                                   &err_rc);
773                 cYAML_print_tree2file(stderr, err_rc);
774                 cYAML_free_tree(err_rc);
775                 return -1;
776         }
777
778         rc = lustre_lnet_config_drop_asym_route(value, -1, &err_rc);
779         if (rc != LUSTRE_CFG_RC_NO_ERR)
780                 cYAML_print_tree2file(stderr, err_rc);
781
782         cYAML_free_tree(err_rc);
783
784         return rc;
785 }
786
787 static int jt_set_tiny(int argc, char **argv)
788 {
789         long int value;
790         int rc;
791         struct cYAML *err_rc = NULL;
792
793         rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
794         if (rc)
795                 return rc;
796
797         rc = parse_long(argv[1], &value);
798         if (rc != 0) {
799                 cYAML_build_error(-1, -1, "parser", "set",
800                                   "cannot parse tiny_buffers value", &err_rc);
801                 cYAML_print_tree2file(stderr, err_rc);
802                 cYAML_free_tree(err_rc);
803                 return -1;
804         }
805
806         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
807         if (rc != LUSTRE_CFG_RC_NO_ERR)
808                 cYAML_print_tree2file(stderr, err_rc);
809
810         cYAML_free_tree(err_rc);
811
812         return rc;
813 }
814
815 static int jt_set_small(int argc, char **argv)
816 {
817         long int value;
818         int rc;
819         struct cYAML *err_rc = NULL;
820
821         rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
822         if (rc)
823                 return rc;
824
825         rc = parse_long(argv[1], &value);
826         if (rc != 0) {
827                 cYAML_build_error(-1, -1, "parser", "set",
828                                   "cannot parse small_buffers value", &err_rc);
829                 cYAML_print_tree2file(stderr, err_rc);
830                 cYAML_free_tree(err_rc);
831                 return -1;
832         }
833
834         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
835         if (rc != LUSTRE_CFG_RC_NO_ERR)
836                 cYAML_print_tree2file(stderr, err_rc);
837
838         cYAML_free_tree(err_rc);
839
840         return rc;
841 }
842
843 static int jt_set_large(int argc, char **argv)
844 {
845         long int value;
846         int rc;
847         struct cYAML *err_rc = NULL;
848
849         rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
850         if (rc)
851                 return rc;
852
853         rc = parse_long(argv[1], &value);
854         if (rc != 0) {
855                 cYAML_build_error(-1, -1, "parser", "set",
856                                   "cannot parse large_buffers value", &err_rc);
857                 cYAML_print_tree2file(stderr, err_rc);
858                 cYAML_free_tree(err_rc);
859                 return -1;
860         }
861
862         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
863         if (rc != LUSTRE_CFG_RC_NO_ERR)
864                 cYAML_print_tree2file(stderr, err_rc);
865
866         cYAML_free_tree(err_rc);
867
868         return rc;
869 }
870
871 static int jt_set_routing(int argc, char **argv)
872 {
873         long int value;
874         struct cYAML *err_rc = NULL;
875         int rc;
876
877         rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
878         if (rc)
879                 return rc;
880
881         rc = parse_long(argv[1], &value);
882         if (rc != 0 || (value != 0 && value != 1)) {
883                 cYAML_build_error(-1, -1, "parser", "set",
884                                   "cannot parse routing value.\n"
885                                   "must be 0 for disable or 1 for enable",
886                                   &err_rc);
887                 cYAML_print_tree2file(stderr, err_rc);
888                 cYAML_free_tree(err_rc);
889                 return -1;
890         }
891
892         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
893
894         if (rc != LUSTRE_CFG_RC_NO_ERR)
895                 cYAML_print_tree2file(stderr, err_rc);
896
897         cYAML_free_tree(err_rc);
898
899         return rc;
900 }
901
902 static int jt_set_max_recovery_ping_interval(int argc, char **argv)
903 {
904         long int value;
905         int rc;
906         struct cYAML *err_rc = NULL;
907
908         rc = check_cmd(set_cmds, "set", "maximum recovery_interval", 2, argc, argv);
909         if (rc)
910                 return rc;
911
912         rc = parse_long(argv[1], &value);
913         if (rc != 0) {
914                 cYAML_build_error(-1, -1, "parser", "set",
915                                   "cannot parse maximum recovery interval value",
916                                   &err_rc);
917                 cYAML_print_tree2file(stderr, err_rc);
918                 cYAML_free_tree(err_rc);
919                 return -1;
920         }
921
922         rc = lustre_lnet_config_max_recovery_ping_interval(value, -1, &err_rc);
923         if (rc != LUSTRE_CFG_RC_NO_ERR)
924                 cYAML_print_tree2file(stderr, err_rc);
925
926         cYAML_free_tree(err_rc);
927
928         return rc;
929 }
930
931 static void yaml_lnet_print_error(char *flag, char *cmd, const char *errstr)
932 {
933         yaml_emitter_t log;
934         yaml_event_t event;
935         char errcode[23];
936         int rc;
937
938         snprintf(errcode, sizeof(errcode), "%d", errno);
939
940         yaml_emitter_initialize(&log);
941         yaml_emitter_set_output_file(&log, stdout);
942
943         yaml_emitter_open(&log);
944         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
945         rc = yaml_emitter_emit(&log, &event);
946         if (rc == 0)
947                 goto emitter_error;
948
949         yaml_mapping_start_event_initialize(&event, NULL,
950                                             (yaml_char_t *)YAML_MAP_TAG,
951                                             1, YAML_ANY_MAPPING_STYLE);
952         rc = yaml_emitter_emit(&log, &event);
953         if (rc == 0)
954                 goto emitter_error;
955
956         yaml_scalar_event_initialize(&event, NULL,
957                                      (yaml_char_t *)YAML_STR_TAG,
958                                      (yaml_char_t *)flag,
959                                      strlen(flag), 1, 0,
960                                      YAML_PLAIN_SCALAR_STYLE);
961         rc = yaml_emitter_emit(&log, &event);
962         if (rc == 0)
963                 goto emitter_error;
964
965         yaml_sequence_start_event_initialize(&event, NULL,
966                                              (yaml_char_t *)YAML_SEQ_TAG,
967                                              1, YAML_ANY_SEQUENCE_STYLE);
968         rc = yaml_emitter_emit(&log, &event);
969         if (rc == 0)
970                 goto emitter_error;
971
972         yaml_mapping_start_event_initialize(&event, NULL,
973                                             (yaml_char_t *)YAML_MAP_TAG,
974                                             1, YAML_ANY_MAPPING_STYLE);
975         rc = yaml_emitter_emit(&log, &event);
976         if (rc == 0)
977                 goto emitter_error;
978
979         yaml_scalar_event_initialize(&event, NULL,
980                                      (yaml_char_t *)YAML_STR_TAG,
981                                      (yaml_char_t *)cmd,
982                                      strlen(cmd),
983                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
984         rc = yaml_emitter_emit(&log, &event);
985         if (rc == 0)
986                 goto emitter_error;
987
988         yaml_scalar_event_initialize(&event, NULL,
989                                      (yaml_char_t *)YAML_STR_TAG,
990                                      (yaml_char_t *)"",
991                                      strlen(""),
992                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
993         rc = yaml_emitter_emit(&log, &event);
994         if (rc == 0)
995                 goto emitter_error;
996
997         yaml_scalar_event_initialize(&event, NULL,
998                                      (yaml_char_t *)YAML_STR_TAG,
999                                      (yaml_char_t *)"errno",
1000                                      strlen("errno"), 1, 0,
1001                                      YAML_PLAIN_SCALAR_STYLE);
1002         rc = yaml_emitter_emit(&log, &event);
1003         if (rc == 0)
1004                 goto emitter_error;
1005
1006         yaml_scalar_event_initialize(&event, NULL,
1007                                      (yaml_char_t *)YAML_INT_TAG,
1008                                      (yaml_char_t *)errcode,
1009                                      strlen(errcode), 1, 0,
1010                                      YAML_PLAIN_SCALAR_STYLE);
1011         rc = yaml_emitter_emit(&log, &event);
1012         if (rc == 0)
1013                 goto emitter_error;
1014
1015
1016         yaml_scalar_event_initialize(&event, NULL,
1017                                      (yaml_char_t *)YAML_STR_TAG,
1018                                      (yaml_char_t *)"descr",
1019                                      strlen("descr"), 1, 0,
1020                                      YAML_PLAIN_SCALAR_STYLE);
1021         rc = yaml_emitter_emit(&log, &event);
1022         if (rc == 0)
1023                 goto emitter_error;
1024
1025         yaml_scalar_event_initialize(&event, NULL,
1026                                      (yaml_char_t *)YAML_INT_TAG,
1027                                      (yaml_char_t *)errstr,
1028                                      strlen(errstr), 1, 0,
1029                                      YAML_PLAIN_SCALAR_STYLE);
1030         rc = yaml_emitter_emit(&log, &event);
1031         if (rc == 0)
1032                 goto emitter_error;
1033
1034         yaml_mapping_end_event_initialize(&event);
1035         rc = yaml_emitter_emit(&log, &event);
1036         if (rc == 0)
1037                 goto emitter_error;
1038
1039         yaml_sequence_end_event_initialize(&event);
1040         rc = yaml_emitter_emit(&log, &event);
1041         if (rc == 0)
1042                 goto emitter_error;
1043
1044         yaml_mapping_end_event_initialize(&event);
1045         rc = yaml_emitter_emit(&log, &event);
1046         if (rc == 0)
1047                 goto emitter_error;
1048
1049         yaml_document_end_event_initialize(&event, 0);
1050         rc = yaml_emitter_emit(&log, &event);
1051         if (rc == 0)
1052                 goto emitter_error;
1053
1054         rc = yaml_emitter_close(&log);
1055 emitter_error:
1056         if (rc == 0)
1057                 yaml_emitter_log_error(&log, stdout);
1058         yaml_emitter_delete(&log);
1059 }
1060
1061 static int jt_config_lnet(int argc, char **argv)
1062 {
1063         struct cYAML *err_rc = NULL;
1064         bool load_mod_params = false;
1065         int rc, opt;
1066
1067         const char *const short_options = "a";
1068         static const struct option long_options[] = {
1069                 { .name = "all",  .has_arg = no_argument, .val = 'a' },
1070                 { .name = NULL }
1071         };
1072
1073         rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
1074         if (rc)
1075                 return rc;
1076
1077         while ((opt = getopt_long(argc, argv, short_options,
1078                                    long_options, NULL)) != -1) {
1079                 switch (opt) {
1080                 case 'a':
1081                         load_mod_params = true;
1082                         break;
1083                 default:
1084                         return 0;
1085                 }
1086         }
1087
1088         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
1089                                           -1, &err_rc);
1090
1091         if (rc != LUSTRE_CFG_RC_NO_ERR)
1092                 cYAML_print_tree2file(stderr, err_rc);
1093
1094         cYAML_free_tree(err_rc);
1095
1096         return rc;
1097 }
1098
1099 static int jt_unconfig_lnet(int argc, char **argv)
1100 {
1101         struct cYAML *err_rc = NULL;
1102         int rc;
1103
1104         rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
1105         if (rc)
1106                 return rc;
1107
1108         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
1109
1110         if (rc != LUSTRE_CFG_RC_NO_ERR)
1111                 cYAML_print_tree2file(stderr, err_rc);
1112
1113         cYAML_free_tree(err_rc);
1114
1115         return rc;
1116 }
1117 static int jt_add_route(int argc, char **argv)
1118 {
1119         char *network = NULL, *gateway = NULL;
1120         long int hop = -1, prio = -1, sen = -1;
1121         struct cYAML *err_rc = NULL;
1122         int rc, opt;
1123
1124         const char *const short_options = "n:g:c:p:";
1125         static const struct option long_options[] = {
1126         { .name = "net",       .has_arg = required_argument, .val = 'n' },
1127         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1128         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1129         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1130         { .name = "health_sensitivity",  .has_arg = required_argument, .val = 's' },
1131         { .name = NULL } };
1132
1133         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
1134         if (rc)
1135                 return rc;
1136
1137         while ((opt = getopt_long(argc, argv, short_options,
1138                                    long_options, NULL)) != -1) {
1139                 switch (opt) {
1140                 case 'n':
1141                         network = optarg;
1142                         break;
1143                 case 'g':
1144                         gateway = optarg;
1145                         break;
1146                 case 'c':
1147                         rc = parse_long(optarg, &hop);
1148                         if (rc != 0) {
1149                                 /* ignore option */
1150                                 hop = -1;
1151                                 continue;
1152                         }
1153                         break;
1154                 case 'p':
1155                         rc = parse_long(optarg, &prio);
1156                         if (rc != 0) {
1157                                 /* ingore option */
1158                                 prio = -1;
1159                                 continue;
1160                         }
1161                         break;
1162                 case 's':
1163                         rc = parse_long(optarg, &sen);
1164                         if (rc != 0) {
1165                                 /* ingore option */
1166                                 sen = -1;
1167                                 continue;
1168                         }
1169                         break;
1170
1171                 case '?':
1172                         print_help(route_cmds, "route", "add");
1173                 default:
1174                         return 0;
1175                 }
1176         }
1177
1178         rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
1179                                       &err_rc);
1180
1181         if (rc != LUSTRE_CFG_RC_NO_ERR)
1182                 cYAML_print_tree2file(stderr, err_rc);
1183
1184         cYAML_free_tree(err_rc);
1185
1186         return rc;
1187 }
1188
1189 static int yaml_add_ni_tunables(yaml_emitter_t *output,
1190                                 struct lnet_ioctl_config_lnd_tunables *tunables,
1191                                 int cpp)
1192 {
1193         yaml_event_t event;
1194         char num[23];
1195         int rc;
1196
1197         yaml_scalar_event_initialize(&event, NULL,
1198                                      (yaml_char_t *)YAML_STR_TAG,
1199                                      (yaml_char_t *)"tunables",
1200                                      strlen("tunables"), 1, 0,
1201                                      YAML_PLAIN_SCALAR_STYLE);
1202         rc = yaml_emitter_emit(output, &event);
1203         if (rc == 0)
1204                 goto error;
1205
1206         yaml_mapping_start_event_initialize(&event, NULL,
1207                                             (yaml_char_t *)YAML_MAP_TAG,
1208                                             1, YAML_ANY_MAPPING_STYLE);
1209         rc = yaml_emitter_emit(output, &event);
1210         if (rc == 0)
1211                 goto error;
1212
1213         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1214                 yaml_scalar_event_initialize(&event, NULL,
1215                                              (yaml_char_t *)YAML_STR_TAG,
1216                                              (yaml_char_t *)"peer_timeout",
1217                                              strlen("peer_timeout"), 1, 0,
1218                                              YAML_PLAIN_SCALAR_STYLE);
1219                 rc = yaml_emitter_emit(output, &event);
1220                 if (rc == 0)
1221                         goto error;
1222
1223                 snprintf(num, sizeof(num), "%u",
1224                          tunables->lt_cmn.lct_peer_timeout);
1225                 yaml_scalar_event_initialize(&event, NULL,
1226                                              (yaml_char_t *)YAML_INT_TAG,
1227                                              (yaml_char_t *)num,
1228                                              strlen(num), 1, 0,
1229                                              YAML_PLAIN_SCALAR_STYLE);
1230                 rc = yaml_emitter_emit(output, &event);
1231                 if (rc == 0)
1232                         goto error;
1233         }
1234
1235         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1236                 yaml_scalar_event_initialize(&event, NULL,
1237                                              (yaml_char_t *)YAML_STR_TAG,
1238                                              (yaml_char_t *)"peer_credits",
1239                                              strlen("peer_credits"), 1, 0,
1240                                              YAML_PLAIN_SCALAR_STYLE);
1241                 rc = yaml_emitter_emit(output, &event);
1242                 if (rc == 0)
1243                         goto error;
1244
1245                 snprintf(num, sizeof(num), "%u",
1246                          tunables->lt_cmn.lct_peer_tx_credits);
1247                 yaml_scalar_event_initialize(&event, NULL,
1248                                              (yaml_char_t *)YAML_INT_TAG,
1249                                              (yaml_char_t *)num,
1250                                              strlen(num), 1, 0,
1251                                              YAML_PLAIN_SCALAR_STYLE);
1252                 rc = yaml_emitter_emit(output, &event);
1253                 if (rc == 0)
1254                         goto error;
1255         }
1256
1257         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1258                 yaml_scalar_event_initialize(&event, NULL,
1259                                              (yaml_char_t *)YAML_STR_TAG,
1260                                              (yaml_char_t *)"peer_buffer_credits",
1261                                              strlen("peer_buffer_credits"), 1, 0,
1262                                              YAML_PLAIN_SCALAR_STYLE);
1263                 rc = yaml_emitter_emit(output, &event);
1264                 if (rc == 0)
1265                         goto error;
1266
1267                 snprintf(num, sizeof(num), "%u",
1268                          tunables->lt_cmn.lct_peer_rtr_credits);
1269                 yaml_scalar_event_initialize(&event, NULL,
1270                                              (yaml_char_t *)YAML_INT_TAG,
1271                                              (yaml_char_t *)num,
1272                                              strlen(num), 1, 0,
1273                                              YAML_PLAIN_SCALAR_STYLE);
1274                 rc = yaml_emitter_emit(output, &event);
1275                 if (rc == 0)
1276                         goto error;
1277         }
1278
1279         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1280                 yaml_scalar_event_initialize(&event, NULL,
1281                                              (yaml_char_t *)YAML_STR_TAG,
1282                                              (yaml_char_t *)"credits",
1283                                              strlen("credits"), 1, 0,
1284                                              YAML_PLAIN_SCALAR_STYLE);
1285                 rc = yaml_emitter_emit(output, &event);
1286                 if (rc == 0)
1287                         goto error;
1288
1289                 snprintf(num, sizeof(num), "%u",
1290                          tunables->lt_cmn.lct_max_tx_credits);
1291                 yaml_scalar_event_initialize(&event, NULL,
1292                                              (yaml_char_t *)YAML_INT_TAG,
1293                                              (yaml_char_t *)num,
1294                                              strlen(num), 1, 0,
1295                                              YAML_PLAIN_SCALAR_STYLE);
1296                 rc = yaml_emitter_emit(output, &event);
1297                 if (rc == 0)
1298                         goto error;
1299         }
1300
1301         yaml_mapping_end_event_initialize(&event);
1302         rc = yaml_emitter_emit(output, &event);
1303         if (rc == 0)
1304                 goto error;
1305
1306         if (cpp > 0 || tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1307                 yaml_scalar_event_initialize(&event, NULL,
1308                                              (yaml_char_t *)YAML_STR_TAG,
1309                                              (yaml_char_t *)"lnd tunables",
1310                                              strlen("lnd tunables"), 1, 0,
1311                                              YAML_PLAIN_SCALAR_STYLE);
1312                 rc = yaml_emitter_emit(output, &event);
1313                 if (rc == 0)
1314                         goto error;
1315
1316                 yaml_mapping_start_event_initialize(&event, NULL,
1317                                                     (yaml_char_t *)YAML_MAP_TAG,
1318                                                     1, YAML_ANY_MAPPING_STYLE);
1319                 rc = yaml_emitter_emit(output, &event);
1320                 if (rc == 0)
1321                         goto error;
1322
1323                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1324                         yaml_scalar_event_initialize(&event, NULL,
1325                                                      (yaml_char_t *)YAML_STR_TAG,
1326                                                      (yaml_char_t *)"auth_key",
1327                                                      strlen("auth_key"), 1, 0,
1328                                                      YAML_PLAIN_SCALAR_STYLE);
1329                         rc = yaml_emitter_emit(output, &event);
1330                         if (rc == 0)
1331                                 goto error;
1332
1333                         snprintf(num, sizeof(num), "%u",
1334                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1335                 } else {
1336                         yaml_scalar_event_initialize(&event, NULL,
1337                                                      (yaml_char_t *)YAML_STR_TAG,
1338                                                      (yaml_char_t *)"conns_per_peer",
1339                                                      strlen("conns_per_peer"), 1, 0,
1340                                                      YAML_PLAIN_SCALAR_STYLE);
1341                         rc = yaml_emitter_emit(output, &event);
1342                         if (rc == 0)
1343                                 goto error;
1344
1345                         snprintf(num, sizeof(num), "%u", cpp);
1346                 }
1347
1348                 yaml_scalar_event_initialize(&event, NULL,
1349                                              (yaml_char_t *)YAML_INT_TAG,
1350                                              (yaml_char_t *)num,
1351                                              strlen(num), 1, 0,
1352                                              YAML_PLAIN_SCALAR_STYLE);
1353                 rc = yaml_emitter_emit(output, &event);
1354                 if (rc == 0)
1355                         goto error;
1356
1357                 yaml_mapping_end_event_initialize(&event);
1358                 rc = yaml_emitter_emit(output, &event);
1359                 if (rc == 0)
1360                         goto error;
1361         }
1362 error:
1363         return rc;
1364 }
1365
1366 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1367                                struct lnet_dlc_network_descr *nw_descr,
1368                                struct lnet_ioctl_config_lnd_tunables *tunables,
1369                                int cpp, struct cfs_expr_list *global_cpts,
1370                                int flags)
1371 {
1372         struct lnet_dlc_intf_descr *intf;
1373         struct nl_sock *sk = NULL;
1374         yaml_emitter_t output;
1375         yaml_parser_t reply;
1376         yaml_event_t event;
1377         int rc;
1378
1379         if (!ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1380                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'",
1381                         (!nw_descr) ? "network , interface" :
1382                         (nw_descr->nw_id == 0) ? "network" : "interface");
1383                 return -EINVAL;
1384         }
1385
1386         if ((flags == NLM_F_CREATE) && list_empty(&nw_descr->nw_intflist)) {
1387                 fprintf(stdout, "creating a local NI needs at least one interface");
1388                 return -EINVAL;
1389         }
1390
1391         /* Create Netlink emitter to send request to kernel */
1392         sk = nl_socket_alloc();
1393         if (!sk)
1394                 return -EOPNOTSUPP;
1395
1396         /* Setup parser to receive Netlink packets */
1397         rc = yaml_parser_initialize(&reply);
1398         if (rc == 0) {
1399                 nl_socket_free(sk);
1400                 return -EOPNOTSUPP;
1401         }
1402
1403         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1404         if (rc == 0)
1405                 goto free_reply;
1406
1407         /* Create Netlink emitter to send request to kernel */
1408         rc = yaml_emitter_initialize(&output);
1409         if (rc == 0)
1410                 goto free_reply;
1411
1412         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1413                                              LNET_GENL_VERSION, LNET_CMD_NETS,
1414                                              flags);
1415         if (rc == 0)
1416                 goto emitter_error;
1417
1418         yaml_emitter_open(&output);
1419         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1420         rc = yaml_emitter_emit(&output, &event);
1421         if (rc == 0)
1422                 goto emitter_error;
1423
1424         yaml_mapping_start_event_initialize(&event, NULL,
1425                                             (yaml_char_t *)YAML_MAP_TAG,
1426                                             1, YAML_ANY_MAPPING_STYLE);
1427         rc = yaml_emitter_emit(&output, &event);
1428         if (rc == 0)
1429                 goto emitter_error;
1430
1431         yaml_scalar_event_initialize(&event, NULL,
1432                                      (yaml_char_t *)YAML_STR_TAG,
1433                                      (yaml_char_t *)"net",
1434                                      strlen("net"), 1, 0,
1435                                      YAML_PLAIN_SCALAR_STYLE);
1436         rc = yaml_emitter_emit(&output, &event);
1437         if (rc == 0)
1438                 goto emitter_error;
1439
1440         if (net_id || ip2net) {
1441                 char *key = net_id ? "net type" : "ip2net";
1442                 char *value = net_id ? net_id : ip2net;
1443
1444                 yaml_sequence_start_event_initialize(&event, NULL,
1445                                                      (yaml_char_t *)YAML_SEQ_TAG,
1446                                                      1, YAML_ANY_SEQUENCE_STYLE);
1447                 rc = yaml_emitter_emit(&output, &event);
1448                 if (rc == 0)
1449                         goto emitter_error;
1450
1451                 yaml_mapping_start_event_initialize(&event, NULL,
1452                                                     (yaml_char_t *)YAML_MAP_TAG,
1453                                                     1, YAML_ANY_MAPPING_STYLE);
1454                 rc = yaml_emitter_emit(&output, &event);
1455                 if (rc == 0)
1456                         goto emitter_error;
1457
1458                 yaml_scalar_event_initialize(&event, NULL,
1459                                              (yaml_char_t *)YAML_STR_TAG,
1460                                              (yaml_char_t *)key,
1461                                              strlen(key),
1462                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
1463                 rc = yaml_emitter_emit(&output, &event);
1464                 if (rc == 0)
1465                         goto emitter_error;
1466
1467                 yaml_scalar_event_initialize(&event, NULL,
1468                                              (yaml_char_t *)YAML_STR_TAG,
1469                                              (yaml_char_t *)value,
1470                                              strlen(value), 1, 0,
1471                                              YAML_PLAIN_SCALAR_STYLE);
1472                 rc = yaml_emitter_emit(&output, &event);
1473                 if (rc == 0)
1474                         goto emitter_error;
1475         } else {
1476                 yaml_scalar_event_initialize(&event, NULL,
1477                                              (yaml_char_t *)YAML_STR_TAG,
1478                                              (yaml_char_t *)"",
1479                                              strlen(""), 1, 0,
1480                                              YAML_PLAIN_SCALAR_STYLE);
1481                 rc = yaml_emitter_emit(&output, &event);
1482                 if (rc == 0)
1483                         goto emitter_error;
1484
1485                 goto no_net_id;
1486         }
1487
1488         if (list_empty(&nw_descr->nw_intflist))
1489                 goto skip_intf;
1490
1491         yaml_scalar_event_initialize(&event, NULL,
1492                                      (yaml_char_t *)YAML_STR_TAG,
1493                                      (yaml_char_t *)"local NI(s)",
1494                                      strlen("local NI(s)"), 1, 0,
1495                                      YAML_PLAIN_SCALAR_STYLE);
1496         rc = yaml_emitter_emit(&output, &event);
1497         if (rc == 0)
1498                 goto emitter_error;
1499
1500         yaml_sequence_start_event_initialize(&event, NULL,
1501                                              (yaml_char_t *)YAML_SEQ_TAG,
1502                                              1, YAML_ANY_SEQUENCE_STYLE);
1503         rc = yaml_emitter_emit(&output, &event);
1504         if (rc == 0)
1505                 goto emitter_error;
1506
1507         list_for_each_entry(intf, &nw_descr->nw_intflist,
1508                             intf_on_network) {
1509                 yaml_mapping_start_event_initialize(&event, NULL,
1510                                                     (yaml_char_t *)YAML_MAP_TAG,
1511                                                     1, YAML_ANY_MAPPING_STYLE);
1512                 rc = yaml_emitter_emit(&output, &event);
1513                 if (rc == 0)
1514                         goto emitter_error;
1515
1516                 yaml_scalar_event_initialize(&event, NULL,
1517                                              (yaml_char_t *)YAML_STR_TAG,
1518                                              (yaml_char_t *)"interfaces",
1519                                              strlen("interfaces"), 1, 0,
1520                                              YAML_PLAIN_SCALAR_STYLE);
1521                 rc = yaml_emitter_emit(&output, &event);
1522                 if (rc == 0)
1523                         goto emitter_error;
1524
1525                 yaml_mapping_start_event_initialize(&event, NULL,
1526                                                     (yaml_char_t *)YAML_MAP_TAG,
1527                                                     1, YAML_ANY_MAPPING_STYLE);
1528                 rc = yaml_emitter_emit(&output, &event);
1529                 if (rc == 0)
1530                         goto emitter_error;
1531
1532                 yaml_scalar_event_initialize(&event, NULL,
1533                                              (yaml_char_t *)YAML_STR_TAG,
1534                                              (yaml_char_t *)"0",
1535                                              strlen("0"), 1, 0,
1536                                              YAML_PLAIN_SCALAR_STYLE);
1537                 rc = yaml_emitter_emit(&output, &event);
1538                 if (rc == 0)
1539                         goto emitter_error;
1540
1541                 yaml_scalar_event_initialize(&event, NULL,
1542                                              (yaml_char_t *)YAML_STR_TAG,
1543                                              (yaml_char_t *)intf->intf_name,
1544                                              strlen(intf->intf_name), 1, 0,
1545                                              YAML_PLAIN_SCALAR_STYLE);
1546                 rc = yaml_emitter_emit(&output, &event);
1547                 if (rc == 0)
1548                         goto emitter_error;
1549
1550                 yaml_mapping_end_event_initialize(&event);
1551                 rc = yaml_emitter_emit(&output, &event);
1552                 if (rc == 0)
1553                         goto emitter_error;
1554
1555                 if (tunables) {
1556                         rc = yaml_add_ni_tunables(&output, tunables, cpp);
1557                         if (rc == 0)
1558                                 goto emitter_error;
1559                 }
1560
1561                 if (global_cpts) {
1562                         __u32 *cpt_array;
1563                         int count, i;
1564
1565                         yaml_scalar_event_initialize(&event, NULL,
1566                                                      (yaml_char_t *)YAML_STR_TAG,
1567                                                      (yaml_char_t *)"CPT",
1568                                                      strlen("CPT"), 1, 0,
1569                                                      YAML_PLAIN_SCALAR_STYLE);
1570                         rc = yaml_emitter_emit(&output, &event);
1571                         if (rc == 0)
1572                                 goto emitter_error;
1573
1574                         yaml_sequence_start_event_initialize(&event, NULL,
1575                                                              (yaml_char_t *)YAML_SEQ_TAG,
1576                                                              1,
1577                                                              YAML_FLOW_SEQUENCE_STYLE);
1578                         rc = yaml_emitter_emit(&output, &event);
1579                         if (rc == 0)
1580                                 goto emitter_error;
1581
1582                         count = cfs_expr_list_values(global_cpts,
1583                                                      LNET_MAX_SHOW_NUM_CPT,
1584                                                      &cpt_array);
1585                         for (i = 0; i < count; i++) {
1586                                 char core[23];
1587
1588                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
1589                                 yaml_scalar_event_initialize(&event, NULL,
1590                                                              (yaml_char_t *)YAML_STR_TAG,
1591                                                              (yaml_char_t *)core,
1592                                                              strlen(core), 1, 0,
1593                                                              YAML_PLAIN_SCALAR_STYLE);
1594                                 rc = yaml_emitter_emit(&output, &event);
1595                                 if (rc == 0)
1596                                         goto emitter_error;
1597                         }
1598
1599                         yaml_sequence_end_event_initialize(&event);
1600                         rc = yaml_emitter_emit(&output, &event);
1601                         if (rc == 0)
1602                                 goto emitter_error;
1603
1604                         cfs_expr_list_free(global_cpts);
1605                         free(cpt_array);
1606                 }
1607
1608                 yaml_mapping_end_event_initialize(&event);
1609                 rc = yaml_emitter_emit(&output, &event);
1610                 if (rc == 0)
1611                         goto emitter_error;
1612         }
1613
1614         yaml_sequence_end_event_initialize(&event);
1615         rc = yaml_emitter_emit(&output, &event);
1616         if (rc == 0)
1617                 goto emitter_error;
1618 skip_intf:
1619         yaml_mapping_end_event_initialize(&event);
1620         rc = yaml_emitter_emit(&output, &event);
1621         if (rc == 0)
1622                 goto emitter_error;
1623
1624         yaml_sequence_end_event_initialize(&event);
1625         rc = yaml_emitter_emit(&output, &event);
1626         if (rc == 0)
1627                 goto emitter_error;
1628 no_net_id:
1629         yaml_mapping_end_event_initialize(&event);
1630         rc = yaml_emitter_emit(&output, &event);
1631         if (rc == 0)
1632                 goto emitter_error;
1633
1634         yaml_document_end_event_initialize(&event, 0);
1635         rc = yaml_emitter_emit(&output, &event);
1636         if (rc == 0)
1637                 goto emitter_error;
1638
1639         rc = yaml_emitter_close(&output);
1640 emitter_error:
1641         if (rc == 0) {
1642                 yaml_emitter_log_error(&output, stderr);
1643                 rc = -EINVAL;
1644         } else {
1645                 yaml_document_t errmsg;
1646
1647                 rc = yaml_parser_load(&reply, &errmsg);
1648         }
1649         yaml_emitter_delete(&output);
1650 free_reply:
1651         if (rc == 0) {
1652                 yaml_lnet_print_error(flags ? "add" : "del", "net",
1653                                       yaml_parser_get_reader_error(&reply));
1654                 rc = -EINVAL;
1655         }
1656         yaml_parser_delete(&reply);
1657         nl_socket_free(sk);
1658
1659         return rc == 1 ? 0 : rc;
1660 }
1661
1662 static int jt_add_ni(int argc, char **argv)
1663 {
1664         char *ip2net = NULL;
1665         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
1666         struct cYAML *err_rc = NULL;
1667         int rc, opt, cpt_rc = -1;
1668         struct lnet_dlc_network_descr nw_descr;
1669         struct cfs_expr_list *global_cpts = NULL;
1670         struct lnet_ioctl_config_lnd_tunables tunables;
1671         bool found = false;
1672         bool skip_mr_route_setup = false;
1673         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:";
1674         static const struct option long_options[] = {
1675         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
1676         { .name = "peer-buffer-credits",
1677                                   .has_arg = required_argument, .val = 'b' },
1678         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
1679         { .name = "if",           .has_arg = required_argument, .val = 'i' },
1680         { .name = "skip-mr-route-setup",
1681                                   .has_arg = no_argument, .val = 'k' },
1682         { .name = "conns-per-peer",
1683                                   .has_arg = required_argument, .val = 'm' },
1684         { .name = "net",          .has_arg = required_argument, .val = 'n' },
1685         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
1686         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
1687         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
1688         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
1689         { .name = NULL } };
1690         char *net_id = NULL;
1691
1692         memset(&tunables, 0, sizeof(tunables));
1693         lustre_lnet_init_nw_descr(&nw_descr);
1694
1695         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
1696         if (rc)
1697                 return rc;
1698
1699         while ((opt = getopt_long(argc, argv, short_options,
1700                                    long_options, NULL)) != -1) {
1701                 switch (opt) {
1702                 case 'a':
1703                         rc = parse_long(optarg, &auth_key);
1704                         if (rc != 0) {
1705                                 /* ignore option */
1706                                 auth_key = -1;
1707                                 continue;
1708                         }
1709                         break;
1710                 case 'b':
1711                         rc = parse_long(optarg, &pbc);
1712                         if (rc != 0) {
1713                                 /* ignore option */
1714                                 pbc = -1;
1715                                 continue;
1716                         }
1717                         break;
1718                 case 'c':
1719                         rc = parse_long(optarg, &pc);
1720                         if (rc != 0) {
1721                                 /* ignore option */
1722                                 pc = -1;
1723                                 continue;
1724                         }
1725                         break;
1726                 case 'i':
1727                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
1728                         if (rc != 0) {
1729                                 cYAML_build_error(-1, -1, "ni", "add",
1730                                                 "bad interface list",
1731                                                 &err_rc);
1732                                 goto failed;
1733                         }
1734                         break;
1735                 case 'k':
1736                         skip_mr_route_setup = true;
1737                         break;
1738                 case 'm':
1739                         rc = parse_long(optarg, &cpp);
1740                         if (rc != 0) {
1741                                 /* ignore option */
1742                                 cpp = -1;
1743                                 continue;
1744                         }
1745                         break;
1746
1747                 case 'n':
1748                         nw_descr.nw_id = libcfs_str2net(optarg);
1749                         net_id = optarg;
1750                         break;
1751                 case 'p':
1752                         ip2net = optarg;
1753                         break;
1754                 case 'r':
1755                         rc = parse_long(optarg, &cre);
1756                         if (rc != 0) {
1757                                 /* ignore option */
1758                                 cre = -1;
1759                                 continue;
1760                         }
1761                         break;
1762                 case 's':
1763                         cpt_rc = cfs_expr_list_parse(optarg,
1764                                                      strlen(optarg), 0,
1765                                                      UINT_MAX, &global_cpts);
1766                         break;
1767                 case 't':
1768                         rc = parse_long(optarg, &pto);
1769                         if (rc != 0) {
1770                                 /* ignore option */
1771                                 pto = -1;
1772                                 continue;
1773                         }
1774                         break;
1775                 case '?':
1776                         print_help(net_cmds, "net", "add");
1777                 default:
1778                         return 0;
1779                 }
1780         }
1781 #ifdef HAVE_KFILND
1782         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
1783                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
1784                 found = true;
1785         }
1786 #endif
1787         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
1788                 tunables.lt_cmn.lct_peer_timeout = pto;
1789                 tunables.lt_cmn.lct_peer_tx_credits = pc;
1790                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
1791                 tunables.lt_cmn.lct_max_tx_credits = cre;
1792                 found = true;
1793         }
1794
1795         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
1796                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
1797
1798         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
1799                                  found ? &tunables : NULL, cpp,
1800                                  (cpt_rc == 0) ? global_cpts : NULL,
1801                                  NLM_F_CREATE);
1802         if (rc <= 0) {
1803                 if (rc == -EOPNOTSUPP)
1804                         goto old_api;
1805                 if (global_cpts != NULL)
1806                         cfs_expr_list_free(global_cpts);
1807                 if (rc == 0 && !skip_mr_route_setup)
1808                         rc = lustre_lnet_setup_mrrouting(&err_rc);
1809                 return rc;
1810         }
1811 old_api:
1812         rc = lustre_lnet_config_ni(&nw_descr,
1813                                    (cpt_rc == 0) ? global_cpts: NULL,
1814                                    ip2net, (found) ? &tunables : NULL,
1815                                    cpp, -1, &err_rc);
1816
1817         if (global_cpts != NULL)
1818                 cfs_expr_list_free(global_cpts);
1819
1820 failed:
1821         if (rc != LUSTRE_CFG_RC_NO_ERR)
1822                 cYAML_print_tree2file(stderr, err_rc);
1823
1824         cYAML_free_tree(err_rc);
1825
1826         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
1827                 err_rc = NULL;
1828                 rc = lustre_lnet_setup_mrrouting(&err_rc);
1829
1830                 if (rc != LUSTRE_CFG_RC_NO_ERR)
1831                         cYAML_print_tree2file(stderr, err_rc);
1832
1833                 cYAML_free_tree(err_rc);
1834         }
1835
1836         return rc;
1837 }
1838
1839 static int jt_del_route(int argc, char **argv)
1840 {
1841         char *network = NULL, *gateway = NULL;
1842         struct cYAML *err_rc = NULL;
1843         int rc, opt;
1844
1845         const char *const short_options = "n:g:";
1846         static const struct option long_options[] = {
1847                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
1848                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
1849                 { .name = NULL } };
1850
1851         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
1852         if (rc)
1853                 return rc;
1854
1855         while ((opt = getopt_long(argc, argv, short_options,
1856                                    long_options, NULL)) != -1) {
1857                 switch (opt) {
1858                 case 'n':
1859                         network = optarg;
1860                         break;
1861                 case 'g':
1862                         gateway = optarg;
1863                         break;
1864                 case '?':
1865                         print_help(route_cmds, "route", "del");
1866                 default:
1867                         return 0;
1868                 }
1869         }
1870
1871         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
1872
1873         if (rc != LUSTRE_CFG_RC_NO_ERR)
1874                 cYAML_print_tree2file(stderr, err_rc);
1875
1876         cYAML_free_tree(err_rc);
1877
1878         return rc;
1879 }
1880
1881 static int jt_del_ni(int argc, char **argv)
1882 {
1883         struct cYAML *err_rc = NULL;
1884         int rc, opt;
1885         struct lnet_dlc_network_descr nw_descr;
1886         const char *const short_options = "n:i:";
1887         static const struct option long_options[] = {
1888         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
1889         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
1890         { .name = NULL } };
1891         char *net_id = NULL;
1892
1893         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
1894         if (rc)
1895                 return rc;
1896
1897         lustre_lnet_init_nw_descr(&nw_descr);
1898
1899         while ((opt = getopt_long(argc, argv, short_options,
1900                                    long_options, NULL)) != -1) {
1901                 switch (opt) {
1902                 case 'n':
1903                         nw_descr.nw_id = libcfs_str2net(optarg);
1904                         net_id = optarg;
1905                         break;
1906                 case 'i':
1907                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
1908                         if (rc != 0) {
1909                                 cYAML_build_error(-1, -1, "ni", "add",
1910                                                 "bad interface list",
1911                                                 &err_rc);
1912                                 goto out;
1913                         }
1914                         break;
1915                 case '?':
1916                         print_help(net_cmds, "net", "del");
1917                 default:
1918                         return 0;
1919                 }
1920         }
1921
1922         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, -1, NULL, 0);
1923         if (rc <= 0) {
1924                 if (rc != -EOPNOTSUPP)
1925                         return rc;
1926         }
1927
1928         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
1929 out:
1930         if (rc != LUSTRE_CFG_RC_NO_ERR)
1931                 cYAML_print_tree2file(stderr, err_rc);
1932
1933         cYAML_free_tree(err_rc);
1934
1935         return rc;
1936 }
1937
1938 static int jt_show_route(int argc, char **argv)
1939 {
1940         char *network = NULL, *gateway = NULL;
1941         long int hop = -1, prio = -1;
1942         int detail = 0, rc, opt;
1943         struct cYAML *err_rc = NULL, *show_rc = NULL;
1944
1945         const char *const short_options = "n:g:h:p:v";
1946         static const struct option long_options[] = {
1947         { .name = "net",       .has_arg = required_argument, .val = 'n' },
1948         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1949         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1950         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1951         { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
1952         { .name = NULL } };
1953
1954         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
1955         if (rc)
1956                 return rc;
1957
1958         while ((opt = getopt_long(argc, argv, short_options,
1959                                    long_options, NULL)) != -1) {
1960                 switch (opt) {
1961                 case 'n':
1962                         network = optarg;
1963                         break;
1964                 case 'g':
1965                         gateway = optarg;
1966                         break;
1967                 case 'c':
1968                         rc = parse_long(optarg, &hop);
1969                         if (rc != 0) {
1970                                 /* ignore option */
1971                                 hop = -1;
1972                                 continue;
1973                         }
1974                         break;
1975                 case 'p':
1976                         rc = parse_long(optarg, &prio);
1977                         if (rc != 0) {
1978                                 /* ignore option */
1979                                 prio = -1;
1980                                 continue;
1981                         }
1982                         break;
1983                 case 'v':
1984                         detail = 1;
1985                         break;
1986                 case '?':
1987                         print_help(route_cmds, "route", "show");
1988                 default:
1989                         return 0;
1990                 }
1991         }
1992
1993         rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
1994                                     &show_rc, &err_rc, false);
1995
1996         if (rc != LUSTRE_CFG_RC_NO_ERR)
1997                 cYAML_print_tree2file(stderr, err_rc);
1998         else if (show_rc)
1999                 cYAML_print_tree(show_rc);
2000
2001         cYAML_free_tree(err_rc);
2002         cYAML_free_tree(show_rc);
2003
2004         return rc;
2005 }
2006
2007 static int set_value_helper(int argc, char **argv,
2008                             int (*cb)(int, bool, char*, int, struct cYAML**))
2009 {
2010         char *nid = NULL;
2011         long int healthv = -1;
2012         bool all = false;
2013         int rc, opt;
2014         struct cYAML *err_rc = NULL;
2015
2016         const char *const short_options = "t:n:a";
2017         static const struct option long_options[] = {
2018                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2019                 { .name = "health", .has_arg = required_argument, .val = 't' },
2020                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2021                 { .name = NULL } };
2022
2023         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2024         if (rc)
2025                 return rc;
2026
2027         while ((opt = getopt_long(argc, argv, short_options,
2028                                    long_options, NULL)) != -1) {
2029                 switch (opt) {
2030                 case 'n':
2031                         nid = optarg;
2032                         break;
2033                 case 't':
2034                         if (parse_long(optarg, &healthv) != 0)
2035                                 healthv = -1;
2036                         break;
2037                 case 'a':
2038                         all = true;
2039                         break;
2040                 default:
2041                         return 0;
2042                 }
2043         }
2044
2045         rc = cb(healthv, all, nid, -1, &err_rc);
2046
2047         if (rc != LUSTRE_CFG_RC_NO_ERR)
2048                 cYAML_print_tree2file(stderr, err_rc);
2049
2050         cYAML_free_tree(err_rc);
2051
2052         return rc;
2053 }
2054
2055 static int jt_set_ni_value(int argc, char **argv)
2056 {
2057         char *nid = NULL;
2058         long int healthv = -1, cpp = -1;
2059         bool all = false;
2060         int rc, opt;
2061         struct cYAML *err_rc = NULL;
2062
2063         const char *const short_options = "a:m:n:t:";
2064         static const struct option long_options[] = {
2065         { .name = "all",            .has_arg = no_argument,       .val = 'a' },
2066         { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2067         { .name = "nid",            .has_arg = required_argument, .val = 'n' },
2068         { .name = "health",         .has_arg = required_argument, .val = 't' },
2069         { .name = NULL } };
2070
2071         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2072         if (rc)
2073                 return rc;
2074
2075         while ((opt = getopt_long(argc, argv, short_options,
2076                                    long_options, NULL)) != -1) {
2077                 switch (opt) {
2078                 case 'a':
2079                         all = true;
2080                         break;
2081                 case 'm':
2082                         rc = parse_long(optarg, &cpp);
2083                         if (rc != 0) {
2084                                 /* ignore option */
2085                                 cpp = -1;
2086                                 continue;
2087                         }
2088                         break;
2089                 case 'n':
2090                         nid = optarg;
2091                         break;
2092                 case 't':
2093                         if (parse_long(optarg, &healthv) != 0) {
2094                                 /* ignore option */
2095                                 healthv = -1;
2096                                 continue;
2097                         }
2098                         break;
2099                 default:
2100                         return 0;
2101                 }
2102         }
2103
2104         if (cpp > -1)
2105                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
2106                                                           -1, &err_rc);
2107         if (healthv > -1)
2108                 rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
2109                                                    -1, &err_rc);
2110
2111         if (rc != LUSTRE_CFG_RC_NO_ERR)
2112                 cYAML_print_tree2file(stderr, err_rc);
2113
2114         cYAML_free_tree(err_rc);
2115
2116         return rc;
2117 }
2118
2119 static int jt_set_peer_ni_value(int argc, char **argv)
2120 {
2121         return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
2122 }
2123
2124 static int jt_show_recovery(int argc, char **argv)
2125 {
2126         int rc, opt;
2127         struct cYAML *err_rc = NULL, *show_rc = NULL;
2128         const char *const short_options = "lp";
2129         static const struct option long_options[] = {
2130                 { .name = "local", .has_arg = no_argument, .val = 'l' },
2131                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
2132                 { .name = NULL } };
2133
2134         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
2135         if (rc)
2136                 return rc;
2137
2138         while ((opt = getopt_long(argc, argv, short_options,
2139                                    long_options, NULL)) != -1) {
2140                 switch (opt) {
2141                 case 'l':
2142                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
2143                         break;
2144                 case 'p':
2145                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
2146                         break;
2147                 default:
2148                         return 0;
2149                 }
2150         }
2151
2152         if (rc != LUSTRE_CFG_RC_NO_ERR)
2153                 cYAML_print_tree2file(stderr, err_rc);
2154         else if (show_rc)
2155                 cYAML_print_tree(show_rc);
2156
2157         cYAML_free_tree(err_rc);
2158         cYAML_free_tree(show_rc);
2159
2160         return rc;
2161 }
2162
2163 static int jt_show_peer_debug_info(int argc, char **argv)
2164 {
2165         int rc, opt;
2166         struct cYAML *err_rc = NULL;
2167         char *peer_nid = optarg;
2168         const char *const short_opts = "k";
2169         const struct option long_opts[] = {
2170         { .name = "nid", .has_arg = required_argument, .val = 'k' },
2171         { .name = NULL } };
2172
2173         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
2174
2175         if (rc)
2176                 return rc;
2177
2178         while ((opt = getopt_long(argc, argv, short_opts,
2179                                    long_opts, NULL)) != -1) {
2180                 switch (opt) {
2181                 case 'k':
2182                         peer_nid = optarg;
2183                         break;
2184                 default:
2185                         return 0;
2186                 }
2187         }
2188
2189         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
2190
2191         if (rc != LUSTRE_CFG_RC_NO_ERR)
2192                 cYAML_print_tree2file(stderr, err_rc);
2193
2194         cYAML_free_tree(err_rc);
2195
2196         return rc;
2197 }
2198
2199 static int jt_show_net(int argc, char **argv)
2200 {
2201         char *network = NULL;
2202         int rc, opt;
2203         struct cYAML *err_rc = NULL, *show_rc = NULL;
2204         long int detail = 0;
2205
2206         const char *const short_options = "n:v";
2207         static const struct option long_options[] = {
2208                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2209                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
2210                 { .name = NULL } };
2211
2212         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
2213         if (rc)
2214                 return rc;
2215
2216         while ((opt = getopt_long(argc, argv, short_options,
2217                                    long_options, NULL)) != -1) {
2218                 switch (opt) {
2219                 case 'n':
2220                         network = optarg;
2221                         break;
2222                 case 'v':
2223                         if ((!optarg) && (argv[optind] != NULL) &&
2224                             (argv[optind][0] != '-')) {
2225                                 if (parse_long(argv[optind++], &detail) != 0)
2226                                         detail = 1;
2227                         } else {
2228                                 detail = 1;
2229                         }
2230                         break;
2231                 case '?':
2232                         print_help(net_cmds, "net", "show");
2233                 default:
2234                         return 0;
2235                 }
2236         }
2237
2238         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
2239                                   false);
2240
2241         if (rc != LUSTRE_CFG_RC_NO_ERR)
2242                 cYAML_print_tree2file(stderr, err_rc);
2243         else if (show_rc)
2244                 cYAML_print_tree(show_rc);
2245
2246         cYAML_free_tree(err_rc);
2247         cYAML_free_tree(show_rc);
2248
2249         return rc;
2250 }
2251
2252 static int jt_show_routing(int argc, char **argv)
2253 {
2254         struct cYAML *err_rc = NULL, *show_rc = NULL;
2255         int rc;
2256
2257         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
2258         if (rc)
2259                 return rc;
2260
2261         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
2262
2263         if (rc != LUSTRE_CFG_RC_NO_ERR)
2264                 cYAML_print_tree2file(stderr, err_rc);
2265         else if (show_rc)
2266                 cYAML_print_tree(show_rc);
2267
2268         cYAML_free_tree(err_rc);
2269         cYAML_free_tree(show_rc);
2270
2271         return rc;
2272 }
2273
2274 static int jt_show_stats(int argc, char **argv)
2275 {
2276         int rc;
2277         struct cYAML *show_rc = NULL, *err_rc = NULL;
2278
2279         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
2280         if (rc)
2281                 return rc;
2282
2283         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
2284
2285         if (rc != LUSTRE_CFG_RC_NO_ERR)
2286                 cYAML_print_tree2file(stderr, err_rc);
2287         else if (show_rc)
2288                 cYAML_print_tree(show_rc);
2289
2290         cYAML_free_tree(err_rc);
2291         cYAML_free_tree(show_rc);
2292
2293         return rc;
2294 }
2295
2296 static int jt_show_udsp(int argc, char **argv)
2297 {
2298         int idx = -1;
2299         int rc, opt;
2300         struct cYAML *err_rc = NULL, *show_rc = NULL;
2301
2302         const char *const short_options = "i:";
2303         static const struct option long_options[] = {
2304                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
2305                 { .name = NULL }
2306         };
2307
2308         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
2309         if (rc)
2310                 return rc;
2311
2312         while ((opt = getopt_long(argc, argv, short_options,
2313                                    long_options, NULL)) != -1) {
2314                 switch (opt) {
2315                 case 'i':
2316                         idx = atoi(optarg);
2317                         break;
2318                 case '?':
2319                         print_help(net_cmds, "net", "show");
2320                 default:
2321                         return 0;
2322                 }
2323         }
2324
2325         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
2326
2327         if (rc != LUSTRE_CFG_RC_NO_ERR)
2328                 cYAML_print_tree2file(stderr, err_rc);
2329         else if (show_rc)
2330                 cYAML_print_tree(show_rc);
2331
2332         cYAML_free_tree(err_rc);
2333         cYAML_free_tree(show_rc);
2334
2335         return rc;
2336 }
2337
2338 static int jt_show_global(int argc, char **argv)
2339 {
2340         int rc;
2341         struct cYAML *show_rc = NULL, *err_rc = NULL;
2342
2343         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
2344         if (rc)
2345                 return rc;
2346
2347         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
2348         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2349                 cYAML_print_tree2file(stderr, err_rc);
2350                 goto out;
2351         }
2352
2353         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
2354         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2355                 cYAML_print_tree2file(stderr, err_rc);
2356                 goto out;
2357         }
2358
2359         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
2360         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2361                 cYAML_print_tree2file(stderr, err_rc);
2362                 goto out;
2363         }
2364
2365         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
2366         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2367                 cYAML_print_tree2file(stderr, err_rc);
2368                 goto out;
2369         }
2370
2371         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
2372         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2373                 cYAML_print_tree2file(stderr, err_rc);
2374                 goto out;
2375         }
2376
2377         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
2378         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2379                 cYAML_print_tree2file(stderr, err_rc);
2380                 goto out;
2381         }
2382
2383         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
2384         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2385                 cYAML_print_tree2file(stderr, err_rc);
2386                 goto out;
2387         }
2388
2389         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
2390         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2391                 cYAML_print_tree2file(stderr, err_rc);
2392                 goto out;
2393         }
2394
2395         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
2396         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2397                 cYAML_print_tree2file(stderr, err_rc);
2398                 goto out;
2399         }
2400
2401         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
2402         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2403                 cYAML_print_tree2file(stderr, err_rc);
2404                 goto out;
2405         }
2406
2407         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
2408         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2409                 cYAML_print_tree2file(stderr, err_rc);
2410                 goto out;
2411         }
2412
2413         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
2414         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2415                 cYAML_print_tree2file(stderr, err_rc);
2416                 goto out;
2417         }
2418
2419         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
2420         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2421                 cYAML_print_tree2file(stderr, err_rc);
2422                 goto out;
2423         }
2424
2425         if (show_rc)
2426                 cYAML_print_tree(show_rc);
2427
2428 out:
2429         cYAML_free_tree(err_rc);
2430         cYAML_free_tree(show_rc);
2431
2432         return rc;
2433 }
2434
2435 static int jt_lnet(int argc, char **argv)
2436 {
2437         int rc;
2438
2439         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
2440         if (rc)
2441                 return rc;
2442
2443         return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
2444 }
2445
2446 static int jt_route(int argc, char **argv)
2447 {
2448         int rc;
2449
2450         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
2451         if (rc)
2452                 return rc;
2453
2454         return Parser_execarg(argc - 1, &argv[1], route_cmds);
2455 }
2456
2457 static int jt_net(int argc, char **argv)
2458 {
2459         int rc;
2460
2461         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
2462         if (rc)
2463                 return rc;
2464
2465         return Parser_execarg(argc - 1, &argv[1], net_cmds);
2466 }
2467
2468 static int jt_routing(int argc, char **argv)
2469 {
2470         int rc;
2471
2472         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
2473         if (rc)
2474                 return rc;
2475
2476         return Parser_execarg(argc - 1, &argv[1], routing_cmds);
2477 }
2478
2479 static int jt_stats(int argc, char **argv)
2480 {
2481         int rc;
2482
2483         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
2484         if (rc)
2485                 return rc;
2486
2487         return Parser_execarg(argc - 1, &argv[1], stats_cmds);
2488 }
2489
2490 static int jt_debug(int argc, char **argv)
2491 {
2492         int rc;
2493
2494         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
2495         if (rc)
2496                 return rc;
2497
2498         return Parser_execarg(argc - 1, &argv[1], debug_cmds);
2499 }
2500
2501 static int jt_global(int argc, char **argv)
2502 {
2503         int rc;
2504
2505         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
2506         if (rc)
2507                 return rc;
2508
2509         return Parser_execarg(argc - 1, &argv[1], global_cmds);
2510 }
2511
2512 static int jt_peers(int argc, char **argv)
2513 {
2514         int rc;
2515
2516         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
2517         if (rc)
2518                 return rc;
2519
2520         return Parser_execarg(argc - 1, &argv[1], peer_cmds);
2521 }
2522
2523 static int jt_set(int argc, char **argv)
2524 {
2525         int rc;
2526
2527         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
2528         if (rc)
2529                 return rc;
2530
2531         return Parser_execarg(argc - 1, &argv[1], set_cmds);
2532 }
2533
2534 static int jt_udsp(int argc, char **argv)
2535 {
2536         int rc;
2537
2538         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
2539         if (rc)
2540                 return rc;
2541
2542         return Parser_execarg(argc - 1, &argv[1], udsp_cmds);
2543 }
2544
2545 static int jt_import(int argc, char **argv)
2546 {
2547         char *file = NULL;
2548         struct cYAML *err_rc = NULL;
2549         struct cYAML *show_rc = NULL;
2550         int rc = 0, return_rc = 0, opt, opt_found = 0;
2551         char cmd = 'a';
2552
2553         const char *const short_options = "adseh";
2554         static const struct option long_options[] = {
2555                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
2556                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
2557                 { .name = "show", .has_arg = no_argument, .val = 's' },
2558                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
2559                 { .name = "help", .has_arg = no_argument, .val = 'h' },
2560                 { .name = NULL } };
2561
2562         while ((opt = getopt_long(argc, argv, short_options,
2563                                    long_options, NULL)) != -1) {
2564                 opt_found = 1;
2565                 switch (opt) {
2566                 case 'a':
2567                         cmd = opt;
2568                         break;
2569                 case 'd':
2570                 case 's':
2571                         cmd = opt;
2572                         break;
2573                 case 'e':
2574                         cmd = opt;
2575                         break;
2576                 case 'h':
2577                         printf("import FILE\n"
2578                                "import < FILE : import a file\n"
2579                                "\t--add: add configuration\n"
2580                                "\t--del: delete configuration\n"
2581                                "\t--show: show configuration\n"
2582                                "\t--exec: execute command\n"
2583                                "\t--help: display this help\n"
2584                                "If no command option is given then --add"
2585                                " is assumed by default\n");
2586                         return 0;
2587                 default:
2588                         return 0;
2589                 }
2590         }
2591
2592         /* grab the file name if one exists */
2593         if (opt_found && argc == 3)
2594                 file = argv[2];
2595         else if (!opt_found && argc == 2)
2596                 file = argv[1];
2597
2598         switch (cmd) {
2599         case 'a':
2600                 rc = lustre_yaml_config(file, &err_rc);
2601                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
2602                 cYAML_print_tree(show_rc);
2603                 cYAML_free_tree(show_rc);
2604                 break;
2605         case 'd':
2606                 rc = lustre_yaml_del(file, &err_rc);
2607                 break;
2608         case 's':
2609                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
2610                 cYAML_print_tree(show_rc);
2611                 cYAML_free_tree(show_rc);
2612                 break;
2613         case 'e':
2614                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
2615                 cYAML_print_tree(show_rc);
2616                 cYAML_free_tree(show_rc);
2617                 break;
2618         }
2619
2620         if (rc || return_rc) {
2621                 cYAML_print_tree2file(stderr, err_rc);
2622                 cYAML_free_tree(err_rc);
2623         }
2624
2625         return rc;
2626 }
2627
2628 static int jt_export(int argc, char **argv)
2629 {
2630         struct cYAML *show_rc = NULL;
2631         struct cYAML *err_rc = NULL;
2632         int rc;
2633         FILE *f = NULL;
2634         int opt;
2635         bool backup = false;
2636         char *file = NULL;
2637
2638         const char *const short_options = "bh";
2639         static const struct option long_options[] = {
2640                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
2641                 { .name = "help", .has_arg = no_argument, .val = 'h' },
2642                 { .name = NULL } };
2643
2644         while ((opt = getopt_long(argc, argv, short_options,
2645                                    long_options, NULL)) != -1) {
2646                 switch (opt) {
2647                 case 'b':
2648                         backup = true;
2649                         break;
2650                 case 'h':
2651                 default:
2652                         printf("export > FILE.yaml : export configuration\n"
2653                                "\t--backup: export only what's necessary for reconfig\n"
2654                                "\t--help: display this help\n");
2655                         return 0;
2656                 }
2657         }
2658
2659         if (backup && argc >= 3)
2660                 file = argv[2];
2661         else if (!backup && argc >= 2)
2662                 file = argv[1];
2663         else
2664                 f = stdout;
2665
2666         if (file) {
2667                 f = fopen(file, "w");
2668                 if (f == NULL)
2669                         return -1;
2670         }
2671
2672         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
2673         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2674                 cYAML_print_tree2file(stderr, err_rc);
2675                 cYAML_free_tree(err_rc);
2676                 err_rc = NULL;
2677         }
2678
2679         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
2680                                     &err_rc, backup);
2681         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2682                 cYAML_print_tree2file(stderr, err_rc);
2683                 cYAML_free_tree(err_rc);
2684                 err_rc = NULL;
2685         }
2686
2687         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
2688         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2689                 cYAML_print_tree2file(stderr, err_rc);
2690                 cYAML_free_tree(err_rc);
2691                 err_rc = NULL;
2692         }
2693
2694         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
2695         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2696                 cYAML_print_tree2file(stderr, err_rc);
2697                 cYAML_free_tree(err_rc);
2698                 err_rc = NULL;
2699         }
2700
2701         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
2702         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2703                 cYAML_print_tree2file(stderr, err_rc);
2704                 cYAML_free_tree(err_rc);
2705                 err_rc = NULL;
2706         }
2707
2708         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
2709         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2710                 cYAML_print_tree2file(stderr, err_rc);
2711                 cYAML_free_tree(err_rc);
2712                 err_rc = NULL;
2713         }
2714
2715         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
2716         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2717                 cYAML_print_tree2file(stderr, err_rc);
2718                 cYAML_free_tree(err_rc);
2719                 err_rc = NULL;
2720         }
2721
2722         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
2723         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2724                 cYAML_print_tree2file(stderr, err_rc);
2725                 cYAML_free_tree(err_rc);
2726                 err_rc = NULL;
2727         }
2728
2729         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
2730         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2731                 cYAML_print_tree2file(stderr, err_rc);
2732                 err_rc = NULL;
2733         }
2734
2735         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
2736         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2737                 cYAML_print_tree2file(stderr, err_rc);
2738                 err_rc = NULL;
2739         }
2740
2741         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
2742         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2743                 cYAML_print_tree2file(stderr, err_rc);
2744                 err_rc = NULL;
2745         }
2746
2747         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
2748         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2749                 cYAML_print_tree2file(stderr, err_rc);
2750                 err_rc = NULL;
2751         }
2752
2753         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
2754         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2755                 cYAML_print_tree2file(stderr, err_rc);
2756                 err_rc = NULL;
2757         }
2758
2759         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
2760         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2761                 cYAML_print_tree2file(stderr, err_rc);
2762                 err_rc = NULL;
2763         }
2764
2765         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
2766         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2767                 cYAML_print_tree2file(stderr, err_rc);
2768                 cYAML_free_tree(err_rc);
2769                 err_rc = NULL;
2770         }
2771
2772         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
2773         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2774                 cYAML_print_tree2file(stderr, err_rc);
2775                 cYAML_free_tree(err_rc);
2776                 err_rc = NULL;
2777         }
2778
2779         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
2780         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2781                 cYAML_print_tree2file(stderr, err_rc);
2782                 cYAML_free_tree(err_rc);
2783                 err_rc = NULL;
2784         }
2785
2786         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
2787         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2788                 cYAML_print_tree2file(stderr, err_rc);
2789                 cYAML_free_tree(err_rc);
2790                 err_rc = NULL;
2791         }
2792
2793         if (show_rc != NULL) {
2794                 cYAML_print_tree2file(f, show_rc);
2795                 cYAML_free_tree(show_rc);
2796         }
2797
2798         if (argc >= 2)
2799                 fclose(f);
2800
2801         return 0;
2802 }
2803
2804 static int jt_peer_nid_common(int argc, char **argv, int cmd)
2805 {
2806         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
2807         bool is_mr = true;
2808         char *prim_nid = NULL, *nidstr = NULL;
2809         char err_str[LNET_MAX_STR_LEN] = "Error";
2810         struct cYAML *err_rc = NULL;
2811
2812         const char *const short_opts = "k:mn:";
2813         const struct option long_opts[] = {
2814         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
2815         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
2816         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
2817         { .name = NULL } };
2818
2819         rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
2820         if (rc)
2821                 return rc;
2822
2823         while ((opt = getopt_long(argc, argv, short_opts,
2824                                   long_opts, NULL)) != -1) {
2825                 switch (opt) {
2826                 case 'k':
2827                         prim_nid = optarg;
2828                         break;
2829                 case 'n':
2830                         nidstr = optarg;
2831                         break;
2832                 case 'm':
2833                         if (cmd == LNETCTL_DEL_CMD) {
2834                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2835                                 snprintf(err_str, LNET_MAX_STR_LEN,
2836                                          "Unrecognized option '-%c'", opt);
2837                                 goto build_error;
2838                         }
2839                         is_mr = false;
2840                         break;
2841                 case '?':
2842                         print_help(peer_cmds, "peer",
2843                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
2844                 default:
2845                         return 0;
2846                 }
2847         }
2848
2849         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
2850                                      -1, &err_rc);
2851         if (rc != LUSTRE_CFG_RC_NO_ERR)
2852                 goto out;
2853
2854 build_error:
2855         cYAML_build_error(rc, -1, "peer",
2856                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
2857                           err_str, &err_rc);
2858
2859 out:
2860         if (rc != LUSTRE_CFG_RC_NO_ERR)
2861                 cYAML_print_tree2file(stderr, err_rc);
2862
2863         cYAML_free_tree(err_rc);
2864
2865         return rc;
2866 }
2867
2868 static int jt_add_peer_nid(int argc, char **argv)
2869 {
2870         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
2871 }
2872
2873 static int jt_del_peer_nid(int argc, char **argv)
2874 {
2875         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
2876 }
2877
2878 static int jt_show_peer(int argc, char **argv)
2879 {
2880         char *nid = NULL;
2881         int rc, opt;
2882         struct cYAML *err_rc = NULL, *show_rc = NULL;
2883         long int detail = 0;
2884
2885         const char *const short_opts = "hn:v::";
2886         const struct option long_opts[] = {
2887         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
2888         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
2889         { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
2890         { .name = NULL } };
2891
2892         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
2893         if (rc)
2894                 return rc;
2895
2896         while ((opt = getopt_long(argc, argv, short_opts,
2897                                   long_opts, NULL)) != -1) {
2898                 switch (opt) {
2899                 case 'n':
2900                         nid = optarg;
2901                         break;
2902                 case 'v':
2903                         if ((!optarg) && (argv[optind] != NULL) &&
2904                             (argv[optind][0] != '-')) {
2905                                 if (parse_long(argv[optind++], &detail) != 0)
2906                                         detail = 1;
2907                         } else {
2908                                 detail = 1;
2909                         }
2910                         break;
2911                 case '?':
2912                         print_help(peer_cmds, "peer", "show");
2913                 default:
2914                         return 0;
2915                 }
2916         }
2917
2918         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
2919                                    false);
2920
2921         if (rc != LUSTRE_CFG_RC_NO_ERR)
2922                 cYAML_print_tree2file(stderr, err_rc);
2923         else if (show_rc)
2924                 cYAML_print_tree(show_rc);
2925
2926         cYAML_free_tree(err_rc);
2927         cYAML_free_tree(show_rc);
2928
2929         return rc;
2930 }
2931
2932 static int jt_list_peer(int argc, char **argv)
2933 {
2934         int rc;
2935         struct cYAML *err_rc = NULL, *list_rc = NULL;
2936
2937         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
2938         if (rc)
2939                 return rc;
2940
2941         rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
2942
2943         if (rc != LUSTRE_CFG_RC_NO_ERR)
2944                 cYAML_print_tree2file(stderr, err_rc);
2945         else if (list_rc)
2946                 cYAML_print_tree(list_rc);
2947
2948         cYAML_free_tree(err_rc);
2949         cYAML_free_tree(list_rc);
2950
2951         return rc;
2952 }
2953
2954 static int jt_ping(int argc, char **argv)
2955 {
2956         struct cYAML *err_rc = NULL;
2957         struct cYAML *show_rc = NULL;
2958         int timeout = 1000;
2959         int rc = 0, opt;
2960         char *src_nidstr = NULL;
2961
2962         const char *const short_options = "hs:t:";
2963         const struct option long_options[] = {
2964         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
2965         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
2966         { .name = "source",     .has_arg = required_argument,   .val = 's' },
2967         { .name = NULL } };
2968
2969         while ((opt = getopt_long(argc, argv, short_options,
2970                                   long_options, NULL)) != -1) {
2971                 switch (opt) {
2972                 case 's':
2973                         src_nidstr = optarg;
2974                         break;
2975                 case 't':
2976                         timeout = 1000 * atol(optarg);
2977                         break;
2978                 case 'h':
2979                         printf("ping nid[,nid,...]\n"
2980                                "\t --source: source nid\n"
2981                                "\t --timeout: ping timeout\n"
2982                                "\t --help: display this help\n");
2983                         return 0;
2984                 default:
2985                         return 0;
2986                 }
2987         }
2988
2989         for (; optind < argc; optind++)
2990                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
2991                                           &show_rc, &err_rc);
2992
2993         if (show_rc)
2994                 cYAML_print_tree(show_rc);
2995
2996         if (err_rc)
2997                 cYAML_print_tree2file(stderr, err_rc);
2998
2999         cYAML_free_tree(err_rc);
3000         cYAML_free_tree(show_rc);
3001
3002         return rc;
3003 }
3004
3005 static int jt_discover(int argc, char **argv)
3006 {
3007         struct cYAML *err_rc = NULL;
3008         struct cYAML *show_rc = NULL;
3009         int force = 0;
3010         int rc = 0, opt;
3011
3012         const char *const short_options = "fh";
3013         const struct option long_options[] = {
3014                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
3015                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
3016                 { .name = NULL } };
3017
3018         while ((opt = getopt_long(argc, argv, short_options,
3019                                   long_options, NULL)) != -1) {
3020                 switch (opt) {
3021                 case 'f':
3022                         force = 1;
3023                         break;
3024                 case 'h':
3025                         printf("discover nid[,nid,...]\n"
3026                                "\t --force: force discovery\n"
3027                                "\t --help: display this help\n");
3028                         return 0;
3029                 default:
3030                         return 0;
3031                 }
3032         }
3033
3034         for (; optind < argc; optind++)
3035                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
3036                                               &err_rc);
3037
3038         if (show_rc)
3039                 cYAML_print_tree(show_rc);
3040
3041         if (err_rc)
3042                 cYAML_print_tree2file(stderr, err_rc);
3043
3044         cYAML_free_tree(err_rc);
3045         cYAML_free_tree(show_rc);
3046
3047         return rc;
3048 }
3049
3050 static int jt_add_udsp(int argc, char **argv)
3051 {
3052         char *src = NULL, *dst = NULL, *rte = NULL;
3053         struct cYAML *err_rc = NULL;
3054         union lnet_udsp_action udsp_action;
3055         long int idx = -1, priority = -1;
3056         int opt, rc = 0;
3057         char *action_type = "pref";
3058
3059         const char *const short_options = "s:d:r:p:i:";
3060         static const struct option long_options[] = {
3061         { .name = "src",         .has_arg = required_argument, .val = 's' },
3062         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
3063         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
3064         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
3065         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
3066         { .name = NULL } };
3067
3068         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
3069         if (rc)
3070                 return rc;
3071
3072         while ((opt = getopt_long(argc, argv, short_options,
3073                                   long_options, NULL)) != -1) {
3074                 switch (opt) {
3075                 case 's':
3076                         src = optarg;
3077                         break;
3078                 case 'd':
3079                         dst = optarg;
3080                         break;
3081                 case 'r':
3082                         rte = optarg;
3083                         break;
3084                 case 'p':
3085                         rc = parse_long(optarg, &priority);
3086                         if (rc != 0)
3087                                 priority = -1;
3088                         action_type = "priority";
3089                         udsp_action.udsp_priority = priority;
3090                         break;
3091                 case 'i':
3092                         rc = parse_long(optarg, &idx);
3093                         if (rc != 0)
3094                                 idx = 0;
3095                         break;
3096                 case '?':
3097                         print_help(udsp_cmds, "udsp", "add");
3098                 default:
3099                         return 0;
3100                 }
3101         }
3102
3103         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
3104                                   idx, -1, &err_rc);
3105
3106         if (rc != LUSTRE_CFG_RC_NO_ERR)
3107                 cYAML_print_tree2file(stderr, err_rc);
3108
3109         cYAML_free_tree(err_rc);
3110
3111         return rc;
3112 }
3113
3114 static int jt_del_udsp(int argc, char **argv)
3115 {
3116         struct cYAML *err_rc = NULL;
3117         long int idx = 0;
3118         int opt, rc = 0;
3119
3120         const char *const short_options = "i:";
3121         static const struct option long_options[] = {
3122         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
3123         { .name = NULL } };
3124
3125         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
3126         if (rc)
3127                 return rc;
3128
3129         while ((opt = getopt_long(argc, argv, short_options,
3130                                   long_options, NULL)) != -1) {
3131                 switch (opt) {
3132                 case 'i':
3133                         rc = parse_long(optarg, &idx);
3134                         if (rc != 0)
3135                                 idx = 0;
3136                         break;
3137                 case '?':
3138                         print_help(udsp_cmds, "udsp", "add");
3139                 default:
3140                         return 0;
3141                 }
3142         }
3143
3144         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
3145         if (rc != LUSTRE_CFG_RC_NO_ERR)
3146                 cYAML_print_tree2file(stderr, err_rc);
3147
3148         cYAML_free_tree(err_rc);
3149
3150         return rc;
3151 }
3152
3153 static int lnetctl_list_commands(int argc, char **argv)
3154 {
3155         char buffer[81] = ""; /* 80 printable chars + terminating NUL */
3156
3157         Parser_list_commands(cmd_list, buffer, sizeof(buffer), NULL, 0, 4);
3158
3159         return 0;
3160 }
3161
3162 int main(int argc, char **argv)
3163 {
3164         int rc = 0;
3165         struct cYAML *err_rc = NULL;
3166
3167         rc = lustre_lnet_config_lib_init();
3168         if (rc < 0) {
3169                 cYAML_build_error(-1, -1, "lnetctl", "startup",
3170                                   "cannot register LNet device", &err_rc);
3171                 cYAML_print_tree2file(stderr, err_rc);
3172                 return rc;
3173         }
3174
3175         Parser_init("lnetctl > ", cmd_list);
3176         if (argc > 1) {
3177                 rc = Parser_execarg(argc - 1, &argv[1], cmd_list);
3178                 goto errorout;
3179         }
3180
3181         Parser_commands();
3182
3183 errorout:
3184         return rc;
3185 }