Whamcloud - gitweb
LU-10391 lnet: migrate router management to Netlink
[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 jt_import(int argc, char **argv);
75 static int jt_export(int argc, char **argv);
76 static int jt_ping(int argc, char **argv);
77 static int jt_discover(int argc, char **argv);
78 static int jt_lnet(int argc, char **argv);
79 static int jt_route(int argc, char **argv);
80 static int jt_net(int argc, char **argv);
81 static int jt_routing(int argc, char **argv);
82 static int jt_set(int argc, char **argv);
83 static int jt_debug(int argc, char **argv);
84 static int jt_stats(int argc, char **argv);
85 static int jt_global(int argc, char **argv);
86 static int jt_peers(int argc, char **argv);
87 static int jt_set_ni_value(int argc, char **argv);
88 static int jt_set_peer_ni_value(int argc, char **argv);
89 static int jt_calc_service_id(int argc, char **argv);
90 static int jt_set_response_tracking(int argc, char **argv);
91 static int jt_set_recovery_limit(int argc, char **argv);
92 static int jt_udsp(int argc, char **argv);
93 static int jt_setup_mrrouting(int argc, char **argv);
94 static int jt_calc_cpt_of_nid(int argc, char **argv);
95 static int jt_show_peer_debug_info(int argc, char **argv);
96
97 command_t cmd_list[] = {
98         {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
99         {"route", jt_route, 0, "route {add | del | show | help}"},
100         {"net", jt_net, 0, "net {add | del | show | set | help}"},
101         {"routing", jt_routing, 0, "routing {show | help}"},
102         {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
103                            " | routing | numa_range | max_interfaces"
104                            " | discovery | drop_asym_route | retry_count"
105                            " | transaction_timeout | health_sensitivity"
106                            " | recovery_interval | router_sensitivity"
107                            " | response_tracking | recovery_limit}"},
108         {"import", jt_import, 0, "import FILE.yaml"},
109         {"export", jt_export, 0, "export FILE.yaml"},
110         {"stats", jt_stats, 0, "stats {show | help}"},
111         {"debug", jt_debug, 0, "debug {recovery {local | peer} | peer}"},
112         {"global", jt_global, 0, "global {show | help}"},
113         {"peer", jt_peers, 0, "peer {add | del | show | list | set | help}"},
114         {"ping", jt_ping, 0, "ping nid,[nid,...]"},
115         {"discover", jt_discover, 0, "discover nid[,nid,...]"},
116         {"service-id", jt_calc_service_id, 0, "Calculate IB Lustre service ID\n"},
117         {"udsp", jt_udsp, 0, "udsp {add | del | help}"},
118         {"setup-mrrouting", jt_setup_mrrouting, 0,
119          "setup linux routing tables\n"},
120         {"cpt-of-nid", jt_calc_cpt_of_nid, 0, "Calculate the CPT associated with NID\n"
121          "\t--nid: NID to calculate the CPT of\n"
122          "\t--ncpt: Number of CPTs to consider in the calculation\n"},
123         { 0, 0, 0, NULL }
124 };
125
126 command_t lnet_cmds[] = {
127         {"configure", jt_config_lnet, 0, "configure lnet\n"
128          "\t--all: load NI configuration from module parameters\n"},
129         {"unconfigure", jt_unconfig_lnet, 0, "unconfigure lnet\n"},
130         { 0, 0, 0, NULL }
131 };
132
133 command_t route_cmds[] = {
134         {"add", jt_add_route, 0, "add a route\n"
135          "\t--net: net name (e.g. tcp0)\n"
136          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
137          "\t--hop|hop-count: number to final destination (1 <= hops <= 255)\n"
138          "\t--priority: priority of route (0 - highest prio\n"
139          "\t--health_sensitivity: gateway health sensitivity (>= 1)\n"},
140         {"del", jt_del_route, 0, "delete a route\n"
141          "\t--net: net name (e.g. tcp0)\n"
142          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"},
143         {"show", jt_show_route, 0, "show routes\n"
144          "\t--net: net name (e.g. tcp0) to filter on\n"
145          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
146          "\t--hop|hop-count: number to final destination (1 <= hops <= 255) to filter on\n"
147          "\t--priority: priority of route (0 - highest prio to filter on\n"
148          "\t--verbose: display detailed output per route\n"},
149         { 0, 0, 0, NULL }
150 };
151
152 command_t net_cmds[] = {
153         {"add", jt_add_ni, 0, "add a network\n"
154          "\t--net: net name (e.g. tcp0)\n"
155          "\t--if: physical interface (e.g. eth0)\n"
156          "\t--ip2net: specify networks based on IP address patterns\n"
157          "\t--peer-timeout: time to wait before declaring a peer dead\n"
158          "\t--peer-credits: define the max number of inflight messages\n"
159          "\t--peer-buffer-credits: the number of buffer credits per peer\n"
160          "\t--credits: Network Interface credits\n"
161          "\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"
162          "\t--conns-per-peer: number of connections per peer\n"
163          "\t--skip-mr-route-setup: do not add linux route for the ni\n"
164          "\t--auth-key: Network authorization key (kfilnd only)\n"
165          "\t--traffic-class: Traffic class (kfilnd only)\n"},
166         {"del", jt_del_ni, 0, "delete a network\n"
167          "\t--net: net name (e.g. tcp0)\n"
168          "\t--if: physical interface (e.g. eth0)\n"},
169         {"show", jt_show_net, 0, "show networks\n"
170          "\t--net: net name (e.g. tcp0) to filter on\n"
171          "\t--verbose: display detailed output per network."
172                        " Optional argument of '2' outputs more stats\n"},
173         {"set", jt_set_ni_value, 0, "set local NI specific parameter\n"
174          "\t--nid: NI NID to set the\n"
175          "\t--health: specify health value to set\n"
176          "\t--conns-per-peer: number of connections per peer\n"
177          "\t--all: set all NIs value to the one specified\n"},
178         { 0, 0, 0, NULL }
179 };
180
181 command_t routing_cmds[] = {
182         {"show", jt_show_routing, 0, "show routing information\n"},
183         { 0, 0, 0, NULL }
184 };
185
186 command_t stats_cmds[] = {
187         {"show", jt_show_stats, 0, "show LNET statistics\n"},
188         {"reset", jt_reset_stats, 0, "reset LNET statistics\n"},
189         { 0, 0, 0, NULL }
190 };
191
192 command_t debug_cmds[] = {
193         {"recovery", jt_show_recovery, 0, "list recovery queues\n"
194                 "\t--local : list local recovery queue\n"
195                 "\t--peer : list peer recovery queue\n"},
196         {"peer", jt_show_peer_debug_info, 0, "show peer debug info\n"
197                 "\t--nid: peer's NID\n"},
198         { 0, 0, 0, NULL }
199 };
200
201 command_t global_cmds[] = {
202         {"show", jt_show_global, 0, "show global variables\n"},
203         { 0, 0, 0, NULL }
204 };
205
206 command_t set_cmds[] = {
207         {"tiny_buffers", jt_set_tiny, 0, "set tiny routing buffers\n"
208          "\tVALUE must be greater than 0\n"},
209         {"small_buffers", jt_set_small, 0, "set small routing buffers\n"
210          "\tVALUE must be greater than 0\n"},
211         {"large_buffers", jt_set_large, 0, "set large routing buffers\n"
212          "\tVALUE must be greater than 0\n"},
213         {"routing", jt_set_routing, 0, "enable/disable routing\n"
214          "\t0 - disable routing\n"
215          "\t1 - enable routing\n"},
216         {"numa_range", jt_set_numa, 0, "set NUMA range for NI selection\n"
217          "\tVALUE must be at least 0\n"},
218         {"max_interfaces", jt_set_max_intf, 0, "set the default value for "
219                 "max interfaces\n"
220          "\tValue must be greater than 16\n"},
221         {"discovery", jt_set_discovery, 0, "enable/disable peer discovery\n"
222          "\t0 - disable peer discovery\n"
223          "\t1 - enable peer discovery (default)\n"},
224         {"drop_asym_route", jt_set_drop_asym_route, 0,
225          "drop/accept asymmetrical route messages\n"
226          "\t0 - accept asymmetrical route messages (default)\n"
227          "\t1 - drop asymmetrical route messages\n"},
228         {"retry_count", jt_set_retry_count, 0, "number of retries\n"
229          "\t0 - turn of retries\n"
230          "\t>0 - number of retries\n"},
231         {"transaction_timeout", jt_set_transaction_to, 0, "Message/Response timeout\n"
232          "\t>0 - timeout in seconds\n"},
233         {"health_sensitivity", jt_set_hsensitivity, 0, "sensitivity to failure\n"
234          "\t0 - turn off health evaluation\n"
235          "\t>0 - sensitivity value not more than 1000\n"},
236         {"recovery_interval", jt_set_recov_intrv, 0, "interval to ping in seconds (at least 1)\n"
237          "\t>0 - time in seconds between pings\n"},
238         {"router_sensitivity", jt_set_rtr_sensitivity, 0, "router sensitivity %\n"
239          "\t100 - router interfaces need to be fully healthy to be used\n"
240          "\t<100 - router interfaces can be used even if not healthy\n"},
241         {"response_tracking", jt_set_response_tracking, 0,
242          "Set the behavior of response tracking\n"
243          "\t0 - Only LNet pings and discovery pushes utilize response tracking\n"
244          "\t1 - GETs are eligible for response tracking\n"
245          "\t2 - PUTs are eligible for response tracking\n"
246          "\t3 - Both PUTs and GETs are eligible for response tracking (default)\n"
247          "\tNote: Regardless of the value of the response_tracking parameter LNet\n"
248          "\t      pings and discovery pushes always utilize response tracking\n"},
249         {"recovery_limit", jt_set_recovery_limit, 0,
250          "Set how long LNet will attempt to recover unhealthy interfaces.\n"
251          "\t0 - Recover indefinitely (default)\n"
252          "\t>0 - Recover for the specified number of seconds.\n"},
253         {"max_recovery_ping_interval", jt_set_max_recovery_ping_interval, 0,
254          "maximum recovery ping interval\n"
255          "\t>0 - maximum recovery ping interval in seconds\n"},
256         { 0, 0, 0, NULL }
257 };
258
259 command_t peer_cmds[] = {
260         {"add", jt_add_peer_nid, 0, "add a peer NID\n"
261          "\t--prim_nid: Primary NID of the peer.\n"
262          "\t--nid: one or more peer NIDs\n"
263          "\t--non_mr: create this peer as not Multi-Rail capable\n"
264          "\t--ip2nets: specify a range of nids per peer\n"
265          "\t--lock_prim: lock primary nid\n"},
266         {"del", jt_del_peer_nid, 0, "delete a peer NID\n"
267          "\t--prim_nid: Primary NID of the peer.\n"
268          "\t--nid: list of NIDs to remove. If none provided,\n"
269          "\t       peer is deleted\n"
270          "\t--ip2nets: specify a range of nids per peer\n"
271          "\t--force: force-delete locked primary NID\n"},
272         {"show", jt_show_peer, 0, "show peer information\n"
273          "\t--nid: NID of peer to filter on.\n"
274          "\t--verbose: display detailed output per peer."
275                        " Optional argument of '2' outputs more stats\n"},
276         {"list", jt_list_peer, 0, "list all peers\n"},
277         {"set", jt_set_peer_ni_value, 0, "set peer ni specific parameter\n"
278          "\t--nid: Peer NI NID to set the\n"
279          "\t--health: specify health value to set\n"
280          "\t--all: set all peer_nis values to the one specified\n"
281          "\t--state: set peer state (DANGEROUS: for test/debug only)"},
282         { 0, 0, 0, NULL }
283 };
284
285 command_t udsp_cmds[] = {
286         {"add", jt_add_udsp, 0, "add a udsp\n"
287          "\t--src nid|net: ip2nets syntax specifying the local NID or network to match.\n"
288          "\t--dst nid:     ip2nets syntax specifying the remote NID to match.\n"
289          "\t--rte nid:     ip2nets syntax specifying the router NID to match.\n"
290          "\t--priority p:  Assign priority value p where p >= 0.\n"
291          "\t               Note: 0 is the highest priority.\n"
292          "\t--idx n:       Insert the rule in the n'th position on the list of rules.\n"
293          "\t               By default, rules are appended to the end of the rule list.\n"},
294         {"del", jt_del_udsp, 0, "delete a udsp\n"
295          "\t--all:   Delete all rules.\n"
296          "\t--idx n: Delete the rule at index n.\n"},
297         {"show", jt_show_udsp, 0, "show udsps\n"
298          "\t--idx n: Show the rule at at index n.\n"
299          "\t         By default, all rules are shown.\n"},
300         { 0, 0, 0, NULL }
301 };
302
303 static int parse_long(const char *number, long int *value)
304 {
305         char *end;
306
307         if (!number)
308                 return -1;
309
310         *value = strtol(number,  &end, 0);
311         if (end != NULL && *end != 0)
312                 return -1;
313
314         return 0;
315 }
316
317 static int jt_setup_mrrouting(int argc, char **argv)
318 {
319         int rc;
320         struct cYAML *err_rc = NULL;
321
322         rc = lustre_lnet_setup_mrrouting(&err_rc);
323
324         if (rc != LUSTRE_CFG_RC_NO_ERR)
325                 cYAML_print_tree2file(stderr, err_rc);
326
327         cYAML_free_tree(err_rc);
328
329         return rc;
330 }
331
332 static inline void print_help(const command_t cmds[], const char *cmd_type,
333                               const char *pc_name)
334 {
335         const command_t *cmd;
336
337         for (cmd = cmds; cmd->pc_name; cmd++) {
338                 if (pc_name != NULL &&
339                     strcmp(cmd->pc_name, pc_name) == 0) {
340                         printf("%s %s: %s\n", cmd_type, cmd->pc_name,
341                                cmd->pc_help);
342                         return;
343                 } else if (pc_name != NULL) {
344                         continue;
345                 }
346                 printf("%s %s: %s\n", cmd_type, cmd->pc_name, cmd->pc_help);
347         }
348 }
349
350 static int check_cmd(const command_t *cmd_list, const char *cmd,
351                      const char *sub_cmd, const int min_args,
352                      int argc, char **argv)
353 {
354         int opt;
355         int rc = 0;
356         optind = 0;
357         opterr = 0;
358
359         const char *const short_options = "h";
360         static const struct option long_options[] = {
361                 { .name = "help", .has_arg = no_argument, .val = 'h' },
362                 { .name = NULL }
363         };
364
365         if (argc < min_args) {
366                 print_help(cmd_list, cmd, sub_cmd);
367                 rc = -1;
368                 goto out;
369         } else if (argc > 2) {
370                 return 0;
371         }
372
373         while ((opt = getopt_long(argc, argv, short_options,
374                                   long_options, NULL)) != -1) {
375                 switch (opt) {
376                 case 'h':
377                         print_help(cmd_list, cmd, sub_cmd);
378                         rc = 1;
379                         break;
380                 default:
381                         rc = 0;
382                         break;
383                 }
384         }
385
386 out:
387         opterr = 1;
388         optind = 0;
389         return rc;
390 }
391
392 static int jt_set_response_tracking(int argc, char **argv)
393 {
394         long int value;
395         int rc;
396         struct cYAML *err_rc = NULL;
397
398         rc = check_cmd(set_cmds, "set", "response_tracking", 2, argc, argv);
399         if (rc)
400                 return rc;
401
402         rc = parse_long(argv[1], &value);
403         if (rc != 0) {
404                 cYAML_build_error(-1, -1, "parser", "set",
405                                   "cannot parse response_tracking value",
406                                   &err_rc);
407                 cYAML_print_tree2file(stderr, err_rc);
408                 cYAML_free_tree(err_rc);
409                 return -1;
410         }
411
412         rc = lustre_lnet_config_response_tracking(value, -1, &err_rc);
413         if (rc != LUSTRE_CFG_RC_NO_ERR)
414                 cYAML_print_tree2file(stderr, err_rc);
415
416         cYAML_free_tree(err_rc);
417
418         return rc;
419 }
420
421 static int jt_calc_service_id(int argc, char **argv)
422 {
423         int rc;
424         __u64 service_id;
425
426         rc = lustre_lnet_calc_service_id(&service_id);
427         if (rc != LUSTRE_CFG_RC_NO_ERR)
428                 return rc;
429
430         /* cYAML currently doesn't support printing hex values.
431          * Therefore just print it locally here
432          */
433         printf("service_id:\n    value: 0x%llx\n",
434                (unsigned long long)(service_id));
435
436         return rc;
437 }
438
439 static int jt_calc_cpt_of_nid(int argc, char **argv)
440 {
441         int rc, opt;
442         int cpt;
443         long int ncpts = -1;
444         char *nid = NULL;
445         struct cYAML *err_rc = NULL;
446         const char *const short_options = "n:c:h";
447         static const struct option long_options[] = {
448         { .name = "nid",       .has_arg = required_argument, .val = 'n' },
449         { .name = "ncpt",     .has_arg = required_argument, .val = 'c' },
450         { .name = NULL } };
451
452         rc = check_cmd(cmd_list, "", "cpt-of-nid", 0, argc, argv);
453         if (rc)
454                 return rc;
455
456         while ((opt = getopt_long(argc, argv, short_options,
457                                    long_options, NULL)) != -1) {
458                 switch (opt) {
459                 case 'n':
460                         nid = optarg;
461                         break;
462                 case 'c':
463                         rc = parse_long(optarg, &ncpts);
464                         if (rc != 0) {
465                                 cYAML_build_error(-1, -1, "cpt", "get",
466                                                 "cannot parse input", &err_rc);
467                                 cYAML_print_tree2file(stderr, err_rc);
468                                 cYAML_free_tree(err_rc);
469                                 return -1;
470                         }
471                         break;
472                 case '?':
473                         print_help(cmd_list, "", "cpt-of-nid");
474                 default:
475                         return 0;
476                 }
477         }
478
479         cpt = lustre_lnet_calc_cpt_of_nid(nid, ncpts);
480         if (cpt < 0)
481                 return -1;
482
483         printf("cpt:\n    value: %d\n", cpt);
484
485         return 0;
486 }
487
488 static int jt_set_recovery_limit(int argc, char **argv)
489 {
490         long int value;
491         int rc;
492         struct cYAML *err_rc = NULL;
493
494         rc = check_cmd(set_cmds, "set", "recovery_limit", 2, argc, argv);
495         if (rc)
496                 return rc;
497
498         rc = parse_long(argv[1], &value);
499         if (rc != 0) {
500                 cYAML_build_error(-1, -1, "parser", "set",
501                                   "cannot parse recovery_limit value",
502                                   &err_rc);
503                 cYAML_print_tree2file(stderr, err_rc);
504                 cYAML_free_tree(err_rc);
505                 return -1;
506         }
507
508         rc = lustre_lnet_config_recovery_limit(value, -1, &err_rc);
509         if (rc != LUSTRE_CFG_RC_NO_ERR)
510                 cYAML_print_tree2file(stderr, err_rc);
511
512         cYAML_free_tree(err_rc);
513
514         return rc;
515 }
516
517 static int jt_set_max_intf(int argc, char **argv)
518 {
519         long int value;
520         int rc;
521         struct cYAML *err_rc = NULL;
522
523         rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
524         if (rc)
525                 return rc;
526
527         rc = parse_long(argv[1], &value);
528         if (rc != 0) {
529                 cYAML_build_error(-1, -1, "parser", "set",
530                                   "cannot parse max_interfaces value", &err_rc);
531                 cYAML_print_tree2file(stderr, err_rc);
532                 cYAML_free_tree(err_rc);
533                 return -1;
534         }
535
536         rc = lustre_lnet_config_max_intf(value, -1, &err_rc);
537         if (rc != LUSTRE_CFG_RC_NO_ERR)
538                 cYAML_print_tree2file(stderr, err_rc);
539
540         cYAML_free_tree(err_rc);
541
542         return rc;
543 }
544
545 static int jt_set_numa(int argc, char **argv)
546 {
547         long int value;
548         int rc;
549         struct cYAML *err_rc = NULL;
550
551         rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
552         if (rc)
553                 return rc;
554
555         rc = parse_long(argv[1], &value);
556         if (rc != 0) {
557                 cYAML_build_error(-1, -1, "parser", "set",
558                                   "cannot parse numa_range value", &err_rc);
559                 cYAML_print_tree2file(stderr, err_rc);
560                 cYAML_free_tree(err_rc);
561                 return -1;
562         }
563
564         rc = lustre_lnet_config_numa_range(value, -1, &err_rc);
565         if (rc != LUSTRE_CFG_RC_NO_ERR)
566                 cYAML_print_tree2file(stderr, err_rc);
567
568         cYAML_free_tree(err_rc);
569
570         return rc;
571 }
572
573 static int jt_set_recov_intrv(int argc, char **argv)
574 {
575         long int value;
576         int rc;
577         struct cYAML *err_rc = NULL;
578
579         rc = check_cmd(set_cmds, "set", "recovery_interval", 2, argc, argv);
580         if (rc)
581                 return rc;
582
583         rc = parse_long(argv[1], &value);
584         if (rc != 0) {
585                 cYAML_build_error(-1, -1, "parser", "set",
586                                   "cannot parse recovery interval value", &err_rc);
587                 cYAML_print_tree2file(stderr, err_rc);
588                 cYAML_free_tree(err_rc);
589                 return -1;
590         }
591
592         rc = lustre_lnet_config_recov_intrv(value, -1, &err_rc);
593         if (rc != LUSTRE_CFG_RC_NO_ERR)
594                 cYAML_print_tree2file(stderr, err_rc);
595
596         cYAML_free_tree(err_rc);
597
598         return rc;
599 }
600
601 static int jt_set_rtr_sensitivity(int argc, char **argv)
602 {
603         long int value;
604         int rc;
605         struct cYAML *err_rc = NULL;
606
607         rc = check_cmd(set_cmds, "set", "router_sensitivity", 2, argc, argv);
608         if (rc)
609                 return rc;
610
611         rc = parse_long(argv[1], &value);
612         if (rc != 0) {
613                 cYAML_build_error(-1, -1, "parser", "set",
614                                   "cannot parse router sensitivity value", &err_rc);
615                 cYAML_print_tree2file(stderr, err_rc);
616                 cYAML_free_tree(err_rc);
617                 return -1;
618         }
619
620         rc = lustre_lnet_config_rtr_sensitivity(value, -1, &err_rc);
621         if (rc != LUSTRE_CFG_RC_NO_ERR)
622                 cYAML_print_tree2file(stderr, err_rc);
623
624         cYAML_free_tree(err_rc);
625
626         return rc;
627 }
628
629 static int jt_set_hsensitivity(int argc, char **argv)
630 {
631         long int value;
632         int rc;
633         struct cYAML *err_rc = NULL;
634
635         rc = check_cmd(set_cmds, "set", "health_sensitivity", 2, argc, argv);
636         if (rc)
637                 return rc;
638
639         rc = parse_long(argv[1], &value);
640         if (rc != 0) {
641                 cYAML_build_error(-1, -1, "parser", "set",
642                                   "cannot parse health sensitivity value", &err_rc);
643                 cYAML_print_tree2file(stderr, err_rc);
644                 cYAML_free_tree(err_rc);
645                 return -1;
646         }
647
648         rc = lustre_lnet_config_hsensitivity(value, -1, &err_rc);
649         if (rc != LUSTRE_CFG_RC_NO_ERR)
650                 cYAML_print_tree2file(stderr, err_rc);
651
652         cYAML_free_tree(err_rc);
653
654         return rc;
655 }
656
657 static int jt_reset_stats(int argc, char **argv)
658 {
659         int rc;
660         struct cYAML *err_rc = NULL;
661
662         rc = check_cmd(stats_cmds, "stats", "reset", 0, argc, argv);
663         if (rc)
664                 return rc;
665
666         rc = lustre_lnet_reset_stats(-1, &err_rc);
667         if (rc != LUSTRE_CFG_RC_NO_ERR)
668                 cYAML_print_tree2file(stderr, err_rc);
669
670         cYAML_free_tree(err_rc);
671
672         return rc;
673 }
674
675 static int jt_set_transaction_to(int argc, char **argv)
676 {
677         long int value;
678         int rc;
679         struct cYAML *err_rc = NULL;
680
681         rc = check_cmd(set_cmds, "set", "transaction_timeout", 2, argc, argv);
682         if (rc)
683                 return rc;
684
685         rc = parse_long(argv[1], &value);
686         if (rc != 0) {
687                 cYAML_build_error(-1, -1, "parser", "set",
688                                   "cannot parse transaction timeout value", &err_rc);
689                 cYAML_print_tree2file(stderr, err_rc);
690                 cYAML_free_tree(err_rc);
691                 return -1;
692         }
693
694         rc = lustre_lnet_config_transaction_to(value, -1, &err_rc);
695         if (rc != LUSTRE_CFG_RC_NO_ERR)
696                 cYAML_print_tree2file(stderr, err_rc);
697
698         cYAML_free_tree(err_rc);
699
700         return rc;
701 }
702
703 static int jt_set_retry_count(int argc, char **argv)
704 {
705         long int value;
706         int rc;
707         struct cYAML *err_rc = NULL;
708
709         rc = check_cmd(set_cmds, "set", "retry_count", 2, argc, argv);
710         if (rc)
711                 return rc;
712
713         rc = parse_long(argv[1], &value);
714         if (rc != 0) {
715                 cYAML_build_error(-1, -1, "parser", "set",
716                                   "cannot parse retry_count value", &err_rc);
717                 cYAML_print_tree2file(stderr, err_rc);
718                 cYAML_free_tree(err_rc);
719                 return -1;
720         }
721
722         rc = lustre_lnet_config_retry_count(value, -1, &err_rc);
723         if (rc != LUSTRE_CFG_RC_NO_ERR)
724                 cYAML_print_tree2file(stderr, err_rc);
725
726         cYAML_free_tree(err_rc);
727
728         return rc;
729 }
730
731 static int jt_set_discovery(int argc, char **argv)
732 {
733         long int value;
734         int rc;
735         struct cYAML *err_rc = NULL;
736
737         rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
738         if (rc)
739                 return rc;
740
741         rc = parse_long(argv[1], &value);
742         if (rc != 0) {
743                 cYAML_build_error(-1, -1, "parser", "set",
744                                   "cannot parse discovery value", &err_rc);
745                 cYAML_print_tree2file(stderr, err_rc);
746                 cYAML_free_tree(err_rc);
747                 return -1;
748         }
749
750         rc = lustre_lnet_config_discovery(value, -1, &err_rc);
751         if (rc != LUSTRE_CFG_RC_NO_ERR)
752                 cYAML_print_tree2file(stderr, err_rc);
753
754         cYAML_free_tree(err_rc);
755
756         return rc;
757 }
758
759 static int jt_set_drop_asym_route(int argc, char **argv)
760 {
761         long int value;
762         int rc;
763         struct cYAML *err_rc = NULL;
764
765         rc = check_cmd(set_cmds, "set", "drop_asym_route", 2, argc, argv);
766         if (rc)
767                 return rc;
768
769         rc = parse_long(argv[1], &value);
770         if (rc != 0) {
771                 cYAML_build_error(-1, -1, "parser", "set",
772                                   "cannot parse drop_asym_route value",
773                                   &err_rc);
774                 cYAML_print_tree2file(stderr, err_rc);
775                 cYAML_free_tree(err_rc);
776                 return -1;
777         }
778
779         rc = lustre_lnet_config_drop_asym_route(value, -1, &err_rc);
780         if (rc != LUSTRE_CFG_RC_NO_ERR)
781                 cYAML_print_tree2file(stderr, err_rc);
782
783         cYAML_free_tree(err_rc);
784
785         return rc;
786 }
787
788 static int jt_set_tiny(int argc, char **argv)
789 {
790         long int value;
791         int rc;
792         struct cYAML *err_rc = NULL;
793
794         rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
795         if (rc)
796                 return rc;
797
798         rc = parse_long(argv[1], &value);
799         if (rc != 0) {
800                 cYAML_build_error(-1, -1, "parser", "set",
801                                   "cannot parse tiny_buffers value", &err_rc);
802                 cYAML_print_tree2file(stderr, err_rc);
803                 cYAML_free_tree(err_rc);
804                 return -1;
805         }
806
807         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
808         if (rc != LUSTRE_CFG_RC_NO_ERR)
809                 cYAML_print_tree2file(stderr, err_rc);
810
811         cYAML_free_tree(err_rc);
812
813         return rc;
814 }
815
816 static int jt_set_small(int argc, char **argv)
817 {
818         long int value;
819         int rc;
820         struct cYAML *err_rc = NULL;
821
822         rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
823         if (rc)
824                 return rc;
825
826         rc = parse_long(argv[1], &value);
827         if (rc != 0) {
828                 cYAML_build_error(-1, -1, "parser", "set",
829                                   "cannot parse small_buffers value", &err_rc);
830                 cYAML_print_tree2file(stderr, err_rc);
831                 cYAML_free_tree(err_rc);
832                 return -1;
833         }
834
835         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
836         if (rc != LUSTRE_CFG_RC_NO_ERR)
837                 cYAML_print_tree2file(stderr, err_rc);
838
839         cYAML_free_tree(err_rc);
840
841         return rc;
842 }
843
844 static int jt_set_large(int argc, char **argv)
845 {
846         long int value;
847         int rc;
848         struct cYAML *err_rc = NULL;
849
850         rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
851         if (rc)
852                 return rc;
853
854         rc = parse_long(argv[1], &value);
855         if (rc != 0) {
856                 cYAML_build_error(-1, -1, "parser", "set",
857                                   "cannot parse large_buffers value", &err_rc);
858                 cYAML_print_tree2file(stderr, err_rc);
859                 cYAML_free_tree(err_rc);
860                 return -1;
861         }
862
863         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
864         if (rc != LUSTRE_CFG_RC_NO_ERR)
865                 cYAML_print_tree2file(stderr, err_rc);
866
867         cYAML_free_tree(err_rc);
868
869         return rc;
870 }
871
872 static int jt_set_routing(int argc, char **argv)
873 {
874         long int value;
875         struct cYAML *err_rc = NULL;
876         int rc;
877
878         rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
879         if (rc)
880                 return rc;
881
882         rc = parse_long(argv[1], &value);
883         if (rc != 0 || (value != 0 && value != 1)) {
884                 cYAML_build_error(-1, -1, "parser", "set",
885                                   "cannot parse routing value.\n"
886                                   "must be 0 for disable or 1 for enable",
887                                   &err_rc);
888                 cYAML_print_tree2file(stderr, err_rc);
889                 cYAML_free_tree(err_rc);
890                 return -1;
891         }
892
893         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
894
895         if (rc != LUSTRE_CFG_RC_NO_ERR)
896                 cYAML_print_tree2file(stderr, err_rc);
897
898         cYAML_free_tree(err_rc);
899
900         return rc;
901 }
902
903 static int jt_set_max_recovery_ping_interval(int argc, char **argv)
904 {
905         long int value;
906         int rc;
907         struct cYAML *err_rc = NULL;
908
909         rc = check_cmd(set_cmds, "set", "maximum recovery_interval", 2, argc, argv);
910         if (rc)
911                 return rc;
912
913         rc = parse_long(argv[1], &value);
914         if (rc != 0) {
915                 cYAML_build_error(-1, -1, "parser", "set",
916                                   "cannot parse maximum recovery interval value",
917                                   &err_rc);
918                 cYAML_print_tree2file(stderr, err_rc);
919                 cYAML_free_tree(err_rc);
920                 return -1;
921         }
922
923         rc = lustre_lnet_config_max_recovery_ping_interval(value, -1, &err_rc);
924         if (rc != LUSTRE_CFG_RC_NO_ERR)
925                 cYAML_print_tree2file(stderr, err_rc);
926
927         cYAML_free_tree(err_rc);
928
929         return rc;
930 }
931
932 static void yaml_lnet_print_error(int op, char *cmd, const char *errstr)
933 {
934         char errcode[INT_STRING_LEN];
935         yaml_emitter_t log;
936         yaml_event_t event;
937         const char *flag;
938         int rc;
939
940         snprintf(errcode, sizeof(errcode), "%d", errno);
941
942         yaml_emitter_initialize(&log);
943         yaml_emitter_set_indent(&log, LNET_DEFAULT_INDENT);
944         yaml_emitter_set_output_file(&log, stderr);
945
946         yaml_emitter_open(&log);
947         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
948         rc = yaml_emitter_emit(&log, &event);
949         if (rc == 0)
950                 goto emitter_error;
951
952         yaml_mapping_start_event_initialize(&event, NULL,
953                                             (yaml_char_t *)YAML_MAP_TAG,
954                                             1, YAML_ANY_MAPPING_STYLE);
955         rc = yaml_emitter_emit(&log, &event);
956         if (rc == 0)
957                 goto emitter_error;
958
959         switch (op) {
960         case NLM_F_CREATE:
961                 flag = "add";
962                 break;
963         case NLM_F_REPLACE:
964                 flag = "set";
965                 break;
966         case 0:
967                 flag = "del";
968                 break;
969         case NLM_F_DUMP:
970         default:
971                 flag = "show";
972                 break;
973         }
974
975         yaml_scalar_event_initialize(&event, NULL,
976                                      (yaml_char_t *)YAML_STR_TAG,
977                                      (yaml_char_t *)flag,
978                                      strlen(flag), 1, 0,
979                                      YAML_PLAIN_SCALAR_STYLE);
980         rc = yaml_emitter_emit(&log, &event);
981         if (rc == 0)
982                 goto emitter_error;
983
984         yaml_sequence_start_event_initialize(&event, NULL,
985                                              (yaml_char_t *)YAML_SEQ_TAG,
986                                              1, YAML_ANY_SEQUENCE_STYLE);
987         rc = yaml_emitter_emit(&log, &event);
988         if (rc == 0)
989                 goto emitter_error;
990
991         yaml_mapping_start_event_initialize(&event, NULL,
992                                             (yaml_char_t *)YAML_MAP_TAG,
993                                             1, YAML_ANY_MAPPING_STYLE);
994         rc = yaml_emitter_emit(&log, &event);
995         if (rc == 0)
996                 goto emitter_error;
997
998         yaml_scalar_event_initialize(&event, NULL,
999                                      (yaml_char_t *)YAML_STR_TAG,
1000                                      (yaml_char_t *)cmd,
1001                                      strlen(cmd),
1002                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
1003         rc = yaml_emitter_emit(&log, &event);
1004         if (rc == 0)
1005                 goto emitter_error;
1006
1007         yaml_scalar_event_initialize(&event, NULL,
1008                                      (yaml_char_t *)YAML_STR_TAG,
1009                                      (yaml_char_t *)"",
1010                                      strlen(""),
1011                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
1012         rc = yaml_emitter_emit(&log, &event);
1013         if (rc == 0)
1014                 goto emitter_error;
1015
1016         yaml_scalar_event_initialize(&event, NULL,
1017                                      (yaml_char_t *)YAML_STR_TAG,
1018                                      (yaml_char_t *)"errno",
1019                                      strlen("errno"), 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 *)errcode,
1028                                      strlen(errcode), 1, 0,
1029                                      YAML_PLAIN_SCALAR_STYLE);
1030         rc = yaml_emitter_emit(&log, &event);
1031         if (rc == 0)
1032                 goto emitter_error;
1033
1034
1035         yaml_scalar_event_initialize(&event, NULL,
1036                                      (yaml_char_t *)YAML_STR_TAG,
1037                                      (yaml_char_t *)"descr",
1038                                      strlen("descr"), 1, 0,
1039                                      YAML_PLAIN_SCALAR_STYLE);
1040         rc = yaml_emitter_emit(&log, &event);
1041         if (rc == 0)
1042                 goto emitter_error;
1043
1044         yaml_scalar_event_initialize(&event, NULL,
1045                                      (yaml_char_t *)YAML_STR_TAG,
1046                                      (yaml_char_t *)errstr,
1047                                      strlen(errstr), 1, 0,
1048                                      YAML_DOUBLE_QUOTED_SCALAR_STYLE);
1049         rc = yaml_emitter_emit(&log, &event);
1050         if (rc == 0)
1051                 goto emitter_error;
1052
1053         yaml_mapping_end_event_initialize(&event);
1054         rc = yaml_emitter_emit(&log, &event);
1055         if (rc == 0)
1056                 goto emitter_error;
1057
1058         yaml_sequence_end_event_initialize(&event);
1059         rc = yaml_emitter_emit(&log, &event);
1060         if (rc == 0)
1061                 goto emitter_error;
1062
1063         yaml_mapping_end_event_initialize(&event);
1064         rc = yaml_emitter_emit(&log, &event);
1065         if (rc == 0)
1066                 goto emitter_error;
1067
1068         yaml_document_end_event_initialize(&event, 0);
1069         rc = yaml_emitter_emit(&log, &event);
1070         if (rc == 0)
1071                 goto emitter_error;
1072
1073         rc = yaml_emitter_close(&log);
1074 emitter_error:
1075         if (rc == 0)
1076                 yaml_emitter_log_error(&log, stdout);
1077         yaml_emitter_delete(&log);
1078 }
1079
1080 static int jt_config_lnet(int argc, char **argv)
1081 {
1082         struct cYAML *err_rc = NULL;
1083         bool load_mod_params = false;
1084         int rc, opt;
1085
1086         const char *const short_options = "a";
1087         static const struct option long_options[] = {
1088                 { .name = "all",  .has_arg = no_argument, .val = 'a' },
1089                 { .name = NULL }
1090         };
1091
1092         rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
1093         if (rc)
1094                 return rc;
1095
1096         while ((opt = getopt_long(argc, argv, short_options,
1097                                    long_options, NULL)) != -1) {
1098                 switch (opt) {
1099                 case 'a':
1100                         load_mod_params = true;
1101                         break;
1102                 default:
1103                         return 0;
1104                 }
1105         }
1106
1107         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
1108                                           -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
1118 static int jt_unconfig_lnet(int argc, char **argv)
1119 {
1120         struct cYAML *err_rc = NULL;
1121         int rc;
1122
1123         rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
1124         if (rc)
1125                 return rc;
1126
1127         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
1128
1129         if (rc != LUSTRE_CFG_RC_NO_ERR)
1130                 cYAML_print_tree2file(stderr, err_rc);
1131
1132         cYAML_free_tree(err_rc);
1133
1134         return rc;
1135 }
1136
1137 static int yaml_lnet_router_gateways(yaml_emitter_t *output, const char *nw,
1138                                      const char *gw, int hops, int prio,
1139                                      int sen)
1140 {
1141         char num[INT_STRING_LEN];
1142         yaml_event_t event;
1143         int rc;
1144
1145         yaml_mapping_start_event_initialize(&event, NULL,
1146                                             (yaml_char_t *)YAML_MAP_TAG, 1,
1147                                             YAML_BLOCK_MAPPING_STYLE);
1148         rc = yaml_emitter_emit(output, &event);
1149         if (rc == 0)
1150                 goto emitter_error;
1151
1152         if (nw) {
1153                 yaml_scalar_event_initialize(&event, NULL,
1154                                              (yaml_char_t *)YAML_STR_TAG,
1155                                              (yaml_char_t *)"net",
1156                                              strlen("net"), 1, 0,
1157                                              YAML_PLAIN_SCALAR_STYLE);
1158                 rc = yaml_emitter_emit(output, &event);
1159                 if (rc == 0)
1160                         goto emitter_error;
1161
1162                 yaml_scalar_event_initialize(&event, NULL,
1163                                              (yaml_char_t *)YAML_STR_TAG,
1164                                              (yaml_char_t *)nw,
1165                                              strlen(nw), 1, 0,
1166                                              YAML_PLAIN_SCALAR_STYLE);
1167                 rc = yaml_emitter_emit(output, &event);
1168                 if (rc == 0)
1169                         goto emitter_error;
1170         }
1171
1172         if (gw) {
1173                 yaml_scalar_event_initialize(&event, NULL,
1174                                              (yaml_char_t *)YAML_STR_TAG,
1175                                              (yaml_char_t *)"gateway",
1176                                              strlen("gateway"), 1, 0,
1177                                              YAML_PLAIN_SCALAR_STYLE);
1178                 rc = yaml_emitter_emit(output, &event);
1179                 if (rc == 0)
1180                         goto emitter_error;
1181
1182                 yaml_scalar_event_initialize(&event, NULL,
1183                                              (yaml_char_t *)YAML_STR_TAG,
1184                                              (yaml_char_t *)gw,
1185                                              strlen(gw), 1, 0,
1186                                              YAML_PLAIN_SCALAR_STYLE);
1187                 rc = yaml_emitter_emit(output, &event);
1188                 if (rc == 0)
1189                         goto emitter_error;
1190         }
1191
1192         if (hops != -1) {
1193                 yaml_scalar_event_initialize(&event, NULL,
1194                                              (yaml_char_t *)YAML_STR_TAG,
1195                                              (yaml_char_t *)"hop",
1196                                              strlen("hop"), 1, 0,
1197                                              YAML_PLAIN_SCALAR_STYLE);
1198                 rc = yaml_emitter_emit(output, &event);
1199                 if (rc == 0)
1200                         goto emitter_error;
1201
1202                 snprintf(num, sizeof(num), "%d", hops);
1203                 yaml_scalar_event_initialize(&event, NULL,
1204                                              (yaml_char_t *)YAML_INT_TAG,
1205                                              (yaml_char_t *)num,
1206                                              strlen(num), 1, 0,
1207                                              YAML_PLAIN_SCALAR_STYLE);
1208                 rc = yaml_emitter_emit(output, &event);
1209                 if (rc == 0)
1210                         goto emitter_error;
1211         }
1212
1213         if (prio != -1) {
1214                 yaml_scalar_event_initialize(&event, NULL,
1215                                              (yaml_char_t *)YAML_STR_TAG,
1216                                              (yaml_char_t *)"priority",
1217                                              strlen("priority"), 1, 0,
1218                                              YAML_PLAIN_SCALAR_STYLE);
1219                 rc = yaml_emitter_emit(output, &event);
1220                 if (rc == 0)
1221                         goto emitter_error;
1222
1223                 snprintf(num, sizeof(num), "%d", prio);
1224                 yaml_scalar_event_initialize(&event, NULL,
1225                                              (yaml_char_t *)YAML_INT_TAG,
1226                                              (yaml_char_t *)num,
1227                                              strlen(num), 1, 0,
1228                                              YAML_PLAIN_SCALAR_STYLE);
1229                 rc = yaml_emitter_emit(output, &event);
1230                 if (rc == 0)
1231                         goto emitter_error;
1232         }
1233
1234         if (sen != -1) {
1235                 yaml_scalar_event_initialize(&event, NULL,
1236                                              (yaml_char_t *)YAML_STR_TAG,
1237                                              (yaml_char_t *)"health_sensitivity",
1238                                              strlen("health_sensitivity"),
1239                                              1, 0,
1240                                              YAML_PLAIN_SCALAR_STYLE);
1241                 rc = yaml_emitter_emit(output, &event);
1242                 if (rc == 0)
1243                         goto emitter_error;
1244
1245                 snprintf(num, sizeof(num), "%d", sen);
1246                 yaml_scalar_event_initialize(&event, NULL,
1247                                              (yaml_char_t *)YAML_INT_TAG,
1248                                              (yaml_char_t *)num,
1249                                              strlen(num), 1, 0,
1250                                              YAML_PLAIN_SCALAR_STYLE);
1251                 rc = yaml_emitter_emit(output, &event);
1252                 if (rc == 0)
1253                         goto emitter_error;
1254         }
1255
1256         yaml_mapping_end_event_initialize(&event);
1257         rc = yaml_emitter_emit(output, &event);
1258 emitter_error:
1259         return rc;
1260 }
1261
1262 static int yaml_lnet_route(char *nw, char *gw, int hops, int prio, int sen,
1263                            int version, int flags)
1264 {
1265         struct nid_node head, *entry;
1266         struct nl_sock *sk = NULL;
1267         const char *msg = NULL;
1268         yaml_emitter_t output;
1269         yaml_parser_t reply;
1270         yaml_event_t event;
1271         int rc;
1272
1273         if (!(flags & NLM_F_DUMP) && (!nw || !gw)) {
1274                 fprintf(stdout, "missing mandatory parameters:'%s'\n",
1275                         (!nw && !gw) ? "net , gateway" :
1276                         !nw ? "net" : "gateway");
1277                 return -EINVAL;
1278         }
1279
1280         /* Create Netlink emitter to send request to kernel */
1281         sk = nl_socket_alloc();
1282         if (!sk)
1283                 return -EOPNOTSUPP;
1284
1285         /* Setup parser to receive Netlink packets */
1286         rc = yaml_parser_initialize(&reply);
1287         if (rc == 0) {
1288                 nl_socket_free(sk);
1289                 return -EOPNOTSUPP;
1290         }
1291
1292         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1293         if (rc == 0) {
1294                 msg = yaml_parser_get_reader_error(&reply);
1295                 goto free_reply;
1296         }
1297
1298         /* Create Netlink emitter to send request to kernel */
1299         rc = yaml_emitter_initialize(&output);
1300         if (rc == 0) {
1301                 msg = "failed to initialize emitter";
1302                 goto free_reply;
1303         }
1304
1305         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1306                                              version, LNET_CMD_ROUTES, flags);
1307         if (rc == 0)
1308                 goto emitter_error;
1309
1310         yaml_emitter_open(&output);
1311         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1312         rc = yaml_emitter_emit(&output, &event);
1313         if (rc == 0)
1314                 goto emitter_error;
1315
1316         yaml_mapping_start_event_initialize(&event, NULL,
1317                                             (yaml_char_t *)YAML_MAP_TAG,
1318                                             1, YAML_ANY_MAPPING_STYLE);
1319         rc = yaml_emitter_emit(&output, &event);
1320         if (rc == 0)
1321                 goto emitter_error;
1322
1323         yaml_scalar_event_initialize(&event, NULL,
1324                                      (yaml_char_t *)YAML_STR_TAG,
1325                                      (yaml_char_t *)"route",
1326                                      strlen("route"), 1, 0,
1327                                      YAML_PLAIN_SCALAR_STYLE);
1328         rc = yaml_emitter_emit(&output, &event);
1329         if (rc == 0)
1330                 goto emitter_error;
1331
1332         /* NLM_F_DUMP can have no arguments */
1333         if (nw || gw) {
1334                 NL_INIT_LIST_HEAD(&head.children);
1335                 nl_init_list_head(&head.list);
1336                 if (gw) {
1337                         rc = lustre_lnet_parse_nid_range(&head, gw, &msg);
1338                         if (rc < 0) {
1339                                 lustre_lnet_free_list(&head);
1340                                 yaml_emitter_delete(&output);
1341                                 errno = rc;
1342                                 rc = 0;
1343                                 goto free_reply;
1344                         }
1345                 }
1346
1347                 yaml_sequence_start_event_initialize(&event, NULL,
1348                                                      (yaml_char_t *)YAML_SEQ_TAG,
1349                                                      1,
1350                                                      YAML_BLOCK_SEQUENCE_STYLE);
1351                 rc = yaml_emitter_emit(&output, &event);
1352                 if (rc == 0)
1353                         goto emitter_error;
1354
1355                 if (!nl_list_empty(&head.children)) {
1356                         nl_list_for_each_entry(entry, &head.children, list) {
1357                                 const char *nid = entry->nidstr;
1358
1359                                 rc = yaml_lnet_router_gateways(&output, nw, nid,
1360                                                                hops, prio, sen);
1361                                 if (rc == 0)
1362                                         goto emitter_error;
1363                         }
1364                 } else {
1365                         rc = yaml_lnet_router_gateways(&output, nw, NULL, hops,
1366                                                        prio, sen);
1367                         if (rc == 0)
1368                                 goto emitter_error;
1369                 }
1370
1371                 yaml_sequence_end_event_initialize(&event);
1372                 rc = yaml_emitter_emit(&output, &event);
1373                 if (rc == 0)
1374                         goto emitter_error;
1375         } else {
1376                 yaml_scalar_event_initialize(&event, NULL,
1377                                              (yaml_char_t *)YAML_STR_TAG,
1378                                              (yaml_char_t *)"",
1379                                              strlen(""), 1, 0,
1380                                              YAML_PLAIN_SCALAR_STYLE);
1381                 rc = yaml_emitter_emit(&output, &event);
1382                 if (rc == 0)
1383                         goto emitter_error;
1384         }
1385
1386         yaml_mapping_end_event_initialize(&event);
1387         rc = yaml_emitter_emit(&output, &event);
1388         if (rc == 0)
1389                 goto emitter_error;
1390
1391         yaml_document_end_event_initialize(&event, 0);
1392         rc = yaml_emitter_emit(&output, &event);
1393         if (rc == 0)
1394                 goto emitter_error;
1395
1396         rc = yaml_emitter_close(&output);
1397 emitter_error:
1398         if (rc == 0) {
1399                 yaml_emitter_log_error(&output, stderr);
1400                 rc = -EINVAL;
1401         } else {
1402                 yaml_document_t errmsg;
1403
1404                 rc = yaml_parser_load(&reply, &errmsg);
1405                 if (rc == 1 && (flags & NLM_F_DUMP)) {
1406                         yaml_emitter_t debug;
1407
1408                         rc = yaml_emitter_initialize(&debug);
1409                         if (rc == 1) {
1410                                 yaml_emitter_set_indent(&debug,
1411                                                         LNET_DEFAULT_INDENT);
1412                                 yaml_emitter_set_output_file(&debug,
1413                                                              stdout);
1414                                 rc = yaml_emitter_dump(&debug, &errmsg);
1415                         }
1416                         yaml_emitter_delete(&debug);
1417                 } else {
1418                         msg = yaml_parser_get_reader_error(&reply);
1419                         /* If we didn't find any routes just be silent */
1420                         if (msg && strcmp(msg, "No routes found") == 0)
1421                                 rc = 1;
1422                 }
1423                 yaml_document_delete(&errmsg);
1424         }
1425         yaml_emitter_delete(&output);
1426 free_reply:
1427         if (rc == 0) {
1428                 yaml_lnet_print_error(flags, "route", msg);
1429                 rc = -EINVAL;
1430         }
1431         yaml_parser_delete(&reply);
1432         nl_socket_free(sk);
1433
1434         return rc == 1 ? 0 : rc;
1435 }
1436
1437 static int jt_add_route(int argc, char **argv)
1438 {
1439         char *network = NULL, *gateway = NULL;
1440         long int hop = -1, prio = -1, sen = -1;
1441         struct cYAML *err_rc = NULL;
1442         int rc, opt;
1443
1444         const char *const short_options = "n:g:c:p:";
1445         static const struct option long_options[] = {
1446                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
1447                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1448                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
1449                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1450                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1451                 { .name = "health_sensitivity",  .has_arg = required_argument, .val = 's' },
1452                 { .name = NULL }
1453         };
1454
1455         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
1456         if (rc)
1457                 return rc;
1458
1459         while ((opt = getopt_long(argc, argv, short_options,
1460                                    long_options, NULL)) != -1) {
1461                 switch (opt) {
1462                 case 'n':
1463                         network = optarg;
1464                         break;
1465                 case 'g':
1466                         gateway = optarg;
1467                         break;
1468                 case 'c':
1469                         rc = parse_long(optarg, &hop);
1470                         if (rc != 0) {
1471                                 /* ignore option */
1472                                 hop = -1;
1473                                 continue;
1474                         }
1475                         break;
1476                 case 'p':
1477                         rc = parse_long(optarg, &prio);
1478                         if (rc != 0) {
1479                                 /* ingore option */
1480                                 prio = -1;
1481                                 continue;
1482                         }
1483                         break;
1484                 case 's':
1485                         rc = parse_long(optarg, &sen);
1486                         if (rc != 0) {
1487                                 /* ingore option */
1488                                 sen = -1;
1489                                 continue;
1490                         }
1491                         break;
1492
1493                 case '?':
1494                         print_help(route_cmds, "route", "add");
1495                 default:
1496                         return 0;
1497                 }
1498         }
1499
1500         rc = yaml_lnet_route(network, gateway, hop, prio, sen,
1501                              LNET_GENL_VERSION, NLM_F_CREATE);
1502         if (rc <= 0) {
1503                 if (rc == -EOPNOTSUPP)
1504                         goto old_api;
1505                 return rc;
1506         }
1507 old_api:
1508         rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
1509                                       &err_rc);
1510
1511         if (rc != LUSTRE_CFG_RC_NO_ERR)
1512                 cYAML_print_tree2file(stderr, err_rc);
1513
1514         cYAML_free_tree(err_rc);
1515
1516         return rc;
1517 }
1518
1519 static int yaml_add_ni_tunables(yaml_emitter_t *output,
1520                                 struct lnet_ioctl_config_lnd_tunables *tunables,
1521                                 struct lnet_dlc_network_descr *nw_descr)
1522 {
1523         char num[INT_STRING_LEN];
1524         yaml_event_t event;
1525         int rc;
1526
1527         if (tunables->lt_cmn.lct_peer_timeout < 0 &&
1528             tunables->lt_cmn.lct_peer_tx_credits <= 0 &&
1529             tunables->lt_cmn.lct_peer_rtr_credits <= 0 &&
1530             tunables->lt_cmn.lct_max_tx_credits <= 0)
1531                 goto skip_general_settings;
1532
1533         yaml_scalar_event_initialize(&event, NULL,
1534                                      (yaml_char_t *)YAML_STR_TAG,
1535                                      (yaml_char_t *)"tunables",
1536                                      strlen("tunables"), 1, 0,
1537                                      YAML_PLAIN_SCALAR_STYLE);
1538         rc = yaml_emitter_emit(output, &event);
1539         if (rc == 0)
1540                 goto error;
1541
1542         yaml_mapping_start_event_initialize(&event, NULL,
1543                                             (yaml_char_t *)YAML_MAP_TAG,
1544                                             1, YAML_ANY_MAPPING_STYLE);
1545         rc = yaml_emitter_emit(output, &event);
1546         if (rc == 0)
1547                 goto error;
1548
1549         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1550                 yaml_scalar_event_initialize(&event, NULL,
1551                                              (yaml_char_t *)YAML_STR_TAG,
1552                                              (yaml_char_t *)"peer_timeout",
1553                                              strlen("peer_timeout"), 1, 0,
1554                                              YAML_PLAIN_SCALAR_STYLE);
1555                 rc = yaml_emitter_emit(output, &event);
1556                 if (rc == 0)
1557                         goto error;
1558
1559                 snprintf(num, sizeof(num), "%u",
1560                          tunables->lt_cmn.lct_peer_timeout);
1561                 yaml_scalar_event_initialize(&event, NULL,
1562                                              (yaml_char_t *)YAML_INT_TAG,
1563                                              (yaml_char_t *)num,
1564                                              strlen(num), 1, 0,
1565                                              YAML_PLAIN_SCALAR_STYLE);
1566                 rc = yaml_emitter_emit(output, &event);
1567                 if (rc == 0)
1568                         goto error;
1569         }
1570
1571         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1572                 yaml_scalar_event_initialize(&event, NULL,
1573                                              (yaml_char_t *)YAML_STR_TAG,
1574                                              (yaml_char_t *)"peer_credits",
1575                                              strlen("peer_credits"), 1, 0,
1576                                              YAML_PLAIN_SCALAR_STYLE);
1577                 rc = yaml_emitter_emit(output, &event);
1578                 if (rc == 0)
1579                         goto error;
1580
1581                 snprintf(num, sizeof(num), "%u",
1582                          tunables->lt_cmn.lct_peer_tx_credits);
1583                 yaml_scalar_event_initialize(&event, NULL,
1584                                              (yaml_char_t *)YAML_INT_TAG,
1585                                              (yaml_char_t *)num,
1586                                              strlen(num), 1, 0,
1587                                              YAML_PLAIN_SCALAR_STYLE);
1588                 rc = yaml_emitter_emit(output, &event);
1589                 if (rc == 0)
1590                         goto error;
1591         }
1592
1593         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1594                 yaml_scalar_event_initialize(&event, NULL,
1595                                              (yaml_char_t *)YAML_STR_TAG,
1596                                              (yaml_char_t *)"peer_buffer_credits",
1597                                              strlen("peer_buffer_credits"), 1, 0,
1598                                              YAML_PLAIN_SCALAR_STYLE);
1599                 rc = yaml_emitter_emit(output, &event);
1600                 if (rc == 0)
1601                         goto error;
1602
1603                 snprintf(num, sizeof(num), "%u",
1604                          tunables->lt_cmn.lct_peer_rtr_credits);
1605                 yaml_scalar_event_initialize(&event, NULL,
1606                                              (yaml_char_t *)YAML_INT_TAG,
1607                                              (yaml_char_t *)num,
1608                                              strlen(num), 1, 0,
1609                                              YAML_PLAIN_SCALAR_STYLE);
1610                 rc = yaml_emitter_emit(output, &event);
1611                 if (rc == 0)
1612                         goto error;
1613         }
1614
1615         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1616                 yaml_scalar_event_initialize(&event, NULL,
1617                                              (yaml_char_t *)YAML_STR_TAG,
1618                                              (yaml_char_t *)"credits",
1619                                              strlen("credits"), 1, 0,
1620                                              YAML_PLAIN_SCALAR_STYLE);
1621                 rc = yaml_emitter_emit(output, &event);
1622                 if (rc == 0)
1623                         goto error;
1624
1625                 snprintf(num, sizeof(num), "%u",
1626                          tunables->lt_cmn.lct_max_tx_credits);
1627                 yaml_scalar_event_initialize(&event, NULL,
1628                                              (yaml_char_t *)YAML_INT_TAG,
1629                                              (yaml_char_t *)num,
1630                                              strlen(num), 1, 0,
1631                                              YAML_PLAIN_SCALAR_STYLE);
1632                 rc = yaml_emitter_emit(output, &event);
1633                 if (rc == 0)
1634                         goto error;
1635         }
1636
1637         yaml_mapping_end_event_initialize(&event);
1638         rc = yaml_emitter_emit(output, &event);
1639         if (rc == 0)
1640                 goto error;
1641
1642 skip_general_settings:
1643         if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1644 #ifdef HAVE_KFILND
1645             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0 ||
1646             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0] ||
1647 #endif
1648             tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1649                 yaml_scalar_event_initialize(&event, NULL,
1650                                              (yaml_char_t *)YAML_STR_TAG,
1651                                              (yaml_char_t *)"lnd tunables",
1652                                              strlen("lnd tunables"), 1, 0,
1653                                              YAML_PLAIN_SCALAR_STYLE);
1654                 rc = yaml_emitter_emit(output, &event);
1655                 if (rc == 0)
1656                         goto error;
1657
1658                 yaml_mapping_start_event_initialize(&event, NULL,
1659                                                     (yaml_char_t *)YAML_MAP_TAG,
1660                                                     1, YAML_ANY_MAPPING_STYLE);
1661                 rc = yaml_emitter_emit(output, &event);
1662                 if (rc == 0)
1663                         goto error;
1664 #ifdef HAVE_KFILND
1665                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1666                         yaml_scalar_event_initialize(&event, NULL,
1667                                                      (yaml_char_t *)YAML_STR_TAG,
1668                                                      (yaml_char_t *)"auth_key",
1669                                                      strlen("auth_key"), 1, 0,
1670                                                      YAML_PLAIN_SCALAR_STYLE);
1671                         rc = yaml_emitter_emit(output, &event);
1672                         if (rc == 0)
1673                                 goto error;
1674
1675                         snprintf(num, sizeof(num), "%u",
1676                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1677
1678                         yaml_scalar_event_initialize(&event, NULL,
1679                                                      (yaml_char_t *)YAML_INT_TAG,
1680                                                      (yaml_char_t *)num,
1681                                                      strlen(num), 1, 0,
1682                                                      YAML_PLAIN_SCALAR_STYLE);
1683                         rc = yaml_emitter_emit(output, &event);
1684                         if (rc == 0)
1685                                 goto error;
1686                 }
1687
1688                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0]) {
1689                         char *tc = &tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0];
1690
1691                         yaml_scalar_event_initialize(&event, NULL,
1692                                                      (yaml_char_t *)YAML_STR_TAG,
1693                                                      (yaml_char_t *)"traffic_class",
1694                                                      strlen("traffic_class"), 1, 0,
1695                                                      YAML_PLAIN_SCALAR_STYLE);
1696                         rc = yaml_emitter_emit(output, &event);
1697                         if (rc == 0)
1698                                 goto error;
1699
1700                         yaml_scalar_event_initialize(&event, NULL,
1701                                                      (yaml_char_t *)YAML_INT_TAG,
1702                                                      (yaml_char_t *)tc,
1703                                                      strlen(tc), 1, 0,
1704                                                      YAML_PLAIN_SCALAR_STYLE);
1705
1706                         rc = yaml_emitter_emit(output, &event);
1707                         if (rc == 0)
1708                                 goto error;
1709                 }
1710 #endif
1711                 if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1712                     tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1713                         int cpp = 0;
1714
1715                         yaml_scalar_event_initialize(&event, NULL,
1716                                                      (yaml_char_t *)YAML_STR_TAG,
1717                                                      (yaml_char_t *)"conns_per_peer",
1718                                                      strlen("conns_per_peer"), 1, 0,
1719                                                      YAML_PLAIN_SCALAR_STYLE);
1720                         rc = yaml_emitter_emit(output, &event);
1721                         if (rc == 0)
1722                                 goto error;
1723
1724                         if (LNET_NETTYP(nw_descr->nw_id) == SOCKLND)
1725                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1726                         else if (LNET_NETTYP(nw_descr->nw_id) == O2IBLND)
1727                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer;
1728                         snprintf(num, sizeof(num), "%u", cpp);
1729
1730                         yaml_scalar_event_initialize(&event, NULL,
1731                                                      (yaml_char_t *)YAML_INT_TAG,
1732                                                      (yaml_char_t *)num,
1733                                                      strlen(num), 1, 0,
1734                                                      YAML_PLAIN_SCALAR_STYLE);
1735                         rc = yaml_emitter_emit(output, &event);
1736                         if (rc == 0)
1737                                 goto error;
1738                 }
1739
1740                 yaml_mapping_end_event_initialize(&event);
1741                 rc = yaml_emitter_emit(output, &event);
1742         }
1743 error:
1744         return rc;
1745 }
1746
1747 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1748                                struct lnet_dlc_network_descr *nw_descr,
1749                                struct lnet_ioctl_config_lnd_tunables *tunables,
1750                                struct cfs_expr_list *global_cpts,
1751                                int version, int flags)
1752 {
1753         struct lnet_dlc_intf_descr *intf;
1754         struct nl_sock *sk = NULL;
1755         const char *msg = NULL;
1756         yaml_emitter_t output;
1757         yaml_parser_t reply;
1758         yaml_event_t event;
1759         int rc;
1760
1761         if (!(flags & NLM_F_DUMP) && !ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1762                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'",
1763                         (!nw_descr) ? "network , interface" :
1764                         (nw_descr->nw_id == 0) ? "network" : "interface");
1765                 return -EINVAL;
1766         }
1767
1768         if ((flags == NLM_F_CREATE) && !ip2net && list_empty(&nw_descr->nw_intflist)) {
1769                 fprintf(stdout, "creating a local NI needs at least one interface");
1770                 return -EINVAL;
1771         }
1772
1773         /* Create Netlink emitter to send request to kernel */
1774         sk = nl_socket_alloc();
1775         if (!sk)
1776                 return -EOPNOTSUPP;
1777
1778         /* Setup parser to receive Netlink packets */
1779         rc = yaml_parser_initialize(&reply);
1780         if (rc == 0) {
1781                 nl_socket_free(sk);
1782                 return -EOPNOTSUPP;
1783         }
1784
1785         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1786         if (rc == 0) {
1787                 msg = yaml_parser_get_reader_error(&reply);
1788                 goto free_reply;
1789         }
1790
1791         /* Create Netlink emitter to send request to kernel */
1792         rc = yaml_emitter_initialize(&output);
1793         if (rc == 0) {
1794                 msg = "failed to initialize emitter";
1795                 goto free_reply;
1796         }
1797
1798         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1799                                              version, LNET_CMD_NETS, flags);
1800         if (rc == 0)
1801                 goto emitter_error;
1802
1803         yaml_emitter_open(&output);
1804         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1805         rc = yaml_emitter_emit(&output, &event);
1806         if (rc == 0)
1807                 goto emitter_error;
1808
1809         yaml_mapping_start_event_initialize(&event, NULL,
1810                                             (yaml_char_t *)YAML_MAP_TAG,
1811                                             1, YAML_ANY_MAPPING_STYLE);
1812         rc = yaml_emitter_emit(&output, &event);
1813         if (rc == 0)
1814                 goto emitter_error;
1815
1816         yaml_scalar_event_initialize(&event, NULL,
1817                                      (yaml_char_t *)YAML_STR_TAG,
1818                                      (yaml_char_t *)"net",
1819                                      strlen("net"), 1, 0,
1820                                      YAML_PLAIN_SCALAR_STYLE);
1821         rc = yaml_emitter_emit(&output, &event);
1822         if (rc == 0)
1823                 goto emitter_error;
1824
1825         if (net_id || ip2net) {
1826                 char *key = net_id ? "net type" : "ip2net";
1827                 char *value = net_id ? net_id : ip2net;
1828
1829                 yaml_sequence_start_event_initialize(&event, NULL,
1830                                                      (yaml_char_t *)YAML_SEQ_TAG,
1831                                                      1, YAML_ANY_SEQUENCE_STYLE);
1832                 rc = yaml_emitter_emit(&output, &event);
1833                 if (rc == 0)
1834                         goto emitter_error;
1835
1836                 yaml_mapping_start_event_initialize(&event, NULL,
1837                                                     (yaml_char_t *)YAML_MAP_TAG,
1838                                                     1, YAML_ANY_MAPPING_STYLE);
1839                 rc = yaml_emitter_emit(&output, &event);
1840                 if (rc == 0)
1841                         goto emitter_error;
1842
1843                 yaml_scalar_event_initialize(&event, NULL,
1844                                              (yaml_char_t *)YAML_STR_TAG,
1845                                              (yaml_char_t *)key,
1846                                              strlen(key),
1847                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
1848                 rc = yaml_emitter_emit(&output, &event);
1849                 if (rc == 0)
1850                         goto emitter_error;
1851
1852                 yaml_scalar_event_initialize(&event, NULL,
1853                                              (yaml_char_t *)YAML_STR_TAG,
1854                                              (yaml_char_t *)value,
1855                                              strlen(value), 1, 0,
1856                                              YAML_PLAIN_SCALAR_STYLE);
1857                 rc = yaml_emitter_emit(&output, &event);
1858                 if (rc == 0)
1859                         goto emitter_error;
1860         } else {
1861                 yaml_scalar_event_initialize(&event, NULL,
1862                                              (yaml_char_t *)YAML_STR_TAG,
1863                                              (yaml_char_t *)"",
1864                                              strlen(""), 1, 0,
1865                                              YAML_PLAIN_SCALAR_STYLE);
1866                 rc = yaml_emitter_emit(&output, &event);
1867                 if (rc == 0)
1868                         goto emitter_error;
1869
1870                 goto no_net_id;
1871         }
1872
1873         if (!nw_descr || list_empty(&nw_descr->nw_intflist))
1874                 goto skip_intf;
1875
1876         yaml_scalar_event_initialize(&event, NULL,
1877                                      (yaml_char_t *)YAML_STR_TAG,
1878                                      (yaml_char_t *)"local NI(s)",
1879                                      strlen("local NI(s)"), 1, 0,
1880                                      YAML_PLAIN_SCALAR_STYLE);
1881         rc = yaml_emitter_emit(&output, &event);
1882         if (rc == 0)
1883                 goto emitter_error;
1884
1885         yaml_sequence_start_event_initialize(&event, NULL,
1886                                              (yaml_char_t *)YAML_SEQ_TAG,
1887                                              1, YAML_ANY_SEQUENCE_STYLE);
1888         rc = yaml_emitter_emit(&output, &event);
1889         if (rc == 0)
1890                 goto emitter_error;
1891
1892         list_for_each_entry(intf, &nw_descr->nw_intflist,
1893                             intf_on_network) {
1894                 yaml_mapping_start_event_initialize(&event, NULL,
1895                                                     (yaml_char_t *)YAML_MAP_TAG,
1896                                                     1, YAML_ANY_MAPPING_STYLE);
1897                 rc = yaml_emitter_emit(&output, &event);
1898                 if (rc == 0)
1899                         goto emitter_error;
1900
1901                 yaml_scalar_event_initialize(&event, NULL,
1902                                              (yaml_char_t *)YAML_STR_TAG,
1903                                              (yaml_char_t *)"interfaces",
1904                                              strlen("interfaces"), 1, 0,
1905                                              YAML_PLAIN_SCALAR_STYLE);
1906                 rc = yaml_emitter_emit(&output, &event);
1907                 if (rc == 0)
1908                         goto emitter_error;
1909
1910                 yaml_mapping_start_event_initialize(&event, NULL,
1911                                                     (yaml_char_t *)YAML_MAP_TAG,
1912                                                     1, YAML_ANY_MAPPING_STYLE);
1913                 rc = yaml_emitter_emit(&output, &event);
1914                 if (rc == 0)
1915                         goto emitter_error;
1916
1917                 yaml_scalar_event_initialize(&event, NULL,
1918                                              (yaml_char_t *)YAML_STR_TAG,
1919                                              (yaml_char_t *)"0",
1920                                              strlen("0"), 1, 0,
1921                                              YAML_PLAIN_SCALAR_STYLE);
1922                 rc = yaml_emitter_emit(&output, &event);
1923                 if (rc == 0)
1924                         goto emitter_error;
1925
1926                 yaml_scalar_event_initialize(&event, NULL,
1927                                              (yaml_char_t *)YAML_STR_TAG,
1928                                              (yaml_char_t *)intf->intf_name,
1929                                              strlen(intf->intf_name), 1, 0,
1930                                              YAML_PLAIN_SCALAR_STYLE);
1931                 rc = yaml_emitter_emit(&output, &event);
1932                 if (rc == 0)
1933                         goto emitter_error;
1934
1935                 yaml_mapping_end_event_initialize(&event);
1936                 rc = yaml_emitter_emit(&output, &event);
1937                 if (rc == 0)
1938                         goto emitter_error;
1939
1940                 if (tunables) {
1941                         rc = yaml_add_ni_tunables(&output, tunables, nw_descr);
1942                         if (rc == 0)
1943                                 goto emitter_error;
1944                 }
1945
1946                 if (global_cpts) {
1947                         __u32 *cpt_array;
1948                         int count, i;
1949
1950                         yaml_scalar_event_initialize(&event, NULL,
1951                                                      (yaml_char_t *)YAML_STR_TAG,
1952                                                      (yaml_char_t *)"CPT",
1953                                                      strlen("CPT"), 1, 0,
1954                                                      YAML_PLAIN_SCALAR_STYLE);
1955                         rc = yaml_emitter_emit(&output, &event);
1956                         if (rc == 0)
1957                                 goto emitter_error;
1958
1959                         yaml_sequence_start_event_initialize(&event, NULL,
1960                                                              (yaml_char_t *)YAML_SEQ_TAG,
1961                                                              1,
1962                                                              YAML_FLOW_SEQUENCE_STYLE);
1963                         rc = yaml_emitter_emit(&output, &event);
1964                         if (rc == 0)
1965                                 goto emitter_error;
1966
1967                         count = cfs_expr_list_values(global_cpts,
1968                                                      LNET_MAX_SHOW_NUM_CPT,
1969                                                      &cpt_array);
1970                         for (i = 0; i < count; i++) {
1971                                 char core[INT_STRING_LEN];
1972
1973                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
1974                                 yaml_scalar_event_initialize(&event, NULL,
1975                                                              (yaml_char_t *)YAML_STR_TAG,
1976                                                              (yaml_char_t *)core,
1977                                                              strlen(core), 1, 0,
1978                                                              YAML_PLAIN_SCALAR_STYLE);
1979                                 rc = yaml_emitter_emit(&output, &event);
1980                                 if (rc == 0)
1981                                         goto emitter_error;
1982                         }
1983
1984                         yaml_sequence_end_event_initialize(&event);
1985                         rc = yaml_emitter_emit(&output, &event);
1986                         if (rc == 0)
1987                                 goto emitter_error;
1988
1989                         cfs_expr_list_free(global_cpts);
1990                         free(cpt_array);
1991                 }
1992
1993                 yaml_mapping_end_event_initialize(&event);
1994                 rc = yaml_emitter_emit(&output, &event);
1995                 if (rc == 0)
1996                         goto emitter_error;
1997         }
1998
1999         yaml_sequence_end_event_initialize(&event);
2000         rc = yaml_emitter_emit(&output, &event);
2001         if (rc == 0)
2002                 goto emitter_error;
2003 skip_intf:
2004         yaml_mapping_end_event_initialize(&event);
2005         rc = yaml_emitter_emit(&output, &event);
2006         if (rc == 0)
2007                 goto emitter_error;
2008
2009         yaml_sequence_end_event_initialize(&event);
2010         rc = yaml_emitter_emit(&output, &event);
2011         if (rc == 0)
2012                 goto emitter_error;
2013 no_net_id:
2014         yaml_mapping_end_event_initialize(&event);
2015         rc = yaml_emitter_emit(&output, &event);
2016         if (rc == 0)
2017                 goto emitter_error;
2018
2019         yaml_document_end_event_initialize(&event, 0);
2020         rc = yaml_emitter_emit(&output, &event);
2021         if (rc == 0)
2022                 goto emitter_error;
2023
2024         rc = yaml_emitter_close(&output);
2025 emitter_error:
2026         if (rc == 0) {
2027                 yaml_emitter_log_error(&output, stderr);
2028                 rc = -EINVAL;
2029         } else {
2030                 yaml_document_t errmsg;
2031
2032                 rc = yaml_parser_load(&reply, &errmsg);
2033                 if (rc == 1 && (flags & NLM_F_DUMP)) {
2034                         yaml_emitter_t debug;
2035
2036                         rc = yaml_emitter_initialize(&debug);
2037                         if (rc == 1) {
2038                                 yaml_emitter_set_indent(&debug,
2039                                                         LNET_DEFAULT_INDENT);
2040                                 yaml_emitter_set_output_file(&debug, stdout);
2041                                 rc = yaml_emitter_dump(&debug, &errmsg);
2042                         }
2043                         yaml_emitter_delete(&debug);
2044                 } else {
2045                         msg = yaml_parser_get_reader_error(&reply);
2046                 }
2047                 yaml_document_delete(&errmsg);
2048         }
2049         yaml_emitter_delete(&output);
2050 free_reply:
2051         if (rc == 0) {
2052                 yaml_lnet_print_error(flags, "net", msg);
2053                 rc = -EINVAL;
2054         }
2055         yaml_parser_delete(&reply);
2056         nl_socket_free(sk);
2057
2058         return rc == 1 ? 0 : rc;
2059 }
2060
2061 static int jt_add_ni(int argc, char **argv)
2062 {
2063         char *ip2net = NULL;
2064         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
2065         char *traffic_class = NULL;
2066         struct cYAML *err_rc = NULL;
2067         int rc, opt, cpt_rc = -1;
2068         struct lnet_dlc_network_descr nw_descr;
2069         struct cfs_expr_list *global_cpts = NULL;
2070         struct lnet_ioctl_config_lnd_tunables tunables;
2071         bool found = false;
2072         bool skip_mr_route_setup = false;
2073         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:T:";
2074         static const struct option long_options[] = {
2075         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
2076         { .name = "peer-buffer-credits",
2077                                   .has_arg = required_argument, .val = 'b' },
2078         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
2079         { .name = "if",           .has_arg = required_argument, .val = 'i' },
2080         { .name = "skip-mr-route-setup",
2081                                   .has_arg = no_argument, .val = 'k' },
2082         { .name = "conns-per-peer",
2083                                   .has_arg = required_argument, .val = 'm' },
2084         { .name = "net",          .has_arg = required_argument, .val = 'n' },
2085         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
2086         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
2087         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
2088         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
2089         { .name = "traffic-class", .has_arg = required_argument, .val = 'T' },
2090         { .name = NULL } };
2091         char *net_id = NULL;
2092
2093         memset(&tunables, 0, sizeof(tunables));
2094         lustre_lnet_init_nw_descr(&nw_descr);
2095
2096         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
2097         if (rc)
2098                 return rc;
2099
2100         while ((opt = getopt_long(argc, argv, short_options,
2101                                    long_options, NULL)) != -1) {
2102                 switch (opt) {
2103                 case 'a':
2104                         rc = parse_long(optarg, &auth_key);
2105                         if (rc != 0) {
2106                                 /* ignore option */
2107                                 auth_key = -1;
2108                                 continue;
2109                         }
2110                         break;
2111                 case 'b':
2112                         rc = parse_long(optarg, &pbc);
2113                         if (rc != 0) {
2114                                 /* ignore option */
2115                                 pbc = -1;
2116                                 continue;
2117                         }
2118                         break;
2119                 case 'c':
2120                         rc = parse_long(optarg, &pc);
2121                         if (rc != 0) {
2122                                 /* ignore option */
2123                                 pc = -1;
2124                                 continue;
2125                         }
2126                         break;
2127                 case 'i':
2128                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2129                         if (rc != 0) {
2130                                 cYAML_build_error(-1, -1, "ni", "add",
2131                                                 "bad interface list",
2132                                                 &err_rc);
2133                                 goto failed;
2134                         }
2135                         break;
2136                 case 'k':
2137                         skip_mr_route_setup = true;
2138                         break;
2139                 case 'm':
2140                         rc = parse_long(optarg, &cpp);
2141                         if (rc != 0) {
2142                                 /* ignore option */
2143                                 cpp = -1;
2144                                 continue;
2145                         }
2146                         break;
2147
2148                 case 'n':
2149                         nw_descr.nw_id = libcfs_str2net(optarg);
2150                         net_id = optarg;
2151                         break;
2152                 case 'p':
2153                         ip2net = optarg;
2154                         break;
2155                 case 'r':
2156                         rc = parse_long(optarg, &cre);
2157                         if (rc != 0) {
2158                                 /* ignore option */
2159                                 cre = -1;
2160                                 continue;
2161                         }
2162                         break;
2163                 case 's':
2164                         cpt_rc = cfs_expr_list_parse(optarg,
2165                                                      strlen(optarg), 0,
2166                                                      UINT_MAX, &global_cpts);
2167                         break;
2168                 case 't':
2169                         rc = parse_long(optarg, &pto);
2170                         if (rc != 0) {
2171                                 /* ignore option */
2172                                 pto = -1;
2173                                 continue;
2174                         }
2175                         break;
2176                 case 'T':
2177                         traffic_class = optarg;
2178                         if (strlen(traffic_class) == 0 ||
2179                             strlen(traffic_class) >= LNET_MAX_STR_LEN) {
2180                                 cYAML_build_error(-1, -1, "ni", "add",
2181                                                   "Invalid traffic-class argument",
2182                                                   &err_rc);
2183                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2184                                 goto failed;
2185                         }
2186                         break;
2187                 case '?':
2188                         print_help(net_cmds, "net", "add");
2189                 default:
2190                         return 0;
2191                 }
2192         }
2193 #ifdef HAVE_KFILND
2194         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
2195                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
2196                 found = true;
2197         }
2198
2199         if (traffic_class && LNET_NETTYP(nw_descr.nw_id) == KFILND &&
2200             strlen(traffic_class) < LNET_MAX_STR_LEN) {
2201                 strcpy(&tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0],
2202                        traffic_class);
2203                 found = true;
2204         }
2205 #endif
2206
2207         if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1)) {
2208                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2209                 found = true;
2210         } else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1)) {
2211                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
2212                 found = true;
2213         }
2214
2215         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
2216                 tunables.lt_cmn.lct_peer_timeout = pto;
2217                 tunables.lt_cmn.lct_peer_tx_credits = pc;
2218                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
2219                 tunables.lt_cmn.lct_max_tx_credits = cre;
2220                 found = true;
2221         }
2222
2223         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
2224                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
2225
2226         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
2227                                  found ? &tunables : NULL,
2228                                  (cpt_rc == 0) ? global_cpts : NULL,
2229                                  LNET_GENL_VERSION, NLM_F_CREATE);
2230         if (rc <= 0) {
2231                 if (rc == -EOPNOTSUPP)
2232                         goto old_api;
2233                 if (global_cpts != NULL)
2234                         cfs_expr_list_free(global_cpts);
2235                 if (rc == 0 && !skip_mr_route_setup)
2236                         rc = lustre_lnet_setup_mrrouting(&err_rc);
2237                 return rc;
2238         }
2239 old_api:
2240         rc = lustre_lnet_config_ni(&nw_descr,
2241                                    (cpt_rc == 0) ? global_cpts: NULL,
2242                                    ip2net, (found) ? &tunables : NULL,
2243                                    cpp, &err_rc);
2244
2245         if (global_cpts != NULL)
2246                 cfs_expr_list_free(global_cpts);
2247
2248 failed:
2249         if (rc != LUSTRE_CFG_RC_NO_ERR)
2250                 cYAML_print_tree2file(stderr, err_rc);
2251
2252         cYAML_free_tree(err_rc);
2253
2254         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
2255                 err_rc = NULL;
2256                 rc = lustre_lnet_setup_mrrouting(&err_rc);
2257
2258                 if (rc != LUSTRE_CFG_RC_NO_ERR)
2259                         cYAML_print_tree2file(stderr, err_rc);
2260
2261                 cYAML_free_tree(err_rc);
2262         }
2263
2264         return rc;
2265 }
2266
2267 static int jt_del_route(int argc, char **argv)
2268 {
2269         char *network = NULL, *gateway = NULL;
2270         struct cYAML *err_rc = NULL;
2271         int rc, opt;
2272         const char *const short_options = "n:g:";
2273         static const struct option long_options[] = {
2274                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2275                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
2276                 { .name = NULL }
2277         };
2278
2279         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
2280         if (rc)
2281                 return rc;
2282
2283         while ((opt = getopt_long(argc, argv, short_options,
2284                                    long_options, NULL)) != -1) {
2285                 switch (opt) {
2286                 case 'n':
2287                         network = optarg;
2288                         break;
2289                 case 'g':
2290                         gateway = optarg;
2291                         break;
2292                 case '?':
2293                         print_help(route_cmds, "route", "del");
2294                 default:
2295                         return 0;
2296                 }
2297         }
2298
2299         rc = yaml_lnet_route(network, gateway, -1, -1, -1, LNET_GENL_VERSION,
2300                              0);
2301         if (rc <= 0) {
2302                 if (rc == -EOPNOTSUPP)
2303                         goto old_api;
2304                 return rc;
2305         }
2306 old_api:
2307         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
2308
2309         if (rc != LUSTRE_CFG_RC_NO_ERR)
2310                 cYAML_print_tree2file(stderr, err_rc);
2311
2312         cYAML_free_tree(err_rc);
2313
2314         return rc;
2315 }
2316
2317 static int jt_del_ni(int argc, char **argv)
2318 {
2319         struct cYAML *err_rc = NULL;
2320         int rc, opt;
2321         struct lnet_dlc_network_descr nw_descr;
2322         const char *const short_options = "n:i:";
2323         static const struct option long_options[] = {
2324         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
2325         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
2326         { .name = NULL } };
2327         char *net_id = NULL;
2328
2329         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
2330         if (rc)
2331                 return rc;
2332
2333         lustre_lnet_init_nw_descr(&nw_descr);
2334
2335         while ((opt = getopt_long(argc, argv, short_options,
2336                                    long_options, NULL)) != -1) {
2337                 switch (opt) {
2338                 case 'n':
2339                         nw_descr.nw_id = libcfs_str2net(optarg);
2340                         net_id = optarg;
2341                         break;
2342                 case 'i':
2343                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2344                         if (rc != 0) {
2345                                 cYAML_build_error(-1, -1, "ni", "add",
2346                                                 "bad interface list",
2347                                                 &err_rc);
2348                                 goto out;
2349                         }
2350                         break;
2351                 case '?':
2352                         print_help(net_cmds, "net", "del");
2353                 default:
2354                         return 0;
2355                 }
2356         }
2357
2358         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, NULL,
2359                                  LNET_GENL_VERSION, 0);
2360         if (rc <= 0) {
2361                 if (rc != -EOPNOTSUPP)
2362                         return rc;
2363         }
2364
2365         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
2366 out:
2367         if (rc != LUSTRE_CFG_RC_NO_ERR)
2368                 cYAML_print_tree2file(stderr, err_rc);
2369
2370         cYAML_free_tree(err_rc);
2371
2372         return rc;
2373 }
2374
2375 static int jt_show_route(int argc, char **argv)
2376 {
2377         char *network = NULL, *gateway = NULL;
2378         long int hop = -1, prio = -1;
2379         int detail = 0, rc, opt;
2380         struct cYAML *err_rc = NULL, *show_rc = NULL;
2381         const char *const short_options = "c:n:g:p:v";
2382         static const struct option long_options[] = {
2383                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
2384                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
2385                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
2386                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
2387                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
2388                 { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
2389                 { .name = NULL }
2390         };
2391
2392         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
2393         if (rc)
2394                 return rc;
2395
2396         while ((opt = getopt_long(argc, argv, short_options,
2397                                    long_options, NULL)) != -1) {
2398                 switch (opt) {
2399                 case 'n':
2400                         network = optarg;
2401                         break;
2402                 case 'g':
2403                         gateway = optarg;
2404                         break;
2405                 case 'c':
2406                         rc = parse_long(optarg, &hop);
2407                         if (rc != 0) {
2408                                 /* ignore option */
2409                                 hop = -1;
2410                                 continue;
2411                         }
2412                         break;
2413                 case 'p':
2414                         rc = parse_long(optarg, &prio);
2415                         if (rc != 0) {
2416                                 /* ignore option */
2417                                 prio = -1;
2418                                 continue;
2419                         }
2420                         break;
2421                 case 'v':
2422                         detail = 1;
2423                         break;
2424                 case '?':
2425                         print_help(route_cmds, "route", "show");
2426                 default:
2427                         return 0;
2428                 }
2429         }
2430
2431         rc = yaml_lnet_route(network, gateway, hop, prio, -1,
2432                              detail, NLM_F_DUMP);
2433         if (rc <= 0) {
2434                 if (rc == -EOPNOTSUPP)
2435                         goto old_api;
2436                 return rc;
2437         }
2438 old_api:
2439         rc = lustre_lnet_show_route(network, gateway, hop, prio,
2440                                     detail ? 1 : 0, -1,
2441                                     &show_rc, &err_rc, false);
2442
2443         if (rc != LUSTRE_CFG_RC_NO_ERR)
2444                 cYAML_print_tree2file(stderr, err_rc);
2445         else if (show_rc)
2446                 cYAML_print_tree(show_rc);
2447
2448         cYAML_free_tree(err_rc);
2449         cYAML_free_tree(show_rc);
2450
2451         return rc;
2452 }
2453
2454 static int set_value_helper(int argc, char **argv,
2455                             int (*cb)(int, bool, char*, int, int, struct cYAML**))
2456 {
2457         char *nid = NULL;
2458         long int healthv = -1;
2459         bool all = false;
2460         long int state = -1;
2461         int rc, opt;
2462         struct cYAML *err_rc = NULL;
2463         const char *const short_options = "t:n:s:a";
2464         static const struct option long_options[] = {
2465                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2466                 { .name = "health", .has_arg = required_argument, .val = 't' },
2467                 { .name = "state", .has_arg = required_argument, .val = 's' },
2468                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2469                 { .name = NULL }
2470         };
2471
2472         while ((opt = getopt_long(argc, argv, short_options,
2473                                   long_options, NULL)) != -1) {
2474                 switch (opt) {
2475                 case 'n':
2476                         nid = optarg;
2477                         break;
2478                 case 't':
2479                         if (parse_long(optarg, &healthv) != 0)
2480                                 healthv = -1;
2481                         break;
2482                 case 's':
2483                         if (parse_long(optarg, &state) != 0)
2484                                 state = -1;
2485                         break;
2486                 case 'a':
2487                         all = true;
2488                         break;
2489                 default:
2490                         return 0;
2491                 }
2492         }
2493
2494         rc = cb(healthv, all, nid, state, -1, &err_rc);
2495         if (rc != LUSTRE_CFG_RC_NO_ERR)
2496                 cYAML_print_tree2file(stderr, err_rc);
2497
2498         cYAML_free_tree(err_rc);
2499
2500         return rc;
2501 }
2502
2503 static int jt_set_ni_value(int argc, char **argv)
2504 {
2505         char *nid = NULL;
2506         long int healthv = -1, cpp = -1;
2507         bool all = false;
2508         int rc, opt;
2509         struct cYAML *err_rc = NULL;
2510
2511         const char *const short_options = "a:m:n:t:";
2512         static const struct option long_options[] = {
2513         { .name = "all",            .has_arg = no_argument,       .val = 'a' },
2514         { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2515         { .name = "nid",            .has_arg = required_argument, .val = 'n' },
2516         { .name = "health",         .has_arg = required_argument, .val = 't' },
2517         { .name = NULL } };
2518
2519         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2520         if (rc)
2521                 return rc;
2522
2523         while ((opt = getopt_long(argc, argv, short_options,
2524                                    long_options, NULL)) != -1) {
2525                 switch (opt) {
2526                 case 'a':
2527                         all = true;
2528                         break;
2529                 case 'm':
2530                         rc = parse_long(optarg, &cpp);
2531                         if (rc != 0) {
2532                                 /* ignore option */
2533                                 cpp = -1;
2534                                 continue;
2535                         }
2536                         break;
2537                 case 'n':
2538                         nid = optarg;
2539                         break;
2540                 case 't':
2541                         if (parse_long(optarg, &healthv) != 0) {
2542                                 /* ignore option */
2543                                 healthv = -1;
2544                                 continue;
2545                         }
2546                         break;
2547                 default:
2548                         return 0;
2549                 }
2550         }
2551
2552         if (cpp > -1)
2553                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
2554                                                           -1, &err_rc);
2555         if (healthv > -1)
2556                 rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
2557                                                    -1, &err_rc);
2558
2559         if (rc != LUSTRE_CFG_RC_NO_ERR)
2560                 cYAML_print_tree2file(stderr, err_rc);
2561
2562         cYAML_free_tree(err_rc);
2563
2564         return rc;
2565 }
2566
2567 static int yaml_lnet_peer_display(yaml_parser_t *reply, bool list_only)
2568 {
2569         yaml_emitter_t debug;
2570         int rc;
2571
2572         rc = yaml_emitter_initialize(&debug);
2573         if (rc == 0)
2574                 goto out_err;
2575
2576         yaml_emitter_set_indent(&debug, 6);
2577         yaml_emitter_set_output_file(&debug, stdout);
2578
2579         if (list_only) {
2580                 bool done = false;
2581
2582                 while (!done) {
2583                         yaml_event_t event;
2584                         char *value;
2585
2586                         rc = yaml_parser_parse(reply, &event);
2587                         if (rc == 0)
2588                                 goto report_reply_error;
2589
2590                         if (event.type != YAML_SCALAR_EVENT)
2591                                 goto merge_event;
2592
2593                         value = (char *)event.data.scalar.value;
2594                         if (strcmp(value, "peer") == 0) {
2595                                 yaml_event_delete(&event);
2596
2597                                 yaml_scalar_event_initialize(&event, NULL,
2598                                                              (yaml_char_t *)YAML_STR_TAG,
2599                                                              (yaml_char_t *)"peer list",
2600                                                              strlen("peer list"),
2601                                                              1, 0,
2602                                                              YAML_PLAIN_SCALAR_STYLE);
2603                         } else if (strcmp(value, "primary nid") == 0) {
2604                                 yaml_event_delete(&event);
2605
2606                                 yaml_scalar_event_initialize(&event, NULL,
2607                                                              (yaml_char_t *)YAML_STR_TAG,
2608                                                              (yaml_char_t *)"nid",
2609                                                              strlen("nid"),
2610                                                              1, 0,
2611                                                              YAML_PLAIN_SCALAR_STYLE);
2612                                 rc = yaml_emitter_emit(&debug, &event);
2613                                 if (rc == 0)
2614                                         break;
2615
2616                                 /* Now print NID address */
2617                                 rc = yaml_parser_parse(reply, &event);
2618                                 if (rc == 0)
2619                                         goto report_reply_error;
2620
2621                                 rc = yaml_emitter_emit(&debug, &event);
2622                                 if (rc == 0)
2623                                         break;
2624
2625                                 /* skip reset */
2626                                 while (event.type != YAML_MAPPING_END_EVENT) {
2627                                         rc = yaml_parser_parse(reply, &event);
2628                                         if (rc == 0)
2629                                                 goto report_reply_error;
2630                                 }
2631
2632                                 /* we can have map end, seq end, map end or
2633                                  * just map end event. If we see seq end event
2634                                  * then skip to next mapping end event
2635                                  */
2636                                 rc = yaml_parser_parse(reply, &event);
2637                                 if (rc == 0)
2638                                         goto report_reply_error;
2639
2640                                 if (event.type == YAML_SEQUENCE_END_EVENT) {
2641                                         yaml_event_delete(&event);
2642
2643                                         rc = yaml_parser_parse(reply, &event);
2644                                         if (rc == 0)
2645                                                 goto report_reply_error;
2646                                 }
2647                         }
2648 merge_event:
2649                         rc = yaml_emitter_emit(&debug, &event);
2650                         if (rc == 0)
2651                                 break;
2652
2653                         done = (event.type == YAML_DOCUMENT_END_EVENT);
2654                 }
2655         } else {
2656                 yaml_document_t errmsg;
2657
2658                 rc = yaml_parser_load(reply, &errmsg);
2659                 if (rc == 1)
2660                         rc = yaml_emitter_dump(&debug, &errmsg);
2661                 yaml_document_delete(&errmsg);
2662         }
2663 out_err:
2664         if (rc == 0)
2665                 yaml_emitter_log_error(&debug, stderr);
2666 report_reply_error:
2667         yaml_emitter_delete(&debug);
2668
2669         return rc;
2670 }
2671
2672 static int yaml_lnet_peer(char *prim_nid, char *nidstr, bool disable_mr,
2673                           int health_value, int state, bool list_only,
2674                           int version, int flags)
2675 {
2676         struct nl_sock *sk = NULL;
2677         const char *msg = NULL;
2678         yaml_emitter_t output;
2679         yaml_parser_t reply;
2680         yaml_event_t event;
2681         int rc;
2682
2683         /* Create Netlink emitter to send request to kernel */
2684         sk = nl_socket_alloc();
2685         if (!sk)
2686                 return -EOPNOTSUPP;
2687
2688         /* Setup parser to receive Netlink packets */
2689         rc = yaml_parser_initialize(&reply);
2690         if (rc == 0) {
2691                 nl_socket_free(sk);
2692                 return -EOPNOTSUPP;
2693         }
2694
2695         rc = yaml_parser_set_input_netlink(&reply, sk, false);
2696         if (rc == 0) {
2697                 msg = yaml_parser_get_reader_error(&reply);
2698                 goto free_reply;
2699         }
2700
2701         /* Create Netlink emitter to send request to kernel */
2702         rc = yaml_emitter_initialize(&output);
2703         if (rc == 0) {
2704                 msg = "failed to initialize emitter";
2705                 goto free_reply;
2706         }
2707
2708         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
2709                                              version, LNET_CMD_PEERS, flags);
2710         if (rc == 0)
2711                 goto emitter_error;
2712
2713         yaml_emitter_open(&output);
2714         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
2715         rc = yaml_emitter_emit(&output, &event);
2716         if (rc == 0)
2717                 goto emitter_error;
2718
2719         yaml_mapping_start_event_initialize(&event, NULL,
2720                                             (yaml_char_t *)YAML_MAP_TAG,
2721                                             1, YAML_ANY_MAPPING_STYLE);
2722         rc = yaml_emitter_emit(&output, &event);
2723         if (rc == 0)
2724                 goto emitter_error;
2725
2726         yaml_scalar_event_initialize(&event, NULL,
2727                                      (yaml_char_t *)YAML_STR_TAG,
2728                                      (yaml_char_t *)"peer",
2729                                      strlen("peer"), 1, 0,
2730                                      YAML_PLAIN_SCALAR_STYLE);
2731         rc = yaml_emitter_emit(&output, &event);
2732         if (rc == 0)
2733                 goto emitter_error;
2734
2735         if (prim_nid) {
2736                 yaml_sequence_start_event_initialize(&event, NULL,
2737                                                      (yaml_char_t *)YAML_SEQ_TAG,
2738                                                      1,
2739                                                      YAML_BLOCK_SEQUENCE_STYLE);
2740                 rc = yaml_emitter_emit(&output, &event);
2741                 if (rc == 0)
2742                         goto emitter_error;
2743
2744                 yaml_mapping_start_event_initialize(&event, NULL,
2745                                                     (yaml_char_t *)YAML_MAP_TAG,
2746                                                     1,
2747                                                     YAML_BLOCK_MAPPING_STYLE);
2748                 rc = yaml_emitter_emit(&output, &event);
2749                 if (rc == 0)
2750                         goto emitter_error;
2751
2752                 yaml_scalar_event_initialize(&event, NULL,
2753                                              (yaml_char_t *)YAML_STR_TAG,
2754                                              (yaml_char_t *)"primary nid",
2755                                              strlen("primary nid"), 1, 0,
2756                                              YAML_PLAIN_SCALAR_STYLE);
2757                 rc = yaml_emitter_emit(&output, &event);
2758                 if (rc == 0)
2759                         goto emitter_error;
2760
2761                 yaml_scalar_event_initialize(&event, NULL,
2762                                              (yaml_char_t *)YAML_STR_TAG,
2763                                              (yaml_char_t *)prim_nid,
2764                                              strlen(prim_nid), 1, 0,
2765                                              YAML_PLAIN_SCALAR_STYLE);
2766                 rc = yaml_emitter_emit(&output, &event);
2767                 if (rc == 0)
2768                         goto emitter_error;
2769
2770                 if (disable_mr) {
2771                         yaml_scalar_event_initialize(&event, NULL,
2772                                                      (yaml_char_t *)YAML_STR_TAG,
2773                                                      (yaml_char_t *)"Multi-Rail",
2774                                                      strlen("Multi-Rail"), 1, 0,
2775                                                      YAML_PLAIN_SCALAR_STYLE);
2776                         rc = yaml_emitter_emit(&output, &event);
2777                         if (rc == 0)
2778                                 goto emitter_error;
2779
2780                         yaml_scalar_event_initialize(&event, NULL,
2781                                                      (yaml_char_t *)YAML_BOOL_TAG,
2782                                                      (yaml_char_t *)"False",
2783                                                      strlen("False"), 1, 0,
2784                                                      YAML_PLAIN_SCALAR_STYLE);
2785                         rc = yaml_emitter_emit(&output, &event);
2786                         if (rc == 0)
2787                                 goto emitter_error;
2788                 }
2789
2790                 if (state != -1) {
2791                         char peer_state[INT_STRING_LEN];
2792
2793                         yaml_scalar_event_initialize(&event, NULL,
2794                                                      (yaml_char_t *)YAML_STR_TAG,
2795                                                      (yaml_char_t *)"peer state",
2796                                                      strlen("peer state"), 1, 0,
2797                                                      YAML_PLAIN_SCALAR_STYLE);
2798                         rc = yaml_emitter_emit(&output, &event);
2799                         if (rc == 0)
2800                                 goto emitter_error;
2801
2802                         snprintf(peer_state, sizeof(peer_state), "%d", state);
2803                         yaml_scalar_event_initialize(&event, NULL,
2804                                                      (yaml_char_t *)YAML_INT_TAG,
2805                                                      (yaml_char_t *)peer_state,
2806                                                      strlen(peer_state), 1, 0,
2807                                                      YAML_PLAIN_SCALAR_STYLE);
2808                         rc = yaml_emitter_emit(&output, &event);
2809                         if (rc == 0)
2810                                 goto emitter_error;
2811                 }
2812
2813                 if (!nidstr && health_value == -1)
2814                         goto skip_peer_nis;
2815
2816                 yaml_scalar_event_initialize(&event, NULL,
2817                                              (yaml_char_t *)YAML_STR_TAG,
2818                                              (yaml_char_t *)"peer ni",
2819                                              strlen("peer ni"), 1, 0,
2820                                              YAML_PLAIN_SCALAR_STYLE);
2821                 rc = yaml_emitter_emit(&output, &event);
2822                 if (rc == 0)
2823                         goto emitter_error;
2824
2825                 yaml_sequence_start_event_initialize(&event, NULL,
2826                                                      (yaml_char_t *)YAML_SEQ_TAG,
2827                                                      1, YAML_BLOCK_SEQUENCE_STYLE);
2828                 rc = yaml_emitter_emit(&output, &event);
2829                 if (rc == 0)
2830                         goto emitter_error;
2831
2832                 if (nidstr) {
2833                         struct nid_node head, *entry;
2834                         int count = 0;
2835
2836                         /* If we have LNET_ANY_NID and its NLM_F_REPLACE we
2837                          * treat it as the all flag case for lnetctl peer set
2838                          */
2839                         if (strcmp(nidstr, "<?>") == 0) {
2840                                 yaml_mapping_start_event_initialize(&event, NULL,
2841                                                                     (yaml_char_t *)YAML_MAP_TAG,
2842                                                                     1, YAML_BLOCK_MAPPING_STYLE);
2843                                 rc = yaml_emitter_emit(&output, &event);
2844                                 if (rc == 0)
2845                                         goto emitter_error;
2846
2847                                 yaml_scalar_event_initialize(&event, NULL,
2848                                                              (yaml_char_t *)YAML_STR_TAG,
2849                                                              (yaml_char_t *)"nid",
2850                                                              strlen("nid"), 1, 0,
2851                                                              YAML_PLAIN_SCALAR_STYLE);
2852                                 rc = yaml_emitter_emit(&output, &event);
2853                                 if (rc == 0)
2854                                         goto emitter_error;
2855
2856                                 yaml_scalar_event_initialize(&event, NULL,
2857                                                              (yaml_char_t *)YAML_STR_TAG,
2858                                                              (yaml_char_t *)nidstr,
2859                                                              strlen(nidstr), 1, 0,
2860                                                      YAML_PLAIN_SCALAR_STYLE);
2861                                 rc = yaml_emitter_emit(&output, &event);
2862                                 if (rc == 0)
2863                                         goto emitter_error;
2864
2865                                 yaml_mapping_end_event_initialize(&event);
2866                                 rc = yaml_emitter_emit(&output, &event);
2867                                 if (rc == 0)
2868                                         goto emitter_error;
2869
2870                                 goto handle_health;
2871                         }
2872
2873                         NL_INIT_LIST_HEAD(&head.children);
2874                         nl_init_list_head(&head.list);
2875                         rc = lustre_lnet_parse_nid_range(&head, nidstr, &msg);
2876                         if (rc < 0) {
2877                                 fprintf(stdout, "can't parse nidrange: \"%s\"\n", nidstr);
2878                                 lustre_lnet_free_list(&head);
2879                                 yaml_emitter_delete(&output);
2880                                 errno = rc;
2881                                 rc = 0;
2882                                 goto free_reply;
2883                         }
2884
2885                         if (nl_list_empty(&head.children)) {
2886                                 lustre_lnet_free_list(&head);
2887                                 yaml_emitter_delete(&output);
2888                                 msg = "Unable to parse nidlist: did not expand to any nids";
2889                                 errno = -ENOENT;
2890                                 rc = 0;
2891                                 goto free_reply;
2892                         }
2893                         rc = 1; /* one means its working */
2894
2895                         nl_list_for_each_entry(entry, &head.children, list) {
2896                                 char *nid = entry->nidstr;
2897
2898                                 if (count++ > LNET_MAX_NIDS_PER_PEER) {
2899                                         lustre_lnet_free_list(&head);
2900                                         yaml_emitter_delete(&output);
2901                                         msg = "Unable to parse nidlist: specifies more NIDs than allowed";
2902                                         errno = -E2BIG;
2903                                         rc = 0;
2904                                         goto free_reply;
2905                                 }
2906
2907                                 yaml_mapping_start_event_initialize(&event, NULL,
2908                                                                     (yaml_char_t *)YAML_MAP_TAG,
2909                                                                     1, YAML_BLOCK_MAPPING_STYLE);
2910                                 rc = yaml_emitter_emit(&output, &event);
2911                                 if (rc == 0)
2912                                         goto emitter_error;
2913
2914                                 yaml_scalar_event_initialize(&event, NULL,
2915                                                              (yaml_char_t *)YAML_STR_TAG,
2916                                                              (yaml_char_t *)"nid",
2917                                                              strlen("nid"), 1, 0,
2918                                                              YAML_PLAIN_SCALAR_STYLE);
2919                                 rc = yaml_emitter_emit(&output, &event);
2920                                 if (rc == 0)
2921                                         goto emitter_error;
2922
2923                                 yaml_scalar_event_initialize(&event, NULL,
2924                                                              (yaml_char_t *)YAML_STR_TAG,
2925                                                              (yaml_char_t *)nid,
2926                                                              strlen(nid), 1, 0,
2927                                                      YAML_PLAIN_SCALAR_STYLE);
2928                                 rc = yaml_emitter_emit(&output, &event);
2929                                 if (rc == 0)
2930                                         goto emitter_error;
2931
2932                                 yaml_mapping_end_event_initialize(&event);
2933                                 rc = yaml_emitter_emit(&output, &event);
2934                                 if (rc == 0)
2935                                         goto emitter_error;
2936                         }
2937                         lustre_lnet_free_list(&head);
2938                 }
2939 handle_health:
2940                 if (health_value >= 0) {
2941                         char health[INT_STRING_LEN];
2942
2943                         /* Create the mapping for 'health stats'. The value field for
2944                          * the mapping is not provided so its treated as a empty string.
2945                          */
2946                         yaml_mapping_start_event_initialize(&event, NULL,
2947                                                             (yaml_char_t *)YAML_MAP_TAG,
2948                                                             1, YAML_BLOCK_MAPPING_STYLE);
2949                         rc = yaml_emitter_emit(&output, &event);
2950                         if (rc == 0)
2951                                 goto emitter_error;
2952
2953                         yaml_scalar_event_initialize(&event, NULL,
2954                                                      (yaml_char_t *)YAML_STR_TAG,
2955                                                      (yaml_char_t *)"health stats",
2956                                                      strlen("health stats"), 1, 0,
2957                                                      YAML_PLAIN_SCALAR_STYLE);
2958                         rc = yaml_emitter_emit(&output, &event);
2959                         if (rc == 0)
2960                                 goto emitter_error;
2961
2962                         /* Setup all mappings for data related to the 'health stats' */
2963                         yaml_mapping_start_event_initialize(&event, NULL,
2964                                                             (yaml_char_t *)YAML_MAP_TAG,
2965                                                             1, YAML_BLOCK_MAPPING_STYLE);
2966                         rc = yaml_emitter_emit(&output, &event);
2967                         if (rc == 0)
2968                                 goto emitter_error;
2969
2970                         yaml_scalar_event_initialize(&event, NULL,
2971                                                      (yaml_char_t *)YAML_STR_TAG,
2972                                                      (yaml_char_t *)"health value",
2973                                                      strlen("health value"), 1, 0,
2974                                                      YAML_PLAIN_SCALAR_STYLE);
2975                         rc = yaml_emitter_emit(&output, &event);
2976                         if (rc == 0)
2977                                 goto emitter_error;
2978
2979                         snprintf(health, sizeof(health), "%d", health_value);
2980                         yaml_scalar_event_initialize(&event, NULL,
2981                                                      (yaml_char_t *)YAML_INT_TAG,
2982                                                      (yaml_char_t *)health,
2983                                                      strlen(health), 1, 0,
2984                                                      YAML_PLAIN_SCALAR_STYLE);
2985                         rc = yaml_emitter_emit(&output, &event);
2986                         if (rc == 0)
2987                                 goto emitter_error;
2988
2989                         yaml_mapping_end_event_initialize(&event);
2990                         rc = yaml_emitter_emit(&output, &event);
2991                         if (rc == 0)
2992                                 goto emitter_error;
2993
2994                         yaml_mapping_end_event_initialize(&event);
2995                         rc = yaml_emitter_emit(&output, &event);
2996                         if (rc == 0)
2997                                 goto emitter_error;
2998                 }
2999
3000                 yaml_sequence_end_event_initialize(&event);
3001                 rc = yaml_emitter_emit(&output, &event);
3002                 if (rc == 0)
3003                         goto emitter_error;
3004 skip_peer_nis:
3005                 yaml_mapping_end_event_initialize(&event);
3006                 rc = yaml_emitter_emit(&output, &event);
3007                 if (rc == 0)
3008                         goto emitter_error;
3009
3010                 yaml_sequence_end_event_initialize(&event);
3011                 rc = yaml_emitter_emit(&output, &event);
3012                 if (rc == 0)
3013                         goto emitter_error;
3014         } else {
3015                 yaml_scalar_event_initialize(&event, NULL,
3016                                              (yaml_char_t *)YAML_STR_TAG,
3017                                              (yaml_char_t *)"",
3018                                              strlen(""), 1, 0,
3019                                              YAML_PLAIN_SCALAR_STYLE);
3020                 rc = yaml_emitter_emit(&output, &event);
3021                 if (rc == 0)
3022                         goto emitter_error;
3023         }
3024
3025         yaml_mapping_end_event_initialize(&event);
3026         rc = yaml_emitter_emit(&output, &event);
3027         if (rc == 0)
3028                 goto emitter_error;
3029
3030         yaml_document_end_event_initialize(&event, 0);
3031         rc = yaml_emitter_emit(&output, &event);
3032         if (rc == 0)
3033                 goto emitter_error;
3034
3035         rc = yaml_emitter_close(&output);
3036 emitter_error:
3037         if (rc == 0) {
3038                 yaml_emitter_log_error(&output, stderr);
3039                 rc = -EINVAL;
3040         } else {
3041                 rc = yaml_lnet_peer_display(&reply, list_only);
3042                 if (rc == 0) {
3043                         msg = yaml_parser_get_reader_error(&reply);
3044                         /* If we didn't find any peers just be silent */
3045                         if (msg && strcmp(msg, "No peers found") == 0)
3046                                 rc = 1;
3047                 }
3048
3049         }
3050         yaml_emitter_delete(&output);
3051 free_reply:
3052         if (rc == 0) {
3053                 yaml_lnet_print_error(flags, "peer", msg);
3054                 rc = -EINVAL;
3055         }
3056         yaml_parser_delete(&reply);
3057         nl_socket_free(sk);
3058
3059         return rc == 1 ? 0 : rc;
3060 }
3061
3062 int yaml_lnet_config_peer_ni_healthv(int healthv, bool all, char *lpni_nid,
3063                                      int state, int seq_no, struct cYAML **err_rc)
3064 {
3065         int rc;
3066
3067         rc = yaml_lnet_peer(lpni_nid ? lpni_nid : "<?>", all ? "<?>" : NULL,
3068                             false, healthv, state, false, LNET_GENL_VERSION,
3069                             NLM_F_REPLACE);
3070         if (rc <= 0) {
3071                 if (rc == -EOPNOTSUPP)
3072                         goto old_api;
3073                 return rc;
3074         }
3075 old_api:
3076         if (state == -1)
3077                 rc = lustre_lnet_config_peer_ni_healthv(healthv, all, lpni_nid,
3078                                                         seq_no, err_rc);
3079         else
3080                 rc = lustre_lnet_set_peer_state(state, lpni_nid, -1, err_rc);
3081         if (rc != LUSTRE_CFG_RC_NO_ERR)
3082                 cYAML_print_tree2file(stderr, *err_rc);
3083
3084         cYAML_free_tree(*err_rc);
3085
3086         return rc;
3087 }
3088
3089 static int jt_set_peer_ni_value(int argc, char **argv)
3090 {
3091         int rc = check_cmd(peer_cmds, "peer", "set", 0, argc, argv);
3092
3093         if (rc < 0)
3094                 return rc;
3095
3096         return set_value_helper(argc, argv, yaml_lnet_config_peer_ni_healthv);
3097 }
3098
3099 static int jt_show_recovery(int argc, char **argv)
3100 {
3101         int rc, opt;
3102         struct cYAML *err_rc = NULL, *show_rc = NULL;
3103         const char *const short_options = "lp";
3104         static const struct option long_options[] = {
3105                 { .name = "local", .has_arg = no_argument, .val = 'l' },
3106                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
3107                 { .name = NULL } };
3108
3109         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
3110         if (rc)
3111                 return rc;
3112
3113         while ((opt = getopt_long(argc, argv, short_options,
3114                                    long_options, NULL)) != -1) {
3115                 switch (opt) {
3116                 case 'l':
3117                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
3118                         break;
3119                 case 'p':
3120                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
3121                         break;
3122                 default:
3123                         return 0;
3124                 }
3125         }
3126
3127         if (rc != LUSTRE_CFG_RC_NO_ERR)
3128                 cYAML_print_tree2file(stderr, err_rc);
3129         else if (show_rc)
3130                 cYAML_print_tree(show_rc);
3131
3132         cYAML_free_tree(err_rc);
3133         cYAML_free_tree(show_rc);
3134
3135         return rc;
3136 }
3137
3138 static int jt_show_peer_debug_info(int argc, char **argv)
3139 {
3140         int rc, opt;
3141         struct cYAML *err_rc = NULL;
3142         char *peer_nid = optarg;
3143         const char *const short_opts = "k";
3144         const struct option long_opts[] = {
3145         { .name = "nid", .has_arg = required_argument, .val = 'k' },
3146         { .name = NULL } };
3147
3148         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
3149
3150         if (rc)
3151                 return rc;
3152
3153         while ((opt = getopt_long(argc, argv, short_opts,
3154                                    long_opts, NULL)) != -1) {
3155                 switch (opt) {
3156                 case 'k':
3157                         peer_nid = optarg;
3158                         break;
3159                 default:
3160                         return 0;
3161                 }
3162         }
3163
3164         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
3165
3166         if (rc != LUSTRE_CFG_RC_NO_ERR)
3167                 cYAML_print_tree2file(stderr, err_rc);
3168
3169         cYAML_free_tree(err_rc);
3170
3171         return rc;
3172 }
3173
3174 static int jt_show_net(int argc, char **argv)
3175 {
3176         char *network = NULL;
3177         int rc, opt;
3178         struct cYAML *err_rc = NULL, *show_rc = NULL;
3179         long int detail = 0;
3180         const char *const short_options = "n:v";
3181         static const struct option long_options[] = {
3182                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
3183                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
3184                 { .name = NULL } };
3185
3186         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
3187         if (rc)
3188                 return rc;
3189
3190         while ((opt = getopt_long(argc, argv, short_options,
3191                                    long_options, NULL)) != -1) {
3192                 switch (opt) {
3193                 case 'n':
3194                         network = optarg;
3195                         break;
3196                 case 'v':
3197                         if ((!optarg) && (argv[optind] != NULL) &&
3198                             (argv[optind][0] != '-')) {
3199                                 if (parse_long(argv[optind++], &detail) != 0)
3200                                         detail = 1;
3201                         } else {
3202                                 detail = 1;
3203                         }
3204                         break;
3205                 case '?':
3206                         print_help(net_cmds, "net", "show");
3207                 default:
3208                         return 0;
3209                 }
3210         }
3211
3212         rc = yaml_lnet_config_ni(network, NULL, NULL, NULL, NULL,
3213                                  detail, NLM_F_DUMP);
3214         if (rc <= 0) {
3215                 if (rc != -EOPNOTSUPP)
3216                         return rc;
3217         }
3218
3219         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
3220                                   false);
3221
3222         if (rc != LUSTRE_CFG_RC_NO_ERR)
3223                 cYAML_print_tree2file(stderr, err_rc);
3224         else if (show_rc)
3225                 cYAML_print_tree(show_rc);
3226
3227         cYAML_free_tree(err_rc);
3228         cYAML_free_tree(show_rc);
3229
3230         return rc;
3231 }
3232
3233 static int jt_show_routing(int argc, char **argv)
3234 {
3235         struct cYAML *err_rc = NULL, *show_rc = NULL;
3236         int rc;
3237
3238         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
3239         if (rc)
3240                 return rc;
3241
3242         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
3243
3244         if (rc != LUSTRE_CFG_RC_NO_ERR)
3245                 cYAML_print_tree2file(stderr, err_rc);
3246         else if (show_rc)
3247                 cYAML_print_tree(show_rc);
3248
3249         cYAML_free_tree(err_rc);
3250         cYAML_free_tree(show_rc);
3251
3252         return rc;
3253 }
3254
3255 static int jt_show_stats(int argc, char **argv)
3256 {
3257         int rc;
3258         struct cYAML *show_rc = NULL, *err_rc = NULL;
3259
3260         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
3261         if (rc)
3262                 return rc;
3263
3264         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
3265
3266         if (rc != LUSTRE_CFG_RC_NO_ERR)
3267                 cYAML_print_tree2file(stderr, err_rc);
3268         else if (show_rc)
3269                 cYAML_print_tree(show_rc);
3270
3271         cYAML_free_tree(err_rc);
3272         cYAML_free_tree(show_rc);
3273
3274         return rc;
3275 }
3276
3277 static int jt_show_udsp(int argc, char **argv)
3278 {
3279         long int idx = -1;
3280         int rc, opt;
3281         struct cYAML *err_rc = NULL, *show_rc = NULL;
3282
3283         const char *const short_options = "i:";
3284         static const struct option long_options[] = {
3285                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
3286                 { .name = NULL }
3287         };
3288
3289         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
3290         if (rc)
3291                 return rc;
3292
3293         while ((opt = getopt_long(argc, argv, short_options,
3294                                    long_options, NULL)) != -1) {
3295                 switch (opt) {
3296                 case 'i':
3297                         rc = parse_long(optarg, &idx);
3298                         if (rc != 0 || idx < -1) {
3299                                 printf("Invalid index \"%s\"\n", optarg);
3300                                 return -EINVAL;
3301                         }
3302                         break;
3303                 case '?':
3304                         print_help(net_cmds, "net", "show");
3305                 default:
3306                         return 0;
3307                 }
3308         }
3309
3310         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
3311
3312         if (rc != LUSTRE_CFG_RC_NO_ERR)
3313                 cYAML_print_tree2file(stderr, err_rc);
3314         else if (show_rc)
3315                 cYAML_print_tree(show_rc);
3316
3317         cYAML_free_tree(err_rc);
3318         cYAML_free_tree(show_rc);
3319
3320         return rc;
3321 }
3322
3323 static int jt_show_global(int argc, char **argv)
3324 {
3325         int rc;
3326         struct cYAML *show_rc = NULL, *err_rc = NULL;
3327
3328         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
3329         if (rc)
3330                 return rc;
3331
3332         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3333         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3334                 cYAML_print_tree2file(stderr, err_rc);
3335                 goto out;
3336         }
3337
3338         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3339         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3340                 cYAML_print_tree2file(stderr, err_rc);
3341                 goto out;
3342         }
3343
3344         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3345         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3346                 cYAML_print_tree2file(stderr, err_rc);
3347                 goto out;
3348         }
3349
3350         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3351         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3352                 cYAML_print_tree2file(stderr, err_rc);
3353                 goto out;
3354         }
3355
3356         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3357         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3358                 cYAML_print_tree2file(stderr, err_rc);
3359                 goto out;
3360         }
3361
3362         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3363         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3364                 cYAML_print_tree2file(stderr, err_rc);
3365                 goto out;
3366         }
3367
3368         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3369         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3370                 cYAML_print_tree2file(stderr, err_rc);
3371                 goto out;
3372         }
3373
3374         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3375         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3376                 cYAML_print_tree2file(stderr, err_rc);
3377                 goto out;
3378         }
3379
3380         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3381         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3382                 cYAML_print_tree2file(stderr, err_rc);
3383                 goto out;
3384         }
3385
3386         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3387         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3388                 cYAML_print_tree2file(stderr, err_rc);
3389                 goto out;
3390         }
3391
3392         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3393         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3394                 cYAML_print_tree2file(stderr, err_rc);
3395                 goto out;
3396         }
3397
3398         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3399         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3400                 cYAML_print_tree2file(stderr, err_rc);
3401                 goto out;
3402         }
3403
3404         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3405         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3406                 cYAML_print_tree2file(stderr, err_rc);
3407                 goto out;
3408         }
3409
3410         if (show_rc)
3411                 cYAML_print_tree(show_rc);
3412
3413 out:
3414         cYAML_free_tree(err_rc);
3415         cYAML_free_tree(show_rc);
3416
3417         return rc;
3418 }
3419
3420 static int jt_lnet(int argc, char **argv)
3421 {
3422         int rc;
3423
3424         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
3425         if (rc)
3426                 return rc;
3427
3428         return cfs_parser(argc, argv, lnet_cmds);
3429 }
3430
3431 static int jt_route(int argc, char **argv)
3432 {
3433         int rc;
3434
3435         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
3436         if (rc)
3437                 return rc;
3438
3439         return cfs_parser(argc, argv, route_cmds);
3440 }
3441
3442 static int jt_net(int argc, char **argv)
3443 {
3444         int rc;
3445
3446         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
3447         if (rc)
3448                 return rc;
3449
3450         return cfs_parser(argc, argv, net_cmds);
3451 }
3452
3453 static int jt_routing(int argc, char **argv)
3454 {
3455         int rc;
3456
3457         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
3458         if (rc)
3459                 return rc;
3460
3461         return cfs_parser(argc, argv, routing_cmds);
3462 }
3463
3464 static int jt_stats(int argc, char **argv)
3465 {
3466         int rc;
3467
3468         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
3469         if (rc)
3470                 return rc;
3471
3472         return cfs_parser(argc, argv, stats_cmds);
3473 }
3474
3475 static int jt_debug(int argc, char **argv)
3476 {
3477         int rc;
3478
3479         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
3480         if (rc)
3481                 return rc;
3482
3483         return cfs_parser(argc, argv, debug_cmds);
3484 }
3485
3486 static int jt_global(int argc, char **argv)
3487 {
3488         int rc;
3489
3490         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
3491         if (rc)
3492                 return rc;
3493
3494         return cfs_parser(argc, argv, global_cmds);
3495 }
3496
3497 static int jt_peers(int argc, char **argv)
3498 {
3499         int rc;
3500
3501         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
3502         if (rc)
3503                 return rc;
3504
3505         return cfs_parser(argc, argv, peer_cmds);
3506 }
3507
3508 static int jt_set(int argc, char **argv)
3509 {
3510         int rc;
3511
3512         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
3513         if (rc)
3514                 return rc;
3515
3516         return cfs_parser(argc, argv, set_cmds);
3517 }
3518
3519 static int jt_udsp(int argc, char **argv)
3520 {
3521         int rc;
3522
3523         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
3524         if (rc)
3525                 return rc;
3526
3527         return cfs_parser(argc, argv, udsp_cmds);
3528 }
3529
3530 static int jt_import(int argc, char **argv)
3531 {
3532         char *file = NULL;
3533         struct cYAML *err_rc = NULL;
3534         struct cYAML *show_rc = NULL;
3535         int rc = 0, return_rc = 0, opt, opt_found = 0;
3536         char cmd = 'a';
3537
3538         const char *const short_options = "adseh";
3539         static const struct option long_options[] = {
3540                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
3541                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
3542                 { .name = "show", .has_arg = no_argument, .val = 's' },
3543                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
3544                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3545                 { .name = NULL } };
3546
3547         while ((opt = getopt_long(argc, argv, short_options,
3548                                    long_options, NULL)) != -1) {
3549                 opt_found = 1;
3550                 switch (opt) {
3551                 case 'a':
3552                         cmd = opt;
3553                         break;
3554                 case 'd':
3555                 case 's':
3556                         cmd = opt;
3557                         break;
3558                 case 'e':
3559                         cmd = opt;
3560                         break;
3561                 case 'h':
3562                         printf("import FILE\n"
3563                                "import < FILE : import a file\n"
3564                                "\t--add: add configuration\n"
3565                                "\t--del: delete configuration\n"
3566                                "\t--show: show configuration\n"
3567                                "\t--exec: execute command\n"
3568                                "\t--help: display this help\n"
3569                                "If no command option is given then --add"
3570                                " is assumed by default\n");
3571                         return 0;
3572                 default:
3573                         return 0;
3574                 }
3575         }
3576
3577         /* grab the file name if one exists */
3578         if (opt_found && argc == 3)
3579                 file = argv[2];
3580         else if (!opt_found && argc == 2)
3581                 file = argv[1];
3582
3583         switch (cmd) {
3584         case 'a':
3585                 rc = lustre_yaml_config(file, &err_rc);
3586                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3587                 cYAML_print_tree(show_rc);
3588                 cYAML_free_tree(show_rc);
3589                 break;
3590         case 'd':
3591                 rc = lustre_yaml_del(file, &err_rc);
3592                 break;
3593         case 's':
3594                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
3595                 cYAML_print_tree(show_rc);
3596                 cYAML_free_tree(show_rc);
3597                 break;
3598         case 'e':
3599                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3600                 cYAML_print_tree(show_rc);
3601                 cYAML_free_tree(show_rc);
3602                 break;
3603         }
3604
3605         if (rc || return_rc) {
3606                 cYAML_print_tree2file(stderr, err_rc);
3607                 cYAML_free_tree(err_rc);
3608         }
3609
3610         return rc;
3611 }
3612
3613 static int jt_export(int argc, char **argv)
3614 {
3615         struct cYAML *show_rc = NULL;
3616         struct cYAML *err_rc = NULL;
3617         int rc;
3618         FILE *f = NULL;
3619         int opt;
3620         bool backup = false;
3621         char *file = NULL;
3622
3623         const char *const short_options = "bh";
3624         static const struct option long_options[] = {
3625                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
3626                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3627                 { .name = NULL } };
3628
3629         while ((opt = getopt_long(argc, argv, short_options,
3630                                    long_options, NULL)) != -1) {
3631                 switch (opt) {
3632                 case 'b':
3633                         backup = true;
3634                         break;
3635                 case 'h':
3636                 default:
3637                         printf("export > FILE.yaml : export configuration\n"
3638                                "\t--backup: export only what's necessary for reconfig\n"
3639                                "\t--help: display this help\n");
3640                         return 0;
3641                 }
3642         }
3643
3644         if (backup && argc >= 3)
3645                 file = argv[2];
3646         else if (!backup && argc >= 2)
3647                 file = argv[1];
3648         else
3649                 f = stdout;
3650
3651         if (file) {
3652                 f = fopen(file, "w");
3653                 if (f == NULL)
3654                         return -1;
3655         }
3656
3657         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
3658         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3659                 cYAML_print_tree2file(stderr, err_rc);
3660                 cYAML_free_tree(err_rc);
3661                 err_rc = NULL;
3662         }
3663
3664         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
3665                                     &err_rc, backup);
3666         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3667                 cYAML_print_tree2file(stderr, err_rc);
3668                 cYAML_free_tree(err_rc);
3669                 err_rc = NULL;
3670         }
3671
3672         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
3673         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3674                 cYAML_print_tree2file(stderr, err_rc);
3675                 cYAML_free_tree(err_rc);
3676                 err_rc = NULL;
3677         }
3678
3679         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
3680         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3681                 cYAML_print_tree2file(stderr, err_rc);
3682                 cYAML_free_tree(err_rc);
3683                 err_rc = NULL;
3684         }
3685
3686         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3687         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3688                 cYAML_print_tree2file(stderr, err_rc);
3689                 cYAML_free_tree(err_rc);
3690                 err_rc = NULL;
3691         }
3692
3693         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3694         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3695                 cYAML_print_tree2file(stderr, err_rc);
3696                 cYAML_free_tree(err_rc);
3697                 err_rc = NULL;
3698         }
3699
3700         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3701         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3702                 cYAML_print_tree2file(stderr, err_rc);
3703                 cYAML_free_tree(err_rc);
3704                 err_rc = NULL;
3705         }
3706
3707         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3708         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3709                 cYAML_print_tree2file(stderr, err_rc);
3710                 cYAML_free_tree(err_rc);
3711                 err_rc = NULL;
3712         }
3713
3714         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3715         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3716                 cYAML_print_tree2file(stderr, err_rc);
3717                 err_rc = NULL;
3718         }
3719
3720         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3721         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3722                 cYAML_print_tree2file(stderr, err_rc);
3723                 err_rc = NULL;
3724         }
3725
3726         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3727         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3728                 cYAML_print_tree2file(stderr, err_rc);
3729                 err_rc = NULL;
3730         }
3731
3732         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3733         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3734                 cYAML_print_tree2file(stderr, err_rc);
3735                 err_rc = NULL;
3736         }
3737
3738         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3739         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3740                 cYAML_print_tree2file(stderr, err_rc);
3741                 err_rc = NULL;
3742         }
3743
3744         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3745         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3746                 cYAML_print_tree2file(stderr, err_rc);
3747                 err_rc = NULL;
3748         }
3749
3750         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3751         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3752                 cYAML_print_tree2file(stderr, err_rc);
3753                 cYAML_free_tree(err_rc);
3754                 err_rc = NULL;
3755         }
3756
3757         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3758         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3759                 cYAML_print_tree2file(stderr, err_rc);
3760                 cYAML_free_tree(err_rc);
3761                 err_rc = NULL;
3762         }
3763
3764         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3765         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3766                 cYAML_print_tree2file(stderr, err_rc);
3767                 cYAML_free_tree(err_rc);
3768                 err_rc = NULL;
3769         }
3770
3771         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
3772         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3773                 cYAML_print_tree2file(stderr, err_rc);
3774                 cYAML_free_tree(err_rc);
3775                 err_rc = NULL;
3776         }
3777
3778         if (show_rc != NULL) {
3779                 cYAML_print_tree2file(f, show_rc);
3780                 cYAML_free_tree(show_rc);
3781         }
3782
3783         if (argc >= 2)
3784                 fclose(f);
3785
3786         return 0;
3787 }
3788
3789 static int jt_peer_nid_common(int argc, char **argv, int cmd)
3790 {
3791         int flags = cmd == LNETCTL_ADD_CMD ? NLM_F_CREATE : 0;
3792         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
3793         bool is_mr = true;
3794         char *prim_nid = NULL, *nidstr = NULL;
3795         char err_str[LNET_MAX_STR_LEN] = "Error";
3796         struct cYAML *err_rc = NULL;
3797         int force_lock = 0;
3798         const char *const short_opts = "k:m:n:f:l";
3799         const struct option long_opts[] = {
3800         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
3801         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
3802         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3803         { .name = "force",      .has_arg = no_argument,         .val = 'f' },
3804         { .name = "lock_prim",  .has_arg = no_argument,         .val = 'l' },
3805         { .name = NULL } };
3806
3807         rc = check_cmd(peer_cmds, "peer",
3808                        cmd == LNETCTL_ADD_CMD ? "add" : "del", 2, argc, argv);
3809         if (rc)
3810                 return rc;
3811
3812         while ((opt = getopt_long(argc, argv, short_opts,
3813                                   long_opts, NULL)) != -1) {
3814                 switch (opt) {
3815                 case 'k':
3816                         prim_nid = optarg;
3817                         break;
3818                 case 'n':
3819                         nidstr = optarg;
3820                         break;
3821                 case 'm':
3822                         if (cmd == LNETCTL_DEL_CMD) {
3823                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3824                                 snprintf(err_str, LNET_MAX_STR_LEN,
3825                                          "Unrecognized option '-%c'", opt);
3826                                 goto build_error;
3827                         }
3828                         is_mr = false;
3829                         break;
3830                 case 'f':
3831                         if (cmd == LNETCTL_ADD_CMD) {
3832                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3833                                 snprintf(err_str, LNET_MAX_STR_LEN,
3834                                          "Unrecognized option '-%c'", opt);
3835                         }
3836                         force_lock = 1;
3837                         flags |= NLM_F_EXCL;
3838                         break;
3839                 case 'l':
3840                         if (cmd == LNETCTL_DEL_CMD) {
3841                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3842                                 snprintf(err_str, LNET_MAX_STR_LEN,
3843                                          "Unrecognized option '-%c'", opt);
3844                         }
3845                         force_lock = 1;
3846                         flags |= NLM_F_EXCL;
3847                         break;
3848                 case '?':
3849                         print_help(peer_cmds, "peer",
3850                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
3851                 default:
3852                         return 0;
3853                 }
3854         }
3855
3856         rc = yaml_lnet_peer(prim_nid, nidstr, !is_mr, -1, -1, false,
3857                             LNET_GENL_VERSION, flags);
3858         if (rc <= 0) {
3859                 if (rc == -EOPNOTSUPP)
3860                         goto old_api;
3861                 return rc;
3862         }
3863 old_api:
3864         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
3865                                      force_lock, -1, &err_rc);
3866         if (rc != LUSTRE_CFG_RC_NO_ERR)
3867                 goto out;
3868
3869 build_error:
3870         cYAML_build_error(rc, -1, "peer",
3871                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
3872                           err_str, &err_rc);
3873
3874 out:
3875         if (rc != LUSTRE_CFG_RC_NO_ERR)
3876                 cYAML_print_tree2file(stderr, err_rc);
3877
3878         cYAML_free_tree(err_rc);
3879
3880         return rc;
3881 }
3882
3883 static int jt_add_peer_nid(int argc, char **argv)
3884 {
3885         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
3886 }
3887
3888 static int jt_del_peer_nid(int argc, char **argv)
3889 {
3890         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
3891 }
3892
3893 static int jt_show_peer(int argc, char **argv)
3894 {
3895         char *nid = NULL;
3896         int rc, opt;
3897         struct cYAML *err_rc = NULL, *show_rc = NULL;
3898         long int detail = 0;
3899         const char *const short_opts = "hn:v::";
3900         const struct option long_opts[] = {
3901                 { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3902                 { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3903                 { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
3904                 { .name = NULL }
3905         };
3906
3907         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
3908         if (rc)
3909                 return rc;
3910
3911         while ((opt = getopt_long(argc, argv, short_opts,
3912                                   long_opts, NULL)) != -1) {
3913                 switch (opt) {
3914                 case 'n':
3915                         nid = optarg;
3916                         break;
3917                 case 'v':
3918                         if ((!optarg) && (argv[optind] != NULL) &&
3919                             (argv[optind][0] != '-')) {
3920                                 if (parse_long(argv[optind++], &detail) != 0)
3921                                         detail = 1;
3922                         } else {
3923                                 detail = 1;
3924                         }
3925                         break;
3926                 case '?':
3927                         print_help(peer_cmds, "peer", "show");
3928                 default:
3929                         return 0;
3930                 }
3931         }
3932
3933         rc = yaml_lnet_peer(nid, NULL, false, -1, -1, false, detail,
3934                             NLM_F_DUMP);
3935         if (rc <= 0) {
3936                 if (rc == -EOPNOTSUPP)
3937                         goto old_api;
3938                 return rc;
3939         }
3940 old_api:
3941         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
3942                                    false);
3943
3944         if (rc != LUSTRE_CFG_RC_NO_ERR)
3945                 cYAML_print_tree2file(stderr, err_rc);
3946         else if (show_rc)
3947                 cYAML_print_tree(show_rc);
3948
3949         cYAML_free_tree(err_rc);
3950         cYAML_free_tree(show_rc);
3951
3952         return rc;
3953 }
3954
3955 static int jt_list_peer(int argc, char **argv)
3956 {
3957         int rc;
3958         struct cYAML *err_rc = NULL, *list_rc = NULL;
3959
3960         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
3961         if (rc)
3962                 return rc;
3963
3964         rc = yaml_lnet_peer(NULL, NULL, false, -1, -1, true, 0, NLM_F_DUMP);
3965         if (rc <= 0) {
3966                 if (rc == -EOPNOTSUPP)
3967                         goto old_api;
3968                 return rc;
3969         }
3970 old_api:
3971         if (rc != LUSTRE_CFG_RC_NO_ERR)
3972                 cYAML_print_tree2file(stderr, err_rc);
3973         else if (list_rc)
3974                 cYAML_print_tree(list_rc);
3975
3976         cYAML_free_tree(err_rc);
3977         cYAML_free_tree(list_rc);
3978
3979         return rc;
3980 }
3981
3982 static int jt_ping(int argc, char **argv)
3983 {
3984         struct cYAML *err_rc = NULL;
3985         struct cYAML *show_rc = NULL;
3986         int timeout = 1000;
3987         int rc = 0, opt;
3988         char *src_nidstr = NULL;
3989
3990         const char *const short_options = "hs:t:";
3991         const struct option long_options[] = {
3992         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3993         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
3994         { .name = "source",     .has_arg = required_argument,   .val = 's' },
3995         { .name = NULL } };
3996
3997         while ((opt = getopt_long(argc, argv, short_options,
3998                                   long_options, NULL)) != -1) {
3999                 switch (opt) {
4000                 case 's':
4001                         src_nidstr = optarg;
4002                         break;
4003                 case 't':
4004                         timeout = 1000 * atol(optarg);
4005                         break;
4006                 case 'h':
4007                         printf("ping nid[,nid,...]\n"
4008                                "\t --source: source nid\n"
4009                                "\t --timeout: ping timeout\n"
4010                                "\t --help: display this help\n");
4011                         return 0;
4012                 default:
4013                         return 0;
4014                 }
4015         }
4016
4017         for (; optind < argc; optind++)
4018                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
4019                                           &show_rc, &err_rc);
4020
4021         if (show_rc)
4022                 cYAML_print_tree(show_rc);
4023
4024         if (err_rc)
4025                 cYAML_print_tree2file(stderr, err_rc);
4026
4027         cYAML_free_tree(err_rc);
4028         cYAML_free_tree(show_rc);
4029
4030         return rc;
4031 }
4032
4033 static int jt_discover(int argc, char **argv)
4034 {
4035         struct cYAML *err_rc = NULL;
4036         struct cYAML *show_rc = NULL;
4037         int force = 0;
4038         int rc = 0, opt;
4039
4040         const char *const short_options = "fh";
4041         const struct option long_options[] = {
4042                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
4043                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
4044                 { .name = NULL } };
4045
4046         while ((opt = getopt_long(argc, argv, short_options,
4047                                   long_options, NULL)) != -1) {
4048                 switch (opt) {
4049                 case 'f':
4050                         force = 1;
4051                         break;
4052                 case 'h':
4053                         printf("discover nid[,nid,...]\n"
4054                                "\t --force: force discovery\n"
4055                                "\t --help: display this help\n");
4056                         return 0;
4057                 default:
4058                         return 0;
4059                 }
4060         }
4061
4062         if (optind == argc) {
4063                 printf("Missing nid argument\n");
4064                 return -1;
4065         }
4066
4067         for (; optind < argc; optind++)
4068                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
4069                                               &err_rc);
4070
4071         if (show_rc)
4072                 cYAML_print_tree(show_rc);
4073
4074         if (err_rc)
4075                 cYAML_print_tree2file(stderr, err_rc);
4076
4077         cYAML_free_tree(err_rc);
4078         cYAML_free_tree(show_rc);
4079
4080         return rc;
4081 }
4082
4083 static int jt_add_udsp(int argc, char **argv)
4084 {
4085         char *src = NULL, *dst = NULL, *rte = NULL;
4086         struct cYAML *err_rc = NULL;
4087         union lnet_udsp_action udsp_action;
4088         long int idx = -1, priority = -1;
4089         int opt, rc = 0;
4090         char *action_type = "pref";
4091
4092         const char *const short_options = "s:d:r:p:i:";
4093         static const struct option long_options[] = {
4094         { .name = "src",         .has_arg = required_argument, .val = 's' },
4095         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
4096         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
4097         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
4098         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
4099         { .name = NULL } };
4100
4101         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
4102         if (rc)
4103                 return rc;
4104
4105         while ((opt = getopt_long(argc, argv, short_options,
4106                                   long_options, NULL)) != -1) {
4107                 switch (opt) {
4108                 case 's':
4109                         src = optarg;
4110                         break;
4111                 case 'd':
4112                         dst = optarg;
4113                         break;
4114                 case 'r':
4115                         rte = optarg;
4116                         break;
4117                 case 'p':
4118                         rc = parse_long(optarg, &priority);
4119                         if (rc != 0 || priority < 0) {
4120                                 printf("Invalid priority \"%s\"\n", optarg);
4121                                 return -EINVAL;
4122                         }
4123                         action_type = "priority";
4124                         udsp_action.udsp_priority = priority;
4125                         break;
4126                 case 'i':
4127                         rc = parse_long(optarg, &idx);
4128                         if (rc != 0 || idx < 0) {
4129                                 printf("Invalid index \"%s\"\n", optarg);
4130                                 return -EINVAL;
4131                         }
4132                         break;
4133                 case '?':
4134                         print_help(udsp_cmds, "udsp", "add");
4135                 default:
4136                         return 0;
4137                 }
4138         }
4139
4140         if (!(src || dst || rte)) {
4141                 print_help(udsp_cmds, "udsp", "add");
4142                 return 0;
4143         }
4144
4145         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
4146                                   idx, -1, &err_rc);
4147
4148         if (rc != LUSTRE_CFG_RC_NO_ERR)
4149                 cYAML_print_tree2file(stderr, err_rc);
4150
4151         cYAML_free_tree(err_rc);
4152
4153         return rc;
4154 }
4155
4156 static int jt_del_udsp(int argc, char **argv)
4157 {
4158         struct cYAML *err_rc = NULL;
4159         long int idx = -2;
4160         int opt, rc = 0;
4161         bool all = false;
4162
4163         const char *const short_options = "ai:";
4164         static const struct option long_options[] = {
4165         { .name = "all",        .has_arg = no_argument, .val = 'a' },
4166         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
4167         { .name = NULL } };
4168
4169         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
4170         if (rc)
4171                 return rc;
4172
4173         while ((opt = getopt_long(argc, argv, short_options,
4174                                   long_options, NULL)) != -1) {
4175                 switch (opt) {
4176                 case 'a':
4177                         all = true;
4178                         break;
4179                 case 'i':
4180                         rc = parse_long(optarg, &idx);
4181                         if (rc != 0 || idx < -1) {
4182                                 printf("Invalid index \"%s\"\n", optarg);
4183                                 return -EINVAL;
4184                         }
4185                         break;
4186                 case '?':
4187                         print_help(udsp_cmds, "udsp", "del");
4188                 default:
4189                         return 0;
4190                 }
4191         }
4192
4193         if (all && idx != -2) {
4194                 printf("Cannot combine --all with --idx\n");
4195                 return -EINVAL;
4196         } else if (all) {
4197                 idx = -1;
4198         } else if (idx == -2) {
4199                 printf("Must specify --idx or --all\n");
4200                 return -EINVAL;
4201         }
4202
4203         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
4204         if (rc != LUSTRE_CFG_RC_NO_ERR)
4205                 cYAML_print_tree2file(stderr, err_rc);
4206
4207         cYAML_free_tree(err_rc);
4208
4209         return rc;
4210 }
4211
4212 int main(int argc, char **argv)
4213 {
4214         int rc = 0;
4215         struct cYAML *err_rc = NULL;
4216
4217         rc = lustre_lnet_config_lib_init();
4218         if (rc < 0) {
4219                 cYAML_build_error(-1, -1, "lnetctl", "startup",
4220                                   "cannot register LNet device", &err_rc);
4221                 cYAML_print_tree2file(stderr, err_rc);
4222                 return rc;
4223         }
4224
4225         return cfs_parser(argc, argv, cmd_list);
4226 }