Whamcloud - gitweb
New tag 2.15.63
[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                                 struct lnet_dlc_network_descr *nw_descr)
1192 {
1193         yaml_event_t event;
1194         char num[23];
1195         int rc;
1196
1197         if (tunables->lt_cmn.lct_peer_timeout < 0 &&
1198             tunables->lt_cmn.lct_peer_tx_credits <= 0 &&
1199             tunables->lt_cmn.lct_peer_rtr_credits <= 0 &&
1200             tunables->lt_cmn.lct_max_tx_credits <= 0)
1201                 goto skip_general_settings;
1202
1203         yaml_scalar_event_initialize(&event, NULL,
1204                                      (yaml_char_t *)YAML_STR_TAG,
1205                                      (yaml_char_t *)"tunables",
1206                                      strlen("tunables"), 1, 0,
1207                                      YAML_PLAIN_SCALAR_STYLE);
1208         rc = yaml_emitter_emit(output, &event);
1209         if (rc == 0)
1210                 goto error;
1211
1212         yaml_mapping_start_event_initialize(&event, NULL,
1213                                             (yaml_char_t *)YAML_MAP_TAG,
1214                                             1, YAML_ANY_MAPPING_STYLE);
1215         rc = yaml_emitter_emit(output, &event);
1216         if (rc == 0)
1217                 goto error;
1218
1219         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1220                 yaml_scalar_event_initialize(&event, NULL,
1221                                              (yaml_char_t *)YAML_STR_TAG,
1222                                              (yaml_char_t *)"peer_timeout",
1223                                              strlen("peer_timeout"), 1, 0,
1224                                              YAML_PLAIN_SCALAR_STYLE);
1225                 rc = yaml_emitter_emit(output, &event);
1226                 if (rc == 0)
1227                         goto error;
1228
1229                 snprintf(num, sizeof(num), "%u",
1230                          tunables->lt_cmn.lct_peer_timeout);
1231                 yaml_scalar_event_initialize(&event, NULL,
1232                                              (yaml_char_t *)YAML_INT_TAG,
1233                                              (yaml_char_t *)num,
1234                                              strlen(num), 1, 0,
1235                                              YAML_PLAIN_SCALAR_STYLE);
1236                 rc = yaml_emitter_emit(output, &event);
1237                 if (rc == 0)
1238                         goto error;
1239         }
1240
1241         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1242                 yaml_scalar_event_initialize(&event, NULL,
1243                                              (yaml_char_t *)YAML_STR_TAG,
1244                                              (yaml_char_t *)"peer_credits",
1245                                              strlen("peer_credits"), 1, 0,
1246                                              YAML_PLAIN_SCALAR_STYLE);
1247                 rc = yaml_emitter_emit(output, &event);
1248                 if (rc == 0)
1249                         goto error;
1250
1251                 snprintf(num, sizeof(num), "%u",
1252                          tunables->lt_cmn.lct_peer_tx_credits);
1253                 yaml_scalar_event_initialize(&event, NULL,
1254                                              (yaml_char_t *)YAML_INT_TAG,
1255                                              (yaml_char_t *)num,
1256                                              strlen(num), 1, 0,
1257                                              YAML_PLAIN_SCALAR_STYLE);
1258                 rc = yaml_emitter_emit(output, &event);
1259                 if (rc == 0)
1260                         goto error;
1261         }
1262
1263         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1264                 yaml_scalar_event_initialize(&event, NULL,
1265                                              (yaml_char_t *)YAML_STR_TAG,
1266                                              (yaml_char_t *)"peer_buffer_credits",
1267                                              strlen("peer_buffer_credits"), 1, 0,
1268                                              YAML_PLAIN_SCALAR_STYLE);
1269                 rc = yaml_emitter_emit(output, &event);
1270                 if (rc == 0)
1271                         goto error;
1272
1273                 snprintf(num, sizeof(num), "%u",
1274                          tunables->lt_cmn.lct_peer_rtr_credits);
1275                 yaml_scalar_event_initialize(&event, NULL,
1276                                              (yaml_char_t *)YAML_INT_TAG,
1277                                              (yaml_char_t *)num,
1278                                              strlen(num), 1, 0,
1279                                              YAML_PLAIN_SCALAR_STYLE);
1280                 rc = yaml_emitter_emit(output, &event);
1281                 if (rc == 0)
1282                         goto error;
1283         }
1284
1285         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1286                 yaml_scalar_event_initialize(&event, NULL,
1287                                              (yaml_char_t *)YAML_STR_TAG,
1288                                              (yaml_char_t *)"credits",
1289                                              strlen("credits"), 1, 0,
1290                                              YAML_PLAIN_SCALAR_STYLE);
1291                 rc = yaml_emitter_emit(output, &event);
1292                 if (rc == 0)
1293                         goto error;
1294
1295                 snprintf(num, sizeof(num), "%u",
1296                          tunables->lt_cmn.lct_max_tx_credits);
1297                 yaml_scalar_event_initialize(&event, NULL,
1298                                              (yaml_char_t *)YAML_INT_TAG,
1299                                              (yaml_char_t *)num,
1300                                              strlen(num), 1, 0,
1301                                              YAML_PLAIN_SCALAR_STYLE);
1302                 rc = yaml_emitter_emit(output, &event);
1303                 if (rc == 0)
1304                         goto error;
1305         }
1306
1307         yaml_mapping_end_event_initialize(&event);
1308         rc = yaml_emitter_emit(output, &event);
1309         if (rc == 0)
1310                 goto error;
1311
1312 skip_general_settings:
1313         if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1314 #ifdef HAVE_KFILND
1315             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0 ||
1316 #endif
1317             tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1318                 yaml_scalar_event_initialize(&event, NULL,
1319                                              (yaml_char_t *)YAML_STR_TAG,
1320                                              (yaml_char_t *)"lnd tunables",
1321                                              strlen("lnd tunables"), 1, 0,
1322                                              YAML_PLAIN_SCALAR_STYLE);
1323                 rc = yaml_emitter_emit(output, &event);
1324                 if (rc == 0)
1325                         goto error;
1326
1327                 yaml_mapping_start_event_initialize(&event, NULL,
1328                                                     (yaml_char_t *)YAML_MAP_TAG,
1329                                                     1, YAML_ANY_MAPPING_STYLE);
1330                 rc = yaml_emitter_emit(output, &event);
1331                 if (rc == 0)
1332                         goto error;
1333 #ifdef HAVE_KFILND
1334                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1335                         yaml_scalar_event_initialize(&event, NULL,
1336                                                      (yaml_char_t *)YAML_STR_TAG,
1337                                                      (yaml_char_t *)"auth_key",
1338                                                      strlen("auth_key"), 1, 0,
1339                                                      YAML_PLAIN_SCALAR_STYLE);
1340                         rc = yaml_emitter_emit(output, &event);
1341                         if (rc == 0)
1342                                 goto error;
1343
1344                         snprintf(num, sizeof(num), "%u",
1345                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1346
1347                         yaml_scalar_event_initialize(&event, NULL,
1348                                                      (yaml_char_t *)YAML_INT_TAG,
1349                                                      (yaml_char_t *)num,
1350                                                      strlen(num), 1, 0,
1351                                                      YAML_PLAIN_SCALAR_STYLE);
1352                         rc = yaml_emitter_emit(output, &event);
1353                         if (rc == 0)
1354                                 goto error;
1355                 }
1356 #endif
1357                 if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1358                     tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1359                         int cpp = 0;
1360
1361                         yaml_scalar_event_initialize(&event, NULL,
1362                                                      (yaml_char_t *)YAML_STR_TAG,
1363                                                      (yaml_char_t *)"conns_per_peer",
1364                                                      strlen("conns_per_peer"), 1, 0,
1365                                                      YAML_PLAIN_SCALAR_STYLE);
1366                         rc = yaml_emitter_emit(output, &event);
1367                         if (rc == 0)
1368                                 goto error;
1369
1370                         if (LNET_NETTYP(nw_descr->nw_id) == SOCKLND)
1371                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1372                         else if (LNET_NETTYP(nw_descr->nw_id) == O2IBLND)
1373                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer;
1374                         snprintf(num, sizeof(num), "%u", cpp);
1375
1376                         yaml_scalar_event_initialize(&event, NULL,
1377                                                      (yaml_char_t *)YAML_INT_TAG,
1378                                                      (yaml_char_t *)num,
1379                                                      strlen(num), 1, 0,
1380                                                      YAML_PLAIN_SCALAR_STYLE);
1381                         rc = yaml_emitter_emit(output, &event);
1382                         if (rc == 0)
1383                                 goto error;
1384                 }
1385
1386                 yaml_mapping_end_event_initialize(&event);
1387                 rc = yaml_emitter_emit(output, &event);
1388         }
1389 error:
1390         return rc;
1391 }
1392
1393 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1394                                struct lnet_dlc_network_descr *nw_descr,
1395                                struct lnet_ioctl_config_lnd_tunables *tunables,
1396                                struct cfs_expr_list *global_cpts,
1397                                int flags)
1398 {
1399         struct lnet_dlc_intf_descr *intf;
1400         struct nl_sock *sk = NULL;
1401         yaml_emitter_t output;
1402         yaml_parser_t reply;
1403         yaml_event_t event;
1404         int rc;
1405
1406         if (!ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1407                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'",
1408                         (!nw_descr) ? "network , interface" :
1409                         (nw_descr->nw_id == 0) ? "network" : "interface");
1410                 return -EINVAL;
1411         }
1412
1413         if ((flags == NLM_F_CREATE) && list_empty(&nw_descr->nw_intflist)) {
1414                 fprintf(stdout, "creating a local NI needs at least one interface");
1415                 return -EINVAL;
1416         }
1417
1418         /* Create Netlink emitter to send request to kernel */
1419         sk = nl_socket_alloc();
1420         if (!sk)
1421                 return -EOPNOTSUPP;
1422
1423         /* Setup parser to receive Netlink packets */
1424         rc = yaml_parser_initialize(&reply);
1425         if (rc == 0) {
1426                 nl_socket_free(sk);
1427                 return -EOPNOTSUPP;
1428         }
1429
1430         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1431         if (rc == 0)
1432                 goto free_reply;
1433
1434         /* Create Netlink emitter to send request to kernel */
1435         rc = yaml_emitter_initialize(&output);
1436         if (rc == 0)
1437                 goto free_reply;
1438
1439         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1440                                              LNET_GENL_VERSION, LNET_CMD_NETS,
1441                                              flags);
1442         if (rc == 0)
1443                 goto emitter_error;
1444
1445         yaml_emitter_open(&output);
1446         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
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 *)"net",
1461                                      strlen("net"), 1, 0,
1462                                      YAML_PLAIN_SCALAR_STYLE);
1463         rc = yaml_emitter_emit(&output, &event);
1464         if (rc == 0)
1465                 goto emitter_error;
1466
1467         if (net_id || ip2net) {
1468                 char *key = net_id ? "net type" : "ip2net";
1469                 char *value = net_id ? net_id : ip2net;
1470
1471                 yaml_sequence_start_event_initialize(&event, NULL,
1472                                                      (yaml_char_t *)YAML_SEQ_TAG,
1473                                                      1, YAML_ANY_SEQUENCE_STYLE);
1474                 rc = yaml_emitter_emit(&output, &event);
1475                 if (rc == 0)
1476                         goto emitter_error;
1477
1478                 yaml_mapping_start_event_initialize(&event, NULL,
1479                                                     (yaml_char_t *)YAML_MAP_TAG,
1480                                                     1, YAML_ANY_MAPPING_STYLE);
1481                 rc = yaml_emitter_emit(&output, &event);
1482                 if (rc == 0)
1483                         goto emitter_error;
1484
1485                 yaml_scalar_event_initialize(&event, NULL,
1486                                              (yaml_char_t *)YAML_STR_TAG,
1487                                              (yaml_char_t *)key,
1488                                              strlen(key),
1489                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
1490                 rc = yaml_emitter_emit(&output, &event);
1491                 if (rc == 0)
1492                         goto emitter_error;
1493
1494                 yaml_scalar_event_initialize(&event, NULL,
1495                                              (yaml_char_t *)YAML_STR_TAG,
1496                                              (yaml_char_t *)value,
1497                                              strlen(value), 1, 0,
1498                                              YAML_PLAIN_SCALAR_STYLE);
1499                 rc = yaml_emitter_emit(&output, &event);
1500                 if (rc == 0)
1501                         goto emitter_error;
1502         } else {
1503                 yaml_scalar_event_initialize(&event, NULL,
1504                                              (yaml_char_t *)YAML_STR_TAG,
1505                                              (yaml_char_t *)"",
1506                                              strlen(""), 1, 0,
1507                                              YAML_PLAIN_SCALAR_STYLE);
1508                 rc = yaml_emitter_emit(&output, &event);
1509                 if (rc == 0)
1510                         goto emitter_error;
1511
1512                 goto no_net_id;
1513         }
1514
1515         if (list_empty(&nw_descr->nw_intflist))
1516                 goto skip_intf;
1517
1518         yaml_scalar_event_initialize(&event, NULL,
1519                                      (yaml_char_t *)YAML_STR_TAG,
1520                                      (yaml_char_t *)"local NI(s)",
1521                                      strlen("local NI(s)"), 1, 0,
1522                                      YAML_PLAIN_SCALAR_STYLE);
1523         rc = yaml_emitter_emit(&output, &event);
1524         if (rc == 0)
1525                 goto emitter_error;
1526
1527         yaml_sequence_start_event_initialize(&event, NULL,
1528                                              (yaml_char_t *)YAML_SEQ_TAG,
1529                                              1, YAML_ANY_SEQUENCE_STYLE);
1530         rc = yaml_emitter_emit(&output, &event);
1531         if (rc == 0)
1532                 goto emitter_error;
1533
1534         list_for_each_entry(intf, &nw_descr->nw_intflist,
1535                             intf_on_network) {
1536                 yaml_mapping_start_event_initialize(&event, NULL,
1537                                                     (yaml_char_t *)YAML_MAP_TAG,
1538                                                     1, YAML_ANY_MAPPING_STYLE);
1539                 rc = yaml_emitter_emit(&output, &event);
1540                 if (rc == 0)
1541                         goto emitter_error;
1542
1543                 yaml_scalar_event_initialize(&event, NULL,
1544                                              (yaml_char_t *)YAML_STR_TAG,
1545                                              (yaml_char_t *)"interfaces",
1546                                              strlen("interfaces"), 1, 0,
1547                                              YAML_PLAIN_SCALAR_STYLE);
1548                 rc = yaml_emitter_emit(&output, &event);
1549                 if (rc == 0)
1550                         goto emitter_error;
1551
1552                 yaml_mapping_start_event_initialize(&event, NULL,
1553                                                     (yaml_char_t *)YAML_MAP_TAG,
1554                                                     1, YAML_ANY_MAPPING_STYLE);
1555                 rc = yaml_emitter_emit(&output, &event);
1556                 if (rc == 0)
1557                         goto emitter_error;
1558
1559                 yaml_scalar_event_initialize(&event, NULL,
1560                                              (yaml_char_t *)YAML_STR_TAG,
1561                                              (yaml_char_t *)"0",
1562                                              strlen("0"), 1, 0,
1563                                              YAML_PLAIN_SCALAR_STYLE);
1564                 rc = yaml_emitter_emit(&output, &event);
1565                 if (rc == 0)
1566                         goto emitter_error;
1567
1568                 yaml_scalar_event_initialize(&event, NULL,
1569                                              (yaml_char_t *)YAML_STR_TAG,
1570                                              (yaml_char_t *)intf->intf_name,
1571                                              strlen(intf->intf_name), 1, 0,
1572                                              YAML_PLAIN_SCALAR_STYLE);
1573                 rc = yaml_emitter_emit(&output, &event);
1574                 if (rc == 0)
1575                         goto emitter_error;
1576
1577                 yaml_mapping_end_event_initialize(&event);
1578                 rc = yaml_emitter_emit(&output, &event);
1579                 if (rc == 0)
1580                         goto emitter_error;
1581
1582                 if (tunables) {
1583                         rc = yaml_add_ni_tunables(&output, tunables, nw_descr);
1584                         if (rc == 0)
1585                                 goto emitter_error;
1586                 }
1587
1588                 if (global_cpts) {
1589                         __u32 *cpt_array;
1590                         int count, i;
1591
1592                         yaml_scalar_event_initialize(&event, NULL,
1593                                                      (yaml_char_t *)YAML_STR_TAG,
1594                                                      (yaml_char_t *)"CPT",
1595                                                      strlen("CPT"), 1, 0,
1596                                                      YAML_PLAIN_SCALAR_STYLE);
1597                         rc = yaml_emitter_emit(&output, &event);
1598                         if (rc == 0)
1599                                 goto emitter_error;
1600
1601                         yaml_sequence_start_event_initialize(&event, NULL,
1602                                                              (yaml_char_t *)YAML_SEQ_TAG,
1603                                                              1,
1604                                                              YAML_FLOW_SEQUENCE_STYLE);
1605                         rc = yaml_emitter_emit(&output, &event);
1606                         if (rc == 0)
1607                                 goto emitter_error;
1608
1609                         count = cfs_expr_list_values(global_cpts,
1610                                                      LNET_MAX_SHOW_NUM_CPT,
1611                                                      &cpt_array);
1612                         for (i = 0; i < count; i++) {
1613                                 char core[23];
1614
1615                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
1616                                 yaml_scalar_event_initialize(&event, NULL,
1617                                                              (yaml_char_t *)YAML_STR_TAG,
1618                                                              (yaml_char_t *)core,
1619                                                              strlen(core), 1, 0,
1620                                                              YAML_PLAIN_SCALAR_STYLE);
1621                                 rc = yaml_emitter_emit(&output, &event);
1622                                 if (rc == 0)
1623                                         goto emitter_error;
1624                         }
1625
1626                         yaml_sequence_end_event_initialize(&event);
1627                         rc = yaml_emitter_emit(&output, &event);
1628                         if (rc == 0)
1629                                 goto emitter_error;
1630
1631                         cfs_expr_list_free(global_cpts);
1632                         free(cpt_array);
1633                 }
1634
1635                 yaml_mapping_end_event_initialize(&event);
1636                 rc = yaml_emitter_emit(&output, &event);
1637                 if (rc == 0)
1638                         goto emitter_error;
1639         }
1640
1641         yaml_sequence_end_event_initialize(&event);
1642         rc = yaml_emitter_emit(&output, &event);
1643         if (rc == 0)
1644                 goto emitter_error;
1645 skip_intf:
1646         yaml_mapping_end_event_initialize(&event);
1647         rc = yaml_emitter_emit(&output, &event);
1648         if (rc == 0)
1649                 goto emitter_error;
1650
1651         yaml_sequence_end_event_initialize(&event);
1652         rc = yaml_emitter_emit(&output, &event);
1653         if (rc == 0)
1654                 goto emitter_error;
1655 no_net_id:
1656         yaml_mapping_end_event_initialize(&event);
1657         rc = yaml_emitter_emit(&output, &event);
1658         if (rc == 0)
1659                 goto emitter_error;
1660
1661         yaml_document_end_event_initialize(&event, 0);
1662         rc = yaml_emitter_emit(&output, &event);
1663         if (rc == 0)
1664                 goto emitter_error;
1665
1666         rc = yaml_emitter_close(&output);
1667 emitter_error:
1668         if (rc == 0) {
1669                 yaml_emitter_log_error(&output, stderr);
1670                 rc = -EINVAL;
1671         } else {
1672                 yaml_document_t errmsg;
1673
1674                 rc = yaml_parser_load(&reply, &errmsg);
1675         }
1676         yaml_emitter_delete(&output);
1677 free_reply:
1678         if (rc == 0) {
1679                 yaml_lnet_print_error(flags ? "add" : "del", "net",
1680                                       yaml_parser_get_reader_error(&reply));
1681                 rc = -EINVAL;
1682         }
1683         yaml_parser_delete(&reply);
1684         nl_socket_free(sk);
1685
1686         return rc == 1 ? 0 : rc;
1687 }
1688
1689 static int jt_add_ni(int argc, char **argv)
1690 {
1691         char *ip2net = NULL;
1692         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
1693         struct cYAML *err_rc = NULL;
1694         int rc, opt, cpt_rc = -1;
1695         struct lnet_dlc_network_descr nw_descr;
1696         struct cfs_expr_list *global_cpts = NULL;
1697         struct lnet_ioctl_config_lnd_tunables tunables;
1698         bool found = false;
1699         bool skip_mr_route_setup = false;
1700         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:";
1701         static const struct option long_options[] = {
1702         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
1703         { .name = "peer-buffer-credits",
1704                                   .has_arg = required_argument, .val = 'b' },
1705         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
1706         { .name = "if",           .has_arg = required_argument, .val = 'i' },
1707         { .name = "skip-mr-route-setup",
1708                                   .has_arg = no_argument, .val = 'k' },
1709         { .name = "conns-per-peer",
1710                                   .has_arg = required_argument, .val = 'm' },
1711         { .name = "net",          .has_arg = required_argument, .val = 'n' },
1712         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
1713         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
1714         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
1715         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
1716         { .name = NULL } };
1717         char *net_id = NULL;
1718
1719         memset(&tunables, 0, sizeof(tunables));
1720         lustre_lnet_init_nw_descr(&nw_descr);
1721
1722         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
1723         if (rc)
1724                 return rc;
1725
1726         while ((opt = getopt_long(argc, argv, short_options,
1727                                    long_options, NULL)) != -1) {
1728                 switch (opt) {
1729                 case 'a':
1730                         rc = parse_long(optarg, &auth_key);
1731                         if (rc != 0) {
1732                                 /* ignore option */
1733                                 auth_key = -1;
1734                                 continue;
1735                         }
1736                         break;
1737                 case 'b':
1738                         rc = parse_long(optarg, &pbc);
1739                         if (rc != 0) {
1740                                 /* ignore option */
1741                                 pbc = -1;
1742                                 continue;
1743                         }
1744                         break;
1745                 case 'c':
1746                         rc = parse_long(optarg, &pc);
1747                         if (rc != 0) {
1748                                 /* ignore option */
1749                                 pc = -1;
1750                                 continue;
1751                         }
1752                         break;
1753                 case 'i':
1754                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
1755                         if (rc != 0) {
1756                                 cYAML_build_error(-1, -1, "ni", "add",
1757                                                 "bad interface list",
1758                                                 &err_rc);
1759                                 goto failed;
1760                         }
1761                         break;
1762                 case 'k':
1763                         skip_mr_route_setup = true;
1764                         break;
1765                 case 'm':
1766                         rc = parse_long(optarg, &cpp);
1767                         if (rc != 0) {
1768                                 /* ignore option */
1769                                 cpp = -1;
1770                                 continue;
1771                         }
1772                         break;
1773
1774                 case 'n':
1775                         nw_descr.nw_id = libcfs_str2net(optarg);
1776                         net_id = optarg;
1777                         break;
1778                 case 'p':
1779                         ip2net = optarg;
1780                         break;
1781                 case 'r':
1782                         rc = parse_long(optarg, &cre);
1783                         if (rc != 0) {
1784                                 /* ignore option */
1785                                 cre = -1;
1786                                 continue;
1787                         }
1788                         break;
1789                 case 's':
1790                         cpt_rc = cfs_expr_list_parse(optarg,
1791                                                      strlen(optarg), 0,
1792                                                      UINT_MAX, &global_cpts);
1793                         break;
1794                 case 't':
1795                         rc = parse_long(optarg, &pto);
1796                         if (rc != 0) {
1797                                 /* ignore option */
1798                                 pto = -1;
1799                                 continue;
1800                         }
1801                         break;
1802                 case '?':
1803                         print_help(net_cmds, "net", "add");
1804                 default:
1805                         return 0;
1806                 }
1807         }
1808 #ifdef HAVE_KFILND
1809         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
1810                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
1811                 found = true;
1812         }
1813 #endif
1814
1815         if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1)) {
1816                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
1817                 found = true;
1818         } else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1)) {
1819                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
1820                 found = true;
1821         }
1822
1823         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
1824                 tunables.lt_cmn.lct_peer_timeout = pto;
1825                 tunables.lt_cmn.lct_peer_tx_credits = pc;
1826                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
1827                 tunables.lt_cmn.lct_max_tx_credits = cre;
1828                 found = true;
1829         }
1830
1831         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
1832                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
1833
1834         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
1835                                  found ? &tunables : NULL,
1836                                  (cpt_rc == 0) ? global_cpts : NULL,
1837                                  NLM_F_CREATE);
1838         if (rc <= 0) {
1839                 if (rc == -EOPNOTSUPP)
1840                         goto old_api;
1841                 if (global_cpts != NULL)
1842                         cfs_expr_list_free(global_cpts);
1843                 if (rc == 0 && !skip_mr_route_setup)
1844                         rc = lustre_lnet_setup_mrrouting(&err_rc);
1845                 return rc;
1846         }
1847 old_api:
1848         rc = lustre_lnet_config_ni(&nw_descr,
1849                                    (cpt_rc == 0) ? global_cpts: NULL,
1850                                    ip2net, (found) ? &tunables : NULL,
1851                                    cpp, &err_rc);
1852
1853         if (global_cpts != NULL)
1854                 cfs_expr_list_free(global_cpts);
1855
1856 failed:
1857         if (rc != LUSTRE_CFG_RC_NO_ERR)
1858                 cYAML_print_tree2file(stderr, err_rc);
1859
1860         cYAML_free_tree(err_rc);
1861
1862         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
1863                 err_rc = NULL;
1864                 rc = lustre_lnet_setup_mrrouting(&err_rc);
1865
1866                 if (rc != LUSTRE_CFG_RC_NO_ERR)
1867                         cYAML_print_tree2file(stderr, err_rc);
1868
1869                 cYAML_free_tree(err_rc);
1870         }
1871
1872         return rc;
1873 }
1874
1875 static int jt_del_route(int argc, char **argv)
1876 {
1877         char *network = NULL, *gateway = NULL;
1878         struct cYAML *err_rc = NULL;
1879         int rc, opt;
1880
1881         const char *const short_options = "n:g:";
1882         static const struct option long_options[] = {
1883                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
1884                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
1885                 { .name = NULL } };
1886
1887         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
1888         if (rc)
1889                 return rc;
1890
1891         while ((opt = getopt_long(argc, argv, short_options,
1892                                    long_options, NULL)) != -1) {
1893                 switch (opt) {
1894                 case 'n':
1895                         network = optarg;
1896                         break;
1897                 case 'g':
1898                         gateway = optarg;
1899                         break;
1900                 case '?':
1901                         print_help(route_cmds, "route", "del");
1902                 default:
1903                         return 0;
1904                 }
1905         }
1906
1907         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
1908
1909         if (rc != LUSTRE_CFG_RC_NO_ERR)
1910                 cYAML_print_tree2file(stderr, err_rc);
1911
1912         cYAML_free_tree(err_rc);
1913
1914         return rc;
1915 }
1916
1917 static int jt_del_ni(int argc, char **argv)
1918 {
1919         struct cYAML *err_rc = NULL;
1920         int rc, opt;
1921         struct lnet_dlc_network_descr nw_descr;
1922         const char *const short_options = "n:i:";
1923         static const struct option long_options[] = {
1924         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
1925         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
1926         { .name = NULL } };
1927         char *net_id = NULL;
1928
1929         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
1930         if (rc)
1931                 return rc;
1932
1933         lustre_lnet_init_nw_descr(&nw_descr);
1934
1935         while ((opt = getopt_long(argc, argv, short_options,
1936                                    long_options, NULL)) != -1) {
1937                 switch (opt) {
1938                 case 'n':
1939                         nw_descr.nw_id = libcfs_str2net(optarg);
1940                         net_id = optarg;
1941                         break;
1942                 case 'i':
1943                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
1944                         if (rc != 0) {
1945                                 cYAML_build_error(-1, -1, "ni", "add",
1946                                                 "bad interface list",
1947                                                 &err_rc);
1948                                 goto out;
1949                         }
1950                         break;
1951                 case '?':
1952                         print_help(net_cmds, "net", "del");
1953                 default:
1954                         return 0;
1955                 }
1956         }
1957
1958         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, NULL, 0);
1959         if (rc <= 0) {
1960                 if (rc != -EOPNOTSUPP)
1961                         return rc;
1962         }
1963
1964         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
1965 out:
1966         if (rc != LUSTRE_CFG_RC_NO_ERR)
1967                 cYAML_print_tree2file(stderr, err_rc);
1968
1969         cYAML_free_tree(err_rc);
1970
1971         return rc;
1972 }
1973
1974 static int jt_show_route(int argc, char **argv)
1975 {
1976         char *network = NULL, *gateway = NULL;
1977         long int hop = -1, prio = -1;
1978         int detail = 0, rc, opt;
1979         struct cYAML *err_rc = NULL, *show_rc = NULL;
1980
1981         const char *const short_options = "n:g:h:p:v";
1982         static const struct option long_options[] = {
1983         { .name = "net",       .has_arg = required_argument, .val = 'n' },
1984         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1985         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1986         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1987         { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
1988         { .name = NULL } };
1989
1990         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
1991         if (rc)
1992                 return rc;
1993
1994         while ((opt = getopt_long(argc, argv, short_options,
1995                                    long_options, NULL)) != -1) {
1996                 switch (opt) {
1997                 case 'n':
1998                         network = optarg;
1999                         break;
2000                 case 'g':
2001                         gateway = optarg;
2002                         break;
2003                 case 'c':
2004                         rc = parse_long(optarg, &hop);
2005                         if (rc != 0) {
2006                                 /* ignore option */
2007                                 hop = -1;
2008                                 continue;
2009                         }
2010                         break;
2011                 case 'p':
2012                         rc = parse_long(optarg, &prio);
2013                         if (rc != 0) {
2014                                 /* ignore option */
2015                                 prio = -1;
2016                                 continue;
2017                         }
2018                         break;
2019                 case 'v':
2020                         detail = 1;
2021                         break;
2022                 case '?':
2023                         print_help(route_cmds, "route", "show");
2024                 default:
2025                         return 0;
2026                 }
2027         }
2028
2029         rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
2030                                     &show_rc, &err_rc, false);
2031
2032         if (rc != LUSTRE_CFG_RC_NO_ERR)
2033                 cYAML_print_tree2file(stderr, err_rc);
2034         else if (show_rc)
2035                 cYAML_print_tree(show_rc);
2036
2037         cYAML_free_tree(err_rc);
2038         cYAML_free_tree(show_rc);
2039
2040         return rc;
2041 }
2042
2043 static int set_value_helper(int argc, char **argv,
2044                             int (*cb)(int, bool, char*, int, struct cYAML**))
2045 {
2046         char *nid = NULL;
2047         long int healthv = -1;
2048         bool all = false;
2049         int rc, opt;
2050         struct cYAML *err_rc = NULL;
2051
2052         const char *const short_options = "t:n:a";
2053         static const struct option long_options[] = {
2054                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2055                 { .name = "health", .has_arg = required_argument, .val = 't' },
2056                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2057                 { .name = NULL } };
2058
2059         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2060         if (rc)
2061                 return rc;
2062
2063         while ((opt = getopt_long(argc, argv, short_options,
2064                                    long_options, NULL)) != -1) {
2065                 switch (opt) {
2066                 case 'n':
2067                         nid = optarg;
2068                         break;
2069                 case 't':
2070                         if (parse_long(optarg, &healthv) != 0)
2071                                 healthv = -1;
2072                         break;
2073                 case 'a':
2074                         all = true;
2075                         break;
2076                 default:
2077                         return 0;
2078                 }
2079         }
2080
2081         rc = cb(healthv, all, nid, -1, &err_rc);
2082
2083         if (rc != LUSTRE_CFG_RC_NO_ERR)
2084                 cYAML_print_tree2file(stderr, err_rc);
2085
2086         cYAML_free_tree(err_rc);
2087
2088         return rc;
2089 }
2090
2091 static int jt_set_ni_value(int argc, char **argv)
2092 {
2093         char *nid = NULL;
2094         long int healthv = -1, cpp = -1;
2095         bool all = false;
2096         int rc, opt;
2097         struct cYAML *err_rc = NULL;
2098
2099         const char *const short_options = "a:m:n:t:";
2100         static const struct option long_options[] = {
2101         { .name = "all",            .has_arg = no_argument,       .val = 'a' },
2102         { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2103         { .name = "nid",            .has_arg = required_argument, .val = 'n' },
2104         { .name = "health",         .has_arg = required_argument, .val = 't' },
2105         { .name = NULL } };
2106
2107         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2108         if (rc)
2109                 return rc;
2110
2111         while ((opt = getopt_long(argc, argv, short_options,
2112                                    long_options, NULL)) != -1) {
2113                 switch (opt) {
2114                 case 'a':
2115                         all = true;
2116                         break;
2117                 case 'm':
2118                         rc = parse_long(optarg, &cpp);
2119                         if (rc != 0) {
2120                                 /* ignore option */
2121                                 cpp = -1;
2122                                 continue;
2123                         }
2124                         break;
2125                 case 'n':
2126                         nid = optarg;
2127                         break;
2128                 case 't':
2129                         if (parse_long(optarg, &healthv) != 0) {
2130                                 /* ignore option */
2131                                 healthv = -1;
2132                                 continue;
2133                         }
2134                         break;
2135                 default:
2136                         return 0;
2137                 }
2138         }
2139
2140         if (cpp > -1)
2141                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
2142                                                           -1, &err_rc);
2143         if (healthv > -1)
2144                 rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
2145                                                    -1, &err_rc);
2146
2147         if (rc != LUSTRE_CFG_RC_NO_ERR)
2148                 cYAML_print_tree2file(stderr, err_rc);
2149
2150         cYAML_free_tree(err_rc);
2151
2152         return rc;
2153 }
2154
2155 static int jt_set_peer_ni_value(int argc, char **argv)
2156 {
2157         return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
2158 }
2159
2160 static int jt_show_recovery(int argc, char **argv)
2161 {
2162         int rc, opt;
2163         struct cYAML *err_rc = NULL, *show_rc = NULL;
2164         const char *const short_options = "lp";
2165         static const struct option long_options[] = {
2166                 { .name = "local", .has_arg = no_argument, .val = 'l' },
2167                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
2168                 { .name = NULL } };
2169
2170         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
2171         if (rc)
2172                 return rc;
2173
2174         while ((opt = getopt_long(argc, argv, short_options,
2175                                    long_options, NULL)) != -1) {
2176                 switch (opt) {
2177                 case 'l':
2178                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
2179                         break;
2180                 case 'p':
2181                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
2182                         break;
2183                 default:
2184                         return 0;
2185                 }
2186         }
2187
2188         if (rc != LUSTRE_CFG_RC_NO_ERR)
2189                 cYAML_print_tree2file(stderr, err_rc);
2190         else if (show_rc)
2191                 cYAML_print_tree(show_rc);
2192
2193         cYAML_free_tree(err_rc);
2194         cYAML_free_tree(show_rc);
2195
2196         return rc;
2197 }
2198
2199 static int jt_show_peer_debug_info(int argc, char **argv)
2200 {
2201         int rc, opt;
2202         struct cYAML *err_rc = NULL;
2203         char *peer_nid = optarg;
2204         const char *const short_opts = "k";
2205         const struct option long_opts[] = {
2206         { .name = "nid", .has_arg = required_argument, .val = 'k' },
2207         { .name = NULL } };
2208
2209         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
2210
2211         if (rc)
2212                 return rc;
2213
2214         while ((opt = getopt_long(argc, argv, short_opts,
2215                                    long_opts, NULL)) != -1) {
2216                 switch (opt) {
2217                 case 'k':
2218                         peer_nid = optarg;
2219                         break;
2220                 default:
2221                         return 0;
2222                 }
2223         }
2224
2225         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
2226
2227         if (rc != LUSTRE_CFG_RC_NO_ERR)
2228                 cYAML_print_tree2file(stderr, err_rc);
2229
2230         cYAML_free_tree(err_rc);
2231
2232         return rc;
2233 }
2234
2235 static int jt_show_net(int argc, char **argv)
2236 {
2237         char *network = NULL;
2238         int rc, opt;
2239         struct cYAML *err_rc = NULL, *show_rc = NULL;
2240         long int detail = 0;
2241
2242         const char *const short_options = "n:v";
2243         static const struct option long_options[] = {
2244                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2245                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
2246                 { .name = NULL } };
2247
2248         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
2249         if (rc)
2250                 return rc;
2251
2252         while ((opt = getopt_long(argc, argv, short_options,
2253                                    long_options, NULL)) != -1) {
2254                 switch (opt) {
2255                 case 'n':
2256                         network = optarg;
2257                         break;
2258                 case 'v':
2259                         if ((!optarg) && (argv[optind] != NULL) &&
2260                             (argv[optind][0] != '-')) {
2261                                 if (parse_long(argv[optind++], &detail) != 0)
2262                                         detail = 1;
2263                         } else {
2264                                 detail = 1;
2265                         }
2266                         break;
2267                 case '?':
2268                         print_help(net_cmds, "net", "show");
2269                 default:
2270                         return 0;
2271                 }
2272         }
2273
2274         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
2275                                   false);
2276
2277         if (rc != LUSTRE_CFG_RC_NO_ERR)
2278                 cYAML_print_tree2file(stderr, err_rc);
2279         else if (show_rc)
2280                 cYAML_print_tree(show_rc);
2281
2282         cYAML_free_tree(err_rc);
2283         cYAML_free_tree(show_rc);
2284
2285         return rc;
2286 }
2287
2288 static int jt_show_routing(int argc, char **argv)
2289 {
2290         struct cYAML *err_rc = NULL, *show_rc = NULL;
2291         int rc;
2292
2293         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
2294         if (rc)
2295                 return rc;
2296
2297         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
2298
2299         if (rc != LUSTRE_CFG_RC_NO_ERR)
2300                 cYAML_print_tree2file(stderr, err_rc);
2301         else if (show_rc)
2302                 cYAML_print_tree(show_rc);
2303
2304         cYAML_free_tree(err_rc);
2305         cYAML_free_tree(show_rc);
2306
2307         return rc;
2308 }
2309
2310 static int jt_show_stats(int argc, char **argv)
2311 {
2312         int rc;
2313         struct cYAML *show_rc = NULL, *err_rc = NULL;
2314
2315         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
2316         if (rc)
2317                 return rc;
2318
2319         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
2320
2321         if (rc != LUSTRE_CFG_RC_NO_ERR)
2322                 cYAML_print_tree2file(stderr, err_rc);
2323         else if (show_rc)
2324                 cYAML_print_tree(show_rc);
2325
2326         cYAML_free_tree(err_rc);
2327         cYAML_free_tree(show_rc);
2328
2329         return rc;
2330 }
2331
2332 static int jt_show_udsp(int argc, char **argv)
2333 {
2334         int idx = -1;
2335         int rc, opt;
2336         struct cYAML *err_rc = NULL, *show_rc = NULL;
2337
2338         const char *const short_options = "i:";
2339         static const struct option long_options[] = {
2340                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
2341                 { .name = NULL }
2342         };
2343
2344         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
2345         if (rc)
2346                 return rc;
2347
2348         while ((opt = getopt_long(argc, argv, short_options,
2349                                    long_options, NULL)) != -1) {
2350                 switch (opt) {
2351                 case 'i':
2352                         idx = atoi(optarg);
2353                         break;
2354                 case '?':
2355                         print_help(net_cmds, "net", "show");
2356                 default:
2357                         return 0;
2358                 }
2359         }
2360
2361         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
2362
2363         if (rc != LUSTRE_CFG_RC_NO_ERR)
2364                 cYAML_print_tree2file(stderr, err_rc);
2365         else if (show_rc)
2366                 cYAML_print_tree(show_rc);
2367
2368         cYAML_free_tree(err_rc);
2369         cYAML_free_tree(show_rc);
2370
2371         return rc;
2372 }
2373
2374 static int jt_show_global(int argc, char **argv)
2375 {
2376         int rc;
2377         struct cYAML *show_rc = NULL, *err_rc = NULL;
2378
2379         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
2380         if (rc)
2381                 return rc;
2382
2383         rc = lustre_lnet_show_numa_range(-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_max_intf(-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_discovery(-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_drop_asym_route(-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_retry_count(-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_transaction_to(-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_hsensitivity(-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         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
2426         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2427                 cYAML_print_tree2file(stderr, err_rc);
2428                 goto out;
2429         }
2430
2431         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
2432         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2433                 cYAML_print_tree2file(stderr, err_rc);
2434                 goto out;
2435         }
2436
2437         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
2438         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2439                 cYAML_print_tree2file(stderr, err_rc);
2440                 goto out;
2441         }
2442
2443         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
2444         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2445                 cYAML_print_tree2file(stderr, err_rc);
2446                 goto out;
2447         }
2448
2449         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
2450         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2451                 cYAML_print_tree2file(stderr, err_rc);
2452                 goto out;
2453         }
2454
2455         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
2456         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2457                 cYAML_print_tree2file(stderr, err_rc);
2458                 goto out;
2459         }
2460
2461         if (show_rc)
2462                 cYAML_print_tree(show_rc);
2463
2464 out:
2465         cYAML_free_tree(err_rc);
2466         cYAML_free_tree(show_rc);
2467
2468         return rc;
2469 }
2470
2471 static int jt_lnet(int argc, char **argv)
2472 {
2473         int rc;
2474
2475         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
2476         if (rc)
2477                 return rc;
2478
2479         return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
2480 }
2481
2482 static int jt_route(int argc, char **argv)
2483 {
2484         int rc;
2485
2486         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
2487         if (rc)
2488                 return rc;
2489
2490         return Parser_execarg(argc - 1, &argv[1], route_cmds);
2491 }
2492
2493 static int jt_net(int argc, char **argv)
2494 {
2495         int rc;
2496
2497         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
2498         if (rc)
2499                 return rc;
2500
2501         return Parser_execarg(argc - 1, &argv[1], net_cmds);
2502 }
2503
2504 static int jt_routing(int argc, char **argv)
2505 {
2506         int rc;
2507
2508         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
2509         if (rc)
2510                 return rc;
2511
2512         return Parser_execarg(argc - 1, &argv[1], routing_cmds);
2513 }
2514
2515 static int jt_stats(int argc, char **argv)
2516 {
2517         int rc;
2518
2519         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
2520         if (rc)
2521                 return rc;
2522
2523         return Parser_execarg(argc - 1, &argv[1], stats_cmds);
2524 }
2525
2526 static int jt_debug(int argc, char **argv)
2527 {
2528         int rc;
2529
2530         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
2531         if (rc)
2532                 return rc;
2533
2534         return Parser_execarg(argc - 1, &argv[1], debug_cmds);
2535 }
2536
2537 static int jt_global(int argc, char **argv)
2538 {
2539         int rc;
2540
2541         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
2542         if (rc)
2543                 return rc;
2544
2545         return Parser_execarg(argc - 1, &argv[1], global_cmds);
2546 }
2547
2548 static int jt_peers(int argc, char **argv)
2549 {
2550         int rc;
2551
2552         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
2553         if (rc)
2554                 return rc;
2555
2556         return Parser_execarg(argc - 1, &argv[1], peer_cmds);
2557 }
2558
2559 static int jt_set(int argc, char **argv)
2560 {
2561         int rc;
2562
2563         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
2564         if (rc)
2565                 return rc;
2566
2567         return Parser_execarg(argc - 1, &argv[1], set_cmds);
2568 }
2569
2570 static int jt_udsp(int argc, char **argv)
2571 {
2572         int rc;
2573
2574         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
2575         if (rc)
2576                 return rc;
2577
2578         return Parser_execarg(argc - 1, &argv[1], udsp_cmds);
2579 }
2580
2581 static int jt_import(int argc, char **argv)
2582 {
2583         char *file = NULL;
2584         struct cYAML *err_rc = NULL;
2585         struct cYAML *show_rc = NULL;
2586         int rc = 0, return_rc = 0, opt, opt_found = 0;
2587         char cmd = 'a';
2588
2589         const char *const short_options = "adseh";
2590         static const struct option long_options[] = {
2591                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
2592                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
2593                 { .name = "show", .has_arg = no_argument, .val = 's' },
2594                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
2595                 { .name = "help", .has_arg = no_argument, .val = 'h' },
2596                 { .name = NULL } };
2597
2598         while ((opt = getopt_long(argc, argv, short_options,
2599                                    long_options, NULL)) != -1) {
2600                 opt_found = 1;
2601                 switch (opt) {
2602                 case 'a':
2603                         cmd = opt;
2604                         break;
2605                 case 'd':
2606                 case 's':
2607                         cmd = opt;
2608                         break;
2609                 case 'e':
2610                         cmd = opt;
2611                         break;
2612                 case 'h':
2613                         printf("import FILE\n"
2614                                "import < FILE : import a file\n"
2615                                "\t--add: add configuration\n"
2616                                "\t--del: delete configuration\n"
2617                                "\t--show: show configuration\n"
2618                                "\t--exec: execute command\n"
2619                                "\t--help: display this help\n"
2620                                "If no command option is given then --add"
2621                                " is assumed by default\n");
2622                         return 0;
2623                 default:
2624                         return 0;
2625                 }
2626         }
2627
2628         /* grab the file name if one exists */
2629         if (opt_found && argc == 3)
2630                 file = argv[2];
2631         else if (!opt_found && argc == 2)
2632                 file = argv[1];
2633
2634         switch (cmd) {
2635         case 'a':
2636                 rc = lustre_yaml_config(file, &err_rc);
2637                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
2638                 cYAML_print_tree(show_rc);
2639                 cYAML_free_tree(show_rc);
2640                 break;
2641         case 'd':
2642                 rc = lustre_yaml_del(file, &err_rc);
2643                 break;
2644         case 's':
2645                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
2646                 cYAML_print_tree(show_rc);
2647                 cYAML_free_tree(show_rc);
2648                 break;
2649         case 'e':
2650                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
2651                 cYAML_print_tree(show_rc);
2652                 cYAML_free_tree(show_rc);
2653                 break;
2654         }
2655
2656         if (rc || return_rc) {
2657                 cYAML_print_tree2file(stderr, err_rc);
2658                 cYAML_free_tree(err_rc);
2659         }
2660
2661         return rc;
2662 }
2663
2664 static int jt_export(int argc, char **argv)
2665 {
2666         struct cYAML *show_rc = NULL;
2667         struct cYAML *err_rc = NULL;
2668         int rc;
2669         FILE *f = NULL;
2670         int opt;
2671         bool backup = false;
2672         char *file = NULL;
2673
2674         const char *const short_options = "bh";
2675         static const struct option long_options[] = {
2676                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
2677                 { .name = "help", .has_arg = no_argument, .val = 'h' },
2678                 { .name = NULL } };
2679
2680         while ((opt = getopt_long(argc, argv, short_options,
2681                                    long_options, NULL)) != -1) {
2682                 switch (opt) {
2683                 case 'b':
2684                         backup = true;
2685                         break;
2686                 case 'h':
2687                 default:
2688                         printf("export > FILE.yaml : export configuration\n"
2689                                "\t--backup: export only what's necessary for reconfig\n"
2690                                "\t--help: display this help\n");
2691                         return 0;
2692                 }
2693         }
2694
2695         if (backup && argc >= 3)
2696                 file = argv[2];
2697         else if (!backup && argc >= 2)
2698                 file = argv[1];
2699         else
2700                 f = stdout;
2701
2702         if (file) {
2703                 f = fopen(file, "w");
2704                 if (f == NULL)
2705                         return -1;
2706         }
2707
2708         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
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_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
2716                                     &err_rc, backup);
2717         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2718                 cYAML_print_tree2file(stderr, err_rc);
2719                 cYAML_free_tree(err_rc);
2720                 err_rc = NULL;
2721         }
2722
2723         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
2724         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2725                 cYAML_print_tree2file(stderr, err_rc);
2726                 cYAML_free_tree(err_rc);
2727                 err_rc = NULL;
2728         }
2729
2730         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
2731         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2732                 cYAML_print_tree2file(stderr, err_rc);
2733                 cYAML_free_tree(err_rc);
2734                 err_rc = NULL;
2735         }
2736
2737         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
2738         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2739                 cYAML_print_tree2file(stderr, err_rc);
2740                 cYAML_free_tree(err_rc);
2741                 err_rc = NULL;
2742         }
2743
2744         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
2745         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2746                 cYAML_print_tree2file(stderr, err_rc);
2747                 cYAML_free_tree(err_rc);
2748                 err_rc = NULL;
2749         }
2750
2751         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
2752         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2753                 cYAML_print_tree2file(stderr, err_rc);
2754                 cYAML_free_tree(err_rc);
2755                 err_rc = NULL;
2756         }
2757
2758         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
2759         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2760                 cYAML_print_tree2file(stderr, err_rc);
2761                 cYAML_free_tree(err_rc);
2762                 err_rc = NULL;
2763         }
2764
2765         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
2766         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2767                 cYAML_print_tree2file(stderr, err_rc);
2768                 err_rc = NULL;
2769         }
2770
2771         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
2772         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2773                 cYAML_print_tree2file(stderr, err_rc);
2774                 err_rc = NULL;
2775         }
2776
2777         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
2778         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2779                 cYAML_print_tree2file(stderr, err_rc);
2780                 err_rc = NULL;
2781         }
2782
2783         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
2784         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2785                 cYAML_print_tree2file(stderr, err_rc);
2786                 err_rc = NULL;
2787         }
2788
2789         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
2790         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2791                 cYAML_print_tree2file(stderr, err_rc);
2792                 err_rc = NULL;
2793         }
2794
2795         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
2796         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2797                 cYAML_print_tree2file(stderr, err_rc);
2798                 err_rc = NULL;
2799         }
2800
2801         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
2802         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2803                 cYAML_print_tree2file(stderr, err_rc);
2804                 cYAML_free_tree(err_rc);
2805                 err_rc = NULL;
2806         }
2807
2808         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
2809         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2810                 cYAML_print_tree2file(stderr, err_rc);
2811                 cYAML_free_tree(err_rc);
2812                 err_rc = NULL;
2813         }
2814
2815         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
2816         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2817                 cYAML_print_tree2file(stderr, err_rc);
2818                 cYAML_free_tree(err_rc);
2819                 err_rc = NULL;
2820         }
2821
2822         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
2823         if (rc != LUSTRE_CFG_RC_NO_ERR) {
2824                 cYAML_print_tree2file(stderr, err_rc);
2825                 cYAML_free_tree(err_rc);
2826                 err_rc = NULL;
2827         }
2828
2829         if (show_rc != NULL) {
2830                 cYAML_print_tree2file(f, show_rc);
2831                 cYAML_free_tree(show_rc);
2832         }
2833
2834         if (argc >= 2)
2835                 fclose(f);
2836
2837         return 0;
2838 }
2839
2840 static int jt_peer_nid_common(int argc, char **argv, int cmd)
2841 {
2842         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
2843         bool is_mr = true;
2844         char *prim_nid = NULL, *nidstr = NULL;
2845         char err_str[LNET_MAX_STR_LEN] = "Error";
2846         struct cYAML *err_rc = NULL;
2847
2848         const char *const short_opts = "k:mn:";
2849         const struct option long_opts[] = {
2850         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
2851         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
2852         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
2853         { .name = NULL } };
2854
2855         rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
2856         if (rc)
2857                 return rc;
2858
2859         while ((opt = getopt_long(argc, argv, short_opts,
2860                                   long_opts, NULL)) != -1) {
2861                 switch (opt) {
2862                 case 'k':
2863                         prim_nid = optarg;
2864                         break;
2865                 case 'n':
2866                         nidstr = optarg;
2867                         break;
2868                 case 'm':
2869                         if (cmd == LNETCTL_DEL_CMD) {
2870                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2871                                 snprintf(err_str, LNET_MAX_STR_LEN,
2872                                          "Unrecognized option '-%c'", opt);
2873                                 goto build_error;
2874                         }
2875                         is_mr = false;
2876                         break;
2877                 case '?':
2878                         print_help(peer_cmds, "peer",
2879                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
2880                 default:
2881                         return 0;
2882                 }
2883         }
2884
2885         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
2886                                      -1, &err_rc);
2887         if (rc != LUSTRE_CFG_RC_NO_ERR)
2888                 goto out;
2889
2890 build_error:
2891         cYAML_build_error(rc, -1, "peer",
2892                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
2893                           err_str, &err_rc);
2894
2895 out:
2896         if (rc != LUSTRE_CFG_RC_NO_ERR)
2897                 cYAML_print_tree2file(stderr, err_rc);
2898
2899         cYAML_free_tree(err_rc);
2900
2901         return rc;
2902 }
2903
2904 static int jt_add_peer_nid(int argc, char **argv)
2905 {
2906         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
2907 }
2908
2909 static int jt_del_peer_nid(int argc, char **argv)
2910 {
2911         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
2912 }
2913
2914 static int jt_show_peer(int argc, char **argv)
2915 {
2916         char *nid = NULL;
2917         int rc, opt;
2918         struct cYAML *err_rc = NULL, *show_rc = NULL;
2919         long int detail = 0;
2920
2921         const char *const short_opts = "hn:v::";
2922         const struct option long_opts[] = {
2923         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
2924         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
2925         { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
2926         { .name = NULL } };
2927
2928         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
2929         if (rc)
2930                 return rc;
2931
2932         while ((opt = getopt_long(argc, argv, short_opts,
2933                                   long_opts, NULL)) != -1) {
2934                 switch (opt) {
2935                 case 'n':
2936                         nid = optarg;
2937                         break;
2938                 case 'v':
2939                         if ((!optarg) && (argv[optind] != NULL) &&
2940                             (argv[optind][0] != '-')) {
2941                                 if (parse_long(argv[optind++], &detail) != 0)
2942                                         detail = 1;
2943                         } else {
2944                                 detail = 1;
2945                         }
2946                         break;
2947                 case '?':
2948                         print_help(peer_cmds, "peer", "show");
2949                 default:
2950                         return 0;
2951                 }
2952         }
2953
2954         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
2955                                    false);
2956
2957         if (rc != LUSTRE_CFG_RC_NO_ERR)
2958                 cYAML_print_tree2file(stderr, err_rc);
2959         else if (show_rc)
2960                 cYAML_print_tree(show_rc);
2961
2962         cYAML_free_tree(err_rc);
2963         cYAML_free_tree(show_rc);
2964
2965         return rc;
2966 }
2967
2968 static int jt_list_peer(int argc, char **argv)
2969 {
2970         int rc;
2971         struct cYAML *err_rc = NULL, *list_rc = NULL;
2972
2973         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
2974         if (rc)
2975                 return rc;
2976
2977         rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
2978
2979         if (rc != LUSTRE_CFG_RC_NO_ERR)
2980                 cYAML_print_tree2file(stderr, err_rc);
2981         else if (list_rc)
2982                 cYAML_print_tree(list_rc);
2983
2984         cYAML_free_tree(err_rc);
2985         cYAML_free_tree(list_rc);
2986
2987         return rc;
2988 }
2989
2990 static int jt_ping(int argc, char **argv)
2991 {
2992         struct cYAML *err_rc = NULL;
2993         struct cYAML *show_rc = NULL;
2994         int timeout = 1000;
2995         int rc = 0, opt;
2996         char *src_nidstr = NULL;
2997
2998         const char *const short_options = "hs:t:";
2999         const struct option long_options[] = {
3000         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3001         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
3002         { .name = "source",     .has_arg = required_argument,   .val = 's' },
3003         { .name = NULL } };
3004
3005         while ((opt = getopt_long(argc, argv, short_options,
3006                                   long_options, NULL)) != -1) {
3007                 switch (opt) {
3008                 case 's':
3009                         src_nidstr = optarg;
3010                         break;
3011                 case 't':
3012                         timeout = 1000 * atol(optarg);
3013                         break;
3014                 case 'h':
3015                         printf("ping nid[,nid,...]\n"
3016                                "\t --source: source nid\n"
3017                                "\t --timeout: ping timeout\n"
3018                                "\t --help: display this help\n");
3019                         return 0;
3020                 default:
3021                         return 0;
3022                 }
3023         }
3024
3025         for (; optind < argc; optind++)
3026                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
3027                                           &show_rc, &err_rc);
3028
3029         if (show_rc)
3030                 cYAML_print_tree(show_rc);
3031
3032         if (err_rc)
3033                 cYAML_print_tree2file(stderr, err_rc);
3034
3035         cYAML_free_tree(err_rc);
3036         cYAML_free_tree(show_rc);
3037
3038         return rc;
3039 }
3040
3041 static int jt_discover(int argc, char **argv)
3042 {
3043         struct cYAML *err_rc = NULL;
3044         struct cYAML *show_rc = NULL;
3045         int force = 0;
3046         int rc = 0, opt;
3047
3048         const char *const short_options = "fh";
3049         const struct option long_options[] = {
3050                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
3051                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
3052                 { .name = NULL } };
3053
3054         while ((opt = getopt_long(argc, argv, short_options,
3055                                   long_options, NULL)) != -1) {
3056                 switch (opt) {
3057                 case 'f':
3058                         force = 1;
3059                         break;
3060                 case 'h':
3061                         printf("discover nid[,nid,...]\n"
3062                                "\t --force: force discovery\n"
3063                                "\t --help: display this help\n");
3064                         return 0;
3065                 default:
3066                         return 0;
3067                 }
3068         }
3069
3070         for (; optind < argc; optind++)
3071                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
3072                                               &err_rc);
3073
3074         if (show_rc)
3075                 cYAML_print_tree(show_rc);
3076
3077         if (err_rc)
3078                 cYAML_print_tree2file(stderr, err_rc);
3079
3080         cYAML_free_tree(err_rc);
3081         cYAML_free_tree(show_rc);
3082
3083         return rc;
3084 }
3085
3086 static int jt_add_udsp(int argc, char **argv)
3087 {
3088         char *src = NULL, *dst = NULL, *rte = NULL;
3089         struct cYAML *err_rc = NULL;
3090         union lnet_udsp_action udsp_action;
3091         long int idx = -1, priority = -1;
3092         int opt, rc = 0;
3093         char *action_type = "pref";
3094
3095         const char *const short_options = "s:d:r:p:i:";
3096         static const struct option long_options[] = {
3097         { .name = "src",         .has_arg = required_argument, .val = 's' },
3098         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
3099         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
3100         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
3101         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
3102         { .name = NULL } };
3103
3104         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
3105         if (rc)
3106                 return rc;
3107
3108         while ((opt = getopt_long(argc, argv, short_options,
3109                                   long_options, NULL)) != -1) {
3110                 switch (opt) {
3111                 case 's':
3112                         src = optarg;
3113                         break;
3114                 case 'd':
3115                         dst = optarg;
3116                         break;
3117                 case 'r':
3118                         rte = optarg;
3119                         break;
3120                 case 'p':
3121                         rc = parse_long(optarg, &priority);
3122                         if (rc != 0)
3123                                 priority = -1;
3124                         action_type = "priority";
3125                         udsp_action.udsp_priority = priority;
3126                         break;
3127                 case 'i':
3128                         rc = parse_long(optarg, &idx);
3129                         if (rc != 0)
3130                                 idx = 0;
3131                         break;
3132                 case '?':
3133                         print_help(udsp_cmds, "udsp", "add");
3134                 default:
3135                         return 0;
3136                 }
3137         }
3138
3139         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
3140                                   idx, -1, &err_rc);
3141
3142         if (rc != LUSTRE_CFG_RC_NO_ERR)
3143                 cYAML_print_tree2file(stderr, err_rc);
3144
3145         cYAML_free_tree(err_rc);
3146
3147         return rc;
3148 }
3149
3150 static int jt_del_udsp(int argc, char **argv)
3151 {
3152         struct cYAML *err_rc = NULL;
3153         long int idx = 0;
3154         int opt, rc = 0;
3155
3156         const char *const short_options = "i:";
3157         static const struct option long_options[] = {
3158         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
3159         { .name = NULL } };
3160
3161         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
3162         if (rc)
3163                 return rc;
3164
3165         while ((opt = getopt_long(argc, argv, short_options,
3166                                   long_options, NULL)) != -1) {
3167                 switch (opt) {
3168                 case 'i':
3169                         rc = parse_long(optarg, &idx);
3170                         if (rc != 0)
3171                                 idx = 0;
3172                         break;
3173                 case '?':
3174                         print_help(udsp_cmds, "udsp", "add");
3175                 default:
3176                         return 0;
3177                 }
3178         }
3179
3180         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
3181         if (rc != LUSTRE_CFG_RC_NO_ERR)
3182                 cYAML_print_tree2file(stderr, err_rc);
3183
3184         cYAML_free_tree(err_rc);
3185
3186         return rc;
3187 }
3188
3189 static int lnetctl_list_commands(int argc, char **argv)
3190 {
3191         Parser_list_commands(cmd_list, 80, 4);
3192
3193         return 0;
3194 }
3195
3196 int main(int argc, char **argv)
3197 {
3198         int rc = 0;
3199         struct cYAML *err_rc = NULL;
3200
3201         rc = lustre_lnet_config_lib_init();
3202         if (rc < 0) {
3203                 cYAML_build_error(-1, -1, "lnetctl", "startup",
3204                                   "cannot register LNet device", &err_rc);
3205                 cYAML_print_tree2file(stderr, err_rc);
3206                 return rc;
3207         }
3208
3209         Parser_init("lnetctl > ", cmd_list);
3210         if (argc > 1) {
3211                 rc = Parser_execarg(argc - 1, &argv[1], cmd_list);
3212                 goto errorout;
3213         }
3214
3215         Parser_commands();
3216
3217 errorout:
3218         return rc;
3219 }