Whamcloud - gitweb
8ed575590b87d5ec5e0a3b9ae675243ac995aad0
[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_route(char *nw, char *gw, int hops, int prio, int sen,
1138                            int version, int flags)
1139 {
1140         struct nl_sock *sk = NULL;
1141         const char *msg = NULL;
1142         yaml_emitter_t output;
1143         yaml_parser_t reply;
1144         yaml_event_t event;
1145         int rc;
1146
1147         /* Create Netlink emitter to send request to kernel */
1148         sk = nl_socket_alloc();
1149         if (!sk)
1150                 return -EOPNOTSUPP;
1151
1152         /* Setup parser to receive Netlink packets */
1153         rc = yaml_parser_initialize(&reply);
1154         if (rc == 0) {
1155                 nl_socket_free(sk);
1156                 return -EOPNOTSUPP;
1157         }
1158
1159         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1160         if (rc == 0) {
1161                 msg = yaml_parser_get_reader_error(&reply);
1162                 goto free_reply;
1163         }
1164
1165         /* Create Netlink emitter to send request to kernel */
1166         rc = yaml_emitter_initialize(&output);
1167         if (rc == 0) {
1168                 msg = "failed to initialize emitter";
1169                 goto free_reply;
1170         }
1171
1172         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1173                                              version, LNET_CMD_ROUTES, flags);
1174         if (rc == 0)
1175                 goto emitter_error;
1176
1177         yaml_emitter_open(&output);
1178         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1179         rc = yaml_emitter_emit(&output, &event);
1180         if (rc == 0)
1181                 goto emitter_error;
1182
1183         yaml_mapping_start_event_initialize(&event, NULL,
1184                                             (yaml_char_t *)YAML_MAP_TAG,
1185                                             1, YAML_ANY_MAPPING_STYLE);
1186         rc = yaml_emitter_emit(&output, &event);
1187         if (rc == 0)
1188                 goto emitter_error;
1189
1190         yaml_scalar_event_initialize(&event, NULL,
1191                                      (yaml_char_t *)YAML_STR_TAG,
1192                                      (yaml_char_t *)"route",
1193                                      strlen("route"), 1, 0,
1194                                      YAML_PLAIN_SCALAR_STYLE);
1195         rc = yaml_emitter_emit(&output, &event);
1196         if (rc == 0)
1197                 goto emitter_error;
1198
1199         if (nw || gw || hops != -1 || prio != -1) {
1200                 char num[INT_STRING_LEN];
1201
1202                 yaml_sequence_start_event_initialize(&event, NULL,
1203                                                      (yaml_char_t *)YAML_SEQ_TAG,
1204                                                      1,
1205                                                      YAML_BLOCK_SEQUENCE_STYLE);
1206                 rc = yaml_emitter_emit(&output, &event);
1207                 if (rc == 0)
1208                         goto emitter_error;
1209
1210                 if (nw) {
1211                         yaml_mapping_start_event_initialize(&event, NULL,
1212                                                             (yaml_char_t *)YAML_MAP_TAG,
1213                                                             1,
1214                                                             YAML_BLOCK_MAPPING_STYLE);
1215                         rc = yaml_emitter_emit(&output, &event);
1216                         if (rc == 0)
1217                                 goto emitter_error;
1218
1219                         yaml_scalar_event_initialize(&event, NULL,
1220                                                      (yaml_char_t *)YAML_STR_TAG,
1221                                                      (yaml_char_t *)"net",
1222                                                      strlen("net"), 1, 0,
1223                                                      YAML_PLAIN_SCALAR_STYLE);
1224                         rc = yaml_emitter_emit(&output, &event);
1225                         if (rc == 0)
1226                                 goto emitter_error;
1227
1228                         yaml_scalar_event_initialize(&event, NULL,
1229                                                      (yaml_char_t *)YAML_STR_TAG,
1230                                                      (yaml_char_t *)nw,
1231                                                      strlen(nw), 1, 0,
1232                                                      YAML_PLAIN_SCALAR_STYLE);
1233                         rc = yaml_emitter_emit(&output, &event);
1234                         if (rc == 0)
1235                                 goto emitter_error;
1236
1237                         yaml_mapping_end_event_initialize(&event);
1238                         rc = yaml_emitter_emit(&output, &event);
1239                         if (rc == 0)
1240                                 goto emitter_error;
1241                 }
1242
1243                 if (gw) {
1244                         yaml_mapping_start_event_initialize(&event, NULL,
1245                                                             (yaml_char_t *)YAML_MAP_TAG,
1246                                                             1,
1247                                                             YAML_BLOCK_MAPPING_STYLE);
1248                         rc = yaml_emitter_emit(&output, &event);
1249                         if (rc == 0)
1250                                 goto emitter_error;
1251
1252                         yaml_scalar_event_initialize(&event, NULL,
1253                                                      (yaml_char_t *)YAML_STR_TAG,
1254                                                      (yaml_char_t *)"gateway",
1255                                                      strlen("gateway"), 1, 0,
1256                                                      YAML_PLAIN_SCALAR_STYLE);
1257                         rc = yaml_emitter_emit(&output, &event);
1258                         if (rc == 0)
1259                                 goto emitter_error;
1260
1261                         yaml_scalar_event_initialize(&event, NULL,
1262                                                      (yaml_char_t *)YAML_STR_TAG,
1263                                                      (yaml_char_t *)gw,
1264                                                      strlen(gw), 1, 0,
1265                                                      YAML_PLAIN_SCALAR_STYLE);
1266                         rc = yaml_emitter_emit(&output, &event);
1267                         if (rc == 0)
1268                                 goto emitter_error;
1269
1270                         yaml_mapping_end_event_initialize(&event);
1271                         rc = yaml_emitter_emit(&output, &event);
1272                         if (rc == 0)
1273                                 goto emitter_error;
1274                 }
1275
1276                 if (hops != -1) {
1277                         yaml_mapping_start_event_initialize(&event, NULL,
1278                                                             (yaml_char_t *)YAML_MAP_TAG,
1279                                                             1,
1280                                                             YAML_BLOCK_MAPPING_STYLE);
1281                         rc = yaml_emitter_emit(&output, &event);
1282                         if (rc == 0)
1283                                 goto emitter_error;
1284
1285                         yaml_scalar_event_initialize(&event, NULL,
1286                                                      (yaml_char_t *)YAML_STR_TAG,
1287                                                      (yaml_char_t *)"hop",
1288                                                      strlen("hop"), 1, 0,
1289                                                      YAML_PLAIN_SCALAR_STYLE);
1290                         rc = yaml_emitter_emit(&output, &event);
1291                         if (rc == 0)
1292                                 goto emitter_error;
1293
1294                         snprintf(num, sizeof(num), "%d", hops);
1295                         yaml_scalar_event_initialize(&event, NULL,
1296                                                      (yaml_char_t *)YAML_INT_TAG,
1297                                                      (yaml_char_t *)num,
1298                                                      strlen(num), 1, 0,
1299                                                      YAML_PLAIN_SCALAR_STYLE);
1300                         rc = yaml_emitter_emit(&output, &event);
1301                         if (rc == 0)
1302                                 goto emitter_error;
1303
1304                         yaml_mapping_end_event_initialize(&event);
1305                         rc = yaml_emitter_emit(&output, &event);
1306                         if (rc == 0)
1307                                 goto emitter_error;
1308                 }
1309
1310                 if (prio != -1) {
1311                         yaml_mapping_start_event_initialize(&event, NULL,
1312                                                             (yaml_char_t *)YAML_MAP_TAG,
1313                                                             1,
1314                                                             YAML_BLOCK_MAPPING_STYLE);
1315                         rc = yaml_emitter_emit(&output, &event);
1316                         if (rc == 0)
1317                                 goto emitter_error;
1318
1319                         yaml_scalar_event_initialize(&event, NULL,
1320                                                      (yaml_char_t *)YAML_STR_TAG,
1321                                                      (yaml_char_t *)"priority",
1322                                                      strlen("priority"), 1, 0,
1323                                                      YAML_PLAIN_SCALAR_STYLE);
1324                         rc = yaml_emitter_emit(&output, &event);
1325                         if (rc == 0)
1326                                 goto emitter_error;
1327
1328                         snprintf(num, sizeof(num), "%d", prio);
1329                         yaml_scalar_event_initialize(&event, NULL,
1330                                                      (yaml_char_t *)YAML_INT_TAG,
1331                                                      (yaml_char_t *)num,
1332                                                      strlen(num), 1, 0,
1333                                                      YAML_PLAIN_SCALAR_STYLE);
1334                         rc = yaml_emitter_emit(&output, &event);
1335                         if (rc == 0)
1336                                 goto emitter_error;
1337
1338                         yaml_mapping_end_event_initialize(&event);
1339                         rc = yaml_emitter_emit(&output, &event);
1340                         if (rc == 0)
1341                                 goto emitter_error;
1342                 }
1343
1344                 if (sen != -1) {
1345                         yaml_mapping_start_event_initialize(&event, NULL,
1346                                                             (yaml_char_t *)YAML_MAP_TAG,
1347                                                             1,
1348                                                             YAML_BLOCK_MAPPING_STYLE);
1349                         rc = yaml_emitter_emit(&output, &event);
1350                         if (rc == 0)
1351                                 goto emitter_error;
1352
1353                         yaml_scalar_event_initialize(&event, NULL,
1354                                                      (yaml_char_t *)YAML_STR_TAG,
1355                                                      (yaml_char_t *)"health_sensitivity",
1356                                                      strlen("health_sensitivity"),
1357                                                      1, 0,
1358                                                      YAML_PLAIN_SCALAR_STYLE);
1359                         rc = yaml_emitter_emit(&output, &event);
1360                         if (rc == 0)
1361                                 goto emitter_error;
1362
1363                         snprintf(num, sizeof(num), "%d", sen);
1364                         yaml_scalar_event_initialize(&event, NULL,
1365                                                      (yaml_char_t *)YAML_INT_TAG,
1366                                                      (yaml_char_t *)num,
1367                                                      strlen(num), 1, 0,
1368                                                      YAML_PLAIN_SCALAR_STYLE);
1369                         rc = yaml_emitter_emit(&output, &event);
1370                         if (rc == 0)
1371                                 goto emitter_error;
1372
1373                         yaml_mapping_end_event_initialize(&event);
1374                         rc = yaml_emitter_emit(&output, &event);
1375                         if (rc == 0)
1376                                 goto emitter_error;
1377                 }
1378
1379                 yaml_sequence_end_event_initialize(&event);
1380                 rc = yaml_emitter_emit(&output, &event);
1381                 if (rc == 0)
1382                         goto emitter_error;
1383         } else {
1384                 yaml_scalar_event_initialize(&event, NULL,
1385                                              (yaml_char_t *)YAML_STR_TAG,
1386                                              (yaml_char_t *)"",
1387                                              strlen(""), 1, 0,
1388                                              YAML_PLAIN_SCALAR_STYLE);
1389                 rc = yaml_emitter_emit(&output, &event);
1390                 if (rc == 0)
1391                         goto emitter_error;
1392         }
1393
1394         yaml_mapping_end_event_initialize(&event);
1395         rc = yaml_emitter_emit(&output, &event);
1396         if (rc == 0)
1397                 goto emitter_error;
1398
1399         yaml_document_end_event_initialize(&event, 0);
1400         rc = yaml_emitter_emit(&output, &event);
1401         if (rc == 0)
1402                 goto emitter_error;
1403
1404         rc = yaml_emitter_close(&output);
1405 emitter_error:
1406         if (rc == 0) {
1407                 yaml_emitter_log_error(&output, stderr);
1408                 rc = -EINVAL;
1409         } else {
1410                 yaml_document_t errmsg;
1411
1412                 rc = yaml_parser_load(&reply, &errmsg);
1413                 if (rc == 1 && flags == NLM_F_DUMP) {
1414                         yaml_emitter_t debug;
1415
1416                         rc = yaml_emitter_initialize(&debug);
1417                         if (rc == 1) {
1418                                 yaml_emitter_set_indent(&debug, 6);
1419                                 yaml_emitter_set_output_file(&debug,
1420                                                              stdout);
1421                                 rc = yaml_emitter_dump(&debug, &errmsg);
1422                         }
1423                         yaml_emitter_delete(&debug);
1424                 } else {
1425                         msg = yaml_parser_get_reader_error(&reply);
1426                         /* If we didn't find any routes just be silent */
1427                         if (msg && strcmp(msg, "No routes found") == 0)
1428                                 rc = 1;
1429                 }
1430                 yaml_document_delete(&errmsg);
1431         }
1432         yaml_emitter_delete(&output);
1433 free_reply:
1434         if (rc == 0) {
1435                 yaml_lnet_print_error(flags, "route", msg);
1436                 rc = -EINVAL;
1437         }
1438         yaml_parser_delete(&reply);
1439         nl_socket_free(sk);
1440
1441         return rc == 1 ? 0 : rc;
1442 }
1443
1444 static int jt_add_route(int argc, char **argv)
1445 {
1446         char *network = NULL, *gateway = NULL;
1447         long int hop = -1, prio = -1, sen = -1;
1448         struct cYAML *err_rc = NULL;
1449         int rc, opt;
1450
1451         const char *const short_options = "n:g:c:p:";
1452         static const struct option long_options[] = {
1453         { .name = "net",       .has_arg = required_argument, .val = 'n' },
1454         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1455         { .name = "hop",       .has_arg = required_argument, .val = 'c' },
1456         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1457         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1458         { .name = "health_sensitivity",  .has_arg = required_argument, .val = 's' },
1459         { .name = NULL } };
1460
1461         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
1462         if (rc)
1463                 return rc;
1464
1465         while ((opt = getopt_long(argc, argv, short_options,
1466                                    long_options, NULL)) != -1) {
1467                 switch (opt) {
1468                 case 'n':
1469                         network = optarg;
1470                         break;
1471                 case 'g':
1472                         gateway = optarg;
1473                         break;
1474                 case 'c':
1475                         rc = parse_long(optarg, &hop);
1476                         if (rc != 0) {
1477                                 /* ignore option */
1478                                 hop = -1;
1479                                 continue;
1480                         }
1481                         break;
1482                 case 'p':
1483                         rc = parse_long(optarg, &prio);
1484                         if (rc != 0) {
1485                                 /* ingore option */
1486                                 prio = -1;
1487                                 continue;
1488                         }
1489                         break;
1490                 case 's':
1491                         rc = parse_long(optarg, &sen);
1492                         if (rc != 0) {
1493                                 /* ingore option */
1494                                 sen = -1;
1495                                 continue;
1496                         }
1497                         break;
1498
1499                 case '?':
1500                         print_help(route_cmds, "route", "add");
1501                 default:
1502                         return 0;
1503                 }
1504         }
1505
1506         rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
1507                                       &err_rc);
1508
1509         if (rc != LUSTRE_CFG_RC_NO_ERR)
1510                 cYAML_print_tree2file(stderr, err_rc);
1511
1512         cYAML_free_tree(err_rc);
1513
1514         return rc;
1515 }
1516
1517 static int yaml_add_ni_tunables(yaml_emitter_t *output,
1518                                 struct lnet_ioctl_config_lnd_tunables *tunables,
1519                                 struct lnet_dlc_network_descr *nw_descr)
1520 {
1521         char num[INT_STRING_LEN];
1522         yaml_event_t event;
1523         int rc;
1524
1525         if (tunables->lt_cmn.lct_peer_timeout < 0 &&
1526             tunables->lt_cmn.lct_peer_tx_credits <= 0 &&
1527             tunables->lt_cmn.lct_peer_rtr_credits <= 0 &&
1528             tunables->lt_cmn.lct_max_tx_credits <= 0)
1529                 goto skip_general_settings;
1530
1531         yaml_scalar_event_initialize(&event, NULL,
1532                                      (yaml_char_t *)YAML_STR_TAG,
1533                                      (yaml_char_t *)"tunables",
1534                                      strlen("tunables"), 1, 0,
1535                                      YAML_PLAIN_SCALAR_STYLE);
1536         rc = yaml_emitter_emit(output, &event);
1537         if (rc == 0)
1538                 goto error;
1539
1540         yaml_mapping_start_event_initialize(&event, NULL,
1541                                             (yaml_char_t *)YAML_MAP_TAG,
1542                                             1, YAML_ANY_MAPPING_STYLE);
1543         rc = yaml_emitter_emit(output, &event);
1544         if (rc == 0)
1545                 goto error;
1546
1547         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1548                 yaml_scalar_event_initialize(&event, NULL,
1549                                              (yaml_char_t *)YAML_STR_TAG,
1550                                              (yaml_char_t *)"peer_timeout",
1551                                              strlen("peer_timeout"), 1, 0,
1552                                              YAML_PLAIN_SCALAR_STYLE);
1553                 rc = yaml_emitter_emit(output, &event);
1554                 if (rc == 0)
1555                         goto error;
1556
1557                 snprintf(num, sizeof(num), "%u",
1558                          tunables->lt_cmn.lct_peer_timeout);
1559                 yaml_scalar_event_initialize(&event, NULL,
1560                                              (yaml_char_t *)YAML_INT_TAG,
1561                                              (yaml_char_t *)num,
1562                                              strlen(num), 1, 0,
1563                                              YAML_PLAIN_SCALAR_STYLE);
1564                 rc = yaml_emitter_emit(output, &event);
1565                 if (rc == 0)
1566                         goto error;
1567         }
1568
1569         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1570                 yaml_scalar_event_initialize(&event, NULL,
1571                                              (yaml_char_t *)YAML_STR_TAG,
1572                                              (yaml_char_t *)"peer_credits",
1573                                              strlen("peer_credits"), 1, 0,
1574                                              YAML_PLAIN_SCALAR_STYLE);
1575                 rc = yaml_emitter_emit(output, &event);
1576                 if (rc == 0)
1577                         goto error;
1578
1579                 snprintf(num, sizeof(num), "%u",
1580                          tunables->lt_cmn.lct_peer_tx_credits);
1581                 yaml_scalar_event_initialize(&event, NULL,
1582                                              (yaml_char_t *)YAML_INT_TAG,
1583                                              (yaml_char_t *)num,
1584                                              strlen(num), 1, 0,
1585                                              YAML_PLAIN_SCALAR_STYLE);
1586                 rc = yaml_emitter_emit(output, &event);
1587                 if (rc == 0)
1588                         goto error;
1589         }
1590
1591         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1592                 yaml_scalar_event_initialize(&event, NULL,
1593                                              (yaml_char_t *)YAML_STR_TAG,
1594                                              (yaml_char_t *)"peer_buffer_credits",
1595                                              strlen("peer_buffer_credits"), 1, 0,
1596                                              YAML_PLAIN_SCALAR_STYLE);
1597                 rc = yaml_emitter_emit(output, &event);
1598                 if (rc == 0)
1599                         goto error;
1600
1601                 snprintf(num, sizeof(num), "%u",
1602                          tunables->lt_cmn.lct_peer_rtr_credits);
1603                 yaml_scalar_event_initialize(&event, NULL,
1604                                              (yaml_char_t *)YAML_INT_TAG,
1605                                              (yaml_char_t *)num,
1606                                              strlen(num), 1, 0,
1607                                              YAML_PLAIN_SCALAR_STYLE);
1608                 rc = yaml_emitter_emit(output, &event);
1609                 if (rc == 0)
1610                         goto error;
1611         }
1612
1613         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1614                 yaml_scalar_event_initialize(&event, NULL,
1615                                              (yaml_char_t *)YAML_STR_TAG,
1616                                              (yaml_char_t *)"credits",
1617                                              strlen("credits"), 1, 0,
1618                                              YAML_PLAIN_SCALAR_STYLE);
1619                 rc = yaml_emitter_emit(output, &event);
1620                 if (rc == 0)
1621                         goto error;
1622
1623                 snprintf(num, sizeof(num), "%u",
1624                          tunables->lt_cmn.lct_max_tx_credits);
1625                 yaml_scalar_event_initialize(&event, NULL,
1626                                              (yaml_char_t *)YAML_INT_TAG,
1627                                              (yaml_char_t *)num,
1628                                              strlen(num), 1, 0,
1629                                              YAML_PLAIN_SCALAR_STYLE);
1630                 rc = yaml_emitter_emit(output, &event);
1631                 if (rc == 0)
1632                         goto error;
1633         }
1634
1635         yaml_mapping_end_event_initialize(&event);
1636         rc = yaml_emitter_emit(output, &event);
1637         if (rc == 0)
1638                 goto error;
1639
1640 skip_general_settings:
1641         if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1642 #ifdef HAVE_KFILND
1643             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0 ||
1644             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0] ||
1645 #endif
1646             tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1647                 yaml_scalar_event_initialize(&event, NULL,
1648                                              (yaml_char_t *)YAML_STR_TAG,
1649                                              (yaml_char_t *)"lnd tunables",
1650                                              strlen("lnd tunables"), 1, 0,
1651                                              YAML_PLAIN_SCALAR_STYLE);
1652                 rc = yaml_emitter_emit(output, &event);
1653                 if (rc == 0)
1654                         goto error;
1655
1656                 yaml_mapping_start_event_initialize(&event, NULL,
1657                                                     (yaml_char_t *)YAML_MAP_TAG,
1658                                                     1, YAML_ANY_MAPPING_STYLE);
1659                 rc = yaml_emitter_emit(output, &event);
1660                 if (rc == 0)
1661                         goto error;
1662 #ifdef HAVE_KFILND
1663                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1664                         yaml_scalar_event_initialize(&event, NULL,
1665                                                      (yaml_char_t *)YAML_STR_TAG,
1666                                                      (yaml_char_t *)"auth_key",
1667                                                      strlen("auth_key"), 1, 0,
1668                                                      YAML_PLAIN_SCALAR_STYLE);
1669                         rc = yaml_emitter_emit(output, &event);
1670                         if (rc == 0)
1671                                 goto error;
1672
1673                         snprintf(num, sizeof(num), "%u",
1674                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1675
1676                         yaml_scalar_event_initialize(&event, NULL,
1677                                                      (yaml_char_t *)YAML_INT_TAG,
1678                                                      (yaml_char_t *)num,
1679                                                      strlen(num), 1, 0,
1680                                                      YAML_PLAIN_SCALAR_STYLE);
1681                         rc = yaml_emitter_emit(output, &event);
1682                         if (rc == 0)
1683                                 goto error;
1684                 }
1685
1686                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0]) {
1687                         char *tc = &tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0];
1688
1689                         yaml_scalar_event_initialize(&event, NULL,
1690                                                      (yaml_char_t *)YAML_STR_TAG,
1691                                                      (yaml_char_t *)"traffic_class",
1692                                                      strlen("traffic_class"), 1, 0,
1693                                                      YAML_PLAIN_SCALAR_STYLE);
1694                         rc = yaml_emitter_emit(output, &event);
1695                         if (rc == 0)
1696                                 goto error;
1697
1698                         yaml_scalar_event_initialize(&event, NULL,
1699                                                      (yaml_char_t *)YAML_INT_TAG,
1700                                                      (yaml_char_t *)tc,
1701                                                      strlen(tc), 1, 0,
1702                                                      YAML_PLAIN_SCALAR_STYLE);
1703
1704                         rc = yaml_emitter_emit(output, &event);
1705                         if (rc == 0)
1706                                 goto error;
1707                 }
1708 #endif
1709                 if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1710                     tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1711                         int cpp = 0;
1712
1713                         yaml_scalar_event_initialize(&event, NULL,
1714                                                      (yaml_char_t *)YAML_STR_TAG,
1715                                                      (yaml_char_t *)"conns_per_peer",
1716                                                      strlen("conns_per_peer"), 1, 0,
1717                                                      YAML_PLAIN_SCALAR_STYLE);
1718                         rc = yaml_emitter_emit(output, &event);
1719                         if (rc == 0)
1720                                 goto error;
1721
1722                         if (LNET_NETTYP(nw_descr->nw_id) == SOCKLND)
1723                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1724                         else if (LNET_NETTYP(nw_descr->nw_id) == O2IBLND)
1725                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer;
1726                         snprintf(num, sizeof(num), "%u", cpp);
1727
1728                         yaml_scalar_event_initialize(&event, NULL,
1729                                                      (yaml_char_t *)YAML_INT_TAG,
1730                                                      (yaml_char_t *)num,
1731                                                      strlen(num), 1, 0,
1732                                                      YAML_PLAIN_SCALAR_STYLE);
1733                         rc = yaml_emitter_emit(output, &event);
1734                         if (rc == 0)
1735                                 goto error;
1736                 }
1737
1738                 yaml_mapping_end_event_initialize(&event);
1739                 rc = yaml_emitter_emit(output, &event);
1740         }
1741 error:
1742         return rc;
1743 }
1744
1745 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1746                                struct lnet_dlc_network_descr *nw_descr,
1747                                struct lnet_ioctl_config_lnd_tunables *tunables,
1748                                struct cfs_expr_list *global_cpts,
1749                                int version, int flags)
1750 {
1751         struct lnet_dlc_intf_descr *intf;
1752         struct nl_sock *sk = NULL;
1753         const char *msg = NULL;
1754         yaml_emitter_t output;
1755         yaml_parser_t reply;
1756         yaml_event_t event;
1757         int rc;
1758
1759         if (!(flags & NLM_F_DUMP) && !ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1760                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'",
1761                         (!nw_descr) ? "network , interface" :
1762                         (nw_descr->nw_id == 0) ? "network" : "interface");
1763                 return -EINVAL;
1764         }
1765
1766         if ((flags == NLM_F_CREATE) && !ip2net && list_empty(&nw_descr->nw_intflist)) {
1767                 fprintf(stdout, "creating a local NI needs at least one interface");
1768                 return -EINVAL;
1769         }
1770
1771         /* Create Netlink emitter to send request to kernel */
1772         sk = nl_socket_alloc();
1773         if (!sk)
1774                 return -EOPNOTSUPP;
1775
1776         /* Setup parser to receive Netlink packets */
1777         rc = yaml_parser_initialize(&reply);
1778         if (rc == 0) {
1779                 nl_socket_free(sk);
1780                 return -EOPNOTSUPP;
1781         }
1782
1783         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1784         if (rc == 0) {
1785                 msg = yaml_parser_get_reader_error(&reply);
1786                 goto free_reply;
1787         }
1788
1789         /* Create Netlink emitter to send request to kernel */
1790         rc = yaml_emitter_initialize(&output);
1791         if (rc == 0) {
1792                 msg = "failed to initialize emitter";
1793                 goto free_reply;
1794         }
1795
1796         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1797                                              version, LNET_CMD_NETS, flags);
1798         if (rc == 0)
1799                 goto emitter_error;
1800
1801         yaml_emitter_open(&output);
1802         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1803         rc = yaml_emitter_emit(&output, &event);
1804         if (rc == 0)
1805                 goto emitter_error;
1806
1807         yaml_mapping_start_event_initialize(&event, NULL,
1808                                             (yaml_char_t *)YAML_MAP_TAG,
1809                                             1, YAML_ANY_MAPPING_STYLE);
1810         rc = yaml_emitter_emit(&output, &event);
1811         if (rc == 0)
1812                 goto emitter_error;
1813
1814         yaml_scalar_event_initialize(&event, NULL,
1815                                      (yaml_char_t *)YAML_STR_TAG,
1816                                      (yaml_char_t *)"net",
1817                                      strlen("net"), 1, 0,
1818                                      YAML_PLAIN_SCALAR_STYLE);
1819         rc = yaml_emitter_emit(&output, &event);
1820         if (rc == 0)
1821                 goto emitter_error;
1822
1823         if (net_id || ip2net) {
1824                 char *key = net_id ? "net type" : "ip2net";
1825                 char *value = net_id ? net_id : ip2net;
1826
1827                 yaml_sequence_start_event_initialize(&event, NULL,
1828                                                      (yaml_char_t *)YAML_SEQ_TAG,
1829                                                      1, YAML_ANY_SEQUENCE_STYLE);
1830                 rc = yaml_emitter_emit(&output, &event);
1831                 if (rc == 0)
1832                         goto emitter_error;
1833
1834                 yaml_mapping_start_event_initialize(&event, NULL,
1835                                                     (yaml_char_t *)YAML_MAP_TAG,
1836                                                     1, YAML_ANY_MAPPING_STYLE);
1837                 rc = yaml_emitter_emit(&output, &event);
1838                 if (rc == 0)
1839                         goto emitter_error;
1840
1841                 yaml_scalar_event_initialize(&event, NULL,
1842                                              (yaml_char_t *)YAML_STR_TAG,
1843                                              (yaml_char_t *)key,
1844                                              strlen(key),
1845                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
1846                 rc = yaml_emitter_emit(&output, &event);
1847                 if (rc == 0)
1848                         goto emitter_error;
1849
1850                 yaml_scalar_event_initialize(&event, NULL,
1851                                              (yaml_char_t *)YAML_STR_TAG,
1852                                              (yaml_char_t *)value,
1853                                              strlen(value), 1, 0,
1854                                              YAML_PLAIN_SCALAR_STYLE);
1855                 rc = yaml_emitter_emit(&output, &event);
1856                 if (rc == 0)
1857                         goto emitter_error;
1858         } else {
1859                 yaml_scalar_event_initialize(&event, NULL,
1860                                              (yaml_char_t *)YAML_STR_TAG,
1861                                              (yaml_char_t *)"",
1862                                              strlen(""), 1, 0,
1863                                              YAML_PLAIN_SCALAR_STYLE);
1864                 rc = yaml_emitter_emit(&output, &event);
1865                 if (rc == 0)
1866                         goto emitter_error;
1867
1868                 goto no_net_id;
1869         }
1870
1871         if (!nw_descr || list_empty(&nw_descr->nw_intflist))
1872                 goto skip_intf;
1873
1874         yaml_scalar_event_initialize(&event, NULL,
1875                                      (yaml_char_t *)YAML_STR_TAG,
1876                                      (yaml_char_t *)"local NI(s)",
1877                                      strlen("local NI(s)"), 1, 0,
1878                                      YAML_PLAIN_SCALAR_STYLE);
1879         rc = yaml_emitter_emit(&output, &event);
1880         if (rc == 0)
1881                 goto emitter_error;
1882
1883         yaml_sequence_start_event_initialize(&event, NULL,
1884                                              (yaml_char_t *)YAML_SEQ_TAG,
1885                                              1, YAML_ANY_SEQUENCE_STYLE);
1886         rc = yaml_emitter_emit(&output, &event);
1887         if (rc == 0)
1888                 goto emitter_error;
1889
1890         list_for_each_entry(intf, &nw_descr->nw_intflist,
1891                             intf_on_network) {
1892                 yaml_mapping_start_event_initialize(&event, NULL,
1893                                                     (yaml_char_t *)YAML_MAP_TAG,
1894                                                     1, YAML_ANY_MAPPING_STYLE);
1895                 rc = yaml_emitter_emit(&output, &event);
1896                 if (rc == 0)
1897                         goto emitter_error;
1898
1899                 yaml_scalar_event_initialize(&event, NULL,
1900                                              (yaml_char_t *)YAML_STR_TAG,
1901                                              (yaml_char_t *)"interfaces",
1902                                              strlen("interfaces"), 1, 0,
1903                                              YAML_PLAIN_SCALAR_STYLE);
1904                 rc = yaml_emitter_emit(&output, &event);
1905                 if (rc == 0)
1906                         goto emitter_error;
1907
1908                 yaml_mapping_start_event_initialize(&event, NULL,
1909                                                     (yaml_char_t *)YAML_MAP_TAG,
1910                                                     1, YAML_ANY_MAPPING_STYLE);
1911                 rc = yaml_emitter_emit(&output, &event);
1912                 if (rc == 0)
1913                         goto emitter_error;
1914
1915                 yaml_scalar_event_initialize(&event, NULL,
1916                                              (yaml_char_t *)YAML_STR_TAG,
1917                                              (yaml_char_t *)"0",
1918                                              strlen("0"), 1, 0,
1919                                              YAML_PLAIN_SCALAR_STYLE);
1920                 rc = yaml_emitter_emit(&output, &event);
1921                 if (rc == 0)
1922                         goto emitter_error;
1923
1924                 yaml_scalar_event_initialize(&event, NULL,
1925                                              (yaml_char_t *)YAML_STR_TAG,
1926                                              (yaml_char_t *)intf->intf_name,
1927                                              strlen(intf->intf_name), 1, 0,
1928                                              YAML_PLAIN_SCALAR_STYLE);
1929                 rc = yaml_emitter_emit(&output, &event);
1930                 if (rc == 0)
1931                         goto emitter_error;
1932
1933                 yaml_mapping_end_event_initialize(&event);
1934                 rc = yaml_emitter_emit(&output, &event);
1935                 if (rc == 0)
1936                         goto emitter_error;
1937
1938                 if (tunables) {
1939                         rc = yaml_add_ni_tunables(&output, tunables, nw_descr);
1940                         if (rc == 0)
1941                                 goto emitter_error;
1942                 }
1943
1944                 if (global_cpts) {
1945                         __u32 *cpt_array;
1946                         int count, i;
1947
1948                         yaml_scalar_event_initialize(&event, NULL,
1949                                                      (yaml_char_t *)YAML_STR_TAG,
1950                                                      (yaml_char_t *)"CPT",
1951                                                      strlen("CPT"), 1, 0,
1952                                                      YAML_PLAIN_SCALAR_STYLE);
1953                         rc = yaml_emitter_emit(&output, &event);
1954                         if (rc == 0)
1955                                 goto emitter_error;
1956
1957                         yaml_sequence_start_event_initialize(&event, NULL,
1958                                                              (yaml_char_t *)YAML_SEQ_TAG,
1959                                                              1,
1960                                                              YAML_FLOW_SEQUENCE_STYLE);
1961                         rc = yaml_emitter_emit(&output, &event);
1962                         if (rc == 0)
1963                                 goto emitter_error;
1964
1965                         count = cfs_expr_list_values(global_cpts,
1966                                                      LNET_MAX_SHOW_NUM_CPT,
1967                                                      &cpt_array);
1968                         for (i = 0; i < count; i++) {
1969                                 char core[INT_STRING_LEN];
1970
1971                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
1972                                 yaml_scalar_event_initialize(&event, NULL,
1973                                                              (yaml_char_t *)YAML_STR_TAG,
1974                                                              (yaml_char_t *)core,
1975                                                              strlen(core), 1, 0,
1976                                                              YAML_PLAIN_SCALAR_STYLE);
1977                                 rc = yaml_emitter_emit(&output, &event);
1978                                 if (rc == 0)
1979                                         goto emitter_error;
1980                         }
1981
1982                         yaml_sequence_end_event_initialize(&event);
1983                         rc = yaml_emitter_emit(&output, &event);
1984                         if (rc == 0)
1985                                 goto emitter_error;
1986
1987                         cfs_expr_list_free(global_cpts);
1988                         free(cpt_array);
1989                 }
1990
1991                 yaml_mapping_end_event_initialize(&event);
1992                 rc = yaml_emitter_emit(&output, &event);
1993                 if (rc == 0)
1994                         goto emitter_error;
1995         }
1996
1997         yaml_sequence_end_event_initialize(&event);
1998         rc = yaml_emitter_emit(&output, &event);
1999         if (rc == 0)
2000                 goto emitter_error;
2001 skip_intf:
2002         yaml_mapping_end_event_initialize(&event);
2003         rc = yaml_emitter_emit(&output, &event);
2004         if (rc == 0)
2005                 goto emitter_error;
2006
2007         yaml_sequence_end_event_initialize(&event);
2008         rc = yaml_emitter_emit(&output, &event);
2009         if (rc == 0)
2010                 goto emitter_error;
2011 no_net_id:
2012         yaml_mapping_end_event_initialize(&event);
2013         rc = yaml_emitter_emit(&output, &event);
2014         if (rc == 0)
2015                 goto emitter_error;
2016
2017         yaml_document_end_event_initialize(&event, 0);
2018         rc = yaml_emitter_emit(&output, &event);
2019         if (rc == 0)
2020                 goto emitter_error;
2021
2022         rc = yaml_emitter_close(&output);
2023 emitter_error:
2024         if (rc == 0) {
2025                 yaml_emitter_log_error(&output, stderr);
2026                 rc = -EINVAL;
2027         } else {
2028                 yaml_document_t errmsg;
2029
2030                 rc = yaml_parser_load(&reply, &errmsg);
2031                 if (rc == 1 && (flags & NLM_F_DUMP)) {
2032                         yaml_emitter_t debug;
2033
2034                         rc = yaml_emitter_initialize(&debug);
2035                         if (rc == 1) {
2036                                 yaml_emitter_set_indent(&debug,
2037                                                         LNET_DEFAULT_INDENT);
2038                                 yaml_emitter_set_output_file(&debug, stdout);
2039                                 rc = yaml_emitter_dump(&debug, &errmsg);
2040                         }
2041                         yaml_emitter_delete(&debug);
2042                 } else {
2043                         msg = yaml_parser_get_reader_error(&reply);
2044                 }
2045                 yaml_document_delete(&errmsg);
2046         }
2047         yaml_emitter_delete(&output);
2048 free_reply:
2049         if (rc == 0) {
2050                 yaml_lnet_print_error(flags, "net", msg);
2051                 rc = -EINVAL;
2052         }
2053         yaml_parser_delete(&reply);
2054         nl_socket_free(sk);
2055
2056         return rc == 1 ? 0 : rc;
2057 }
2058
2059 static int jt_add_ni(int argc, char **argv)
2060 {
2061         char *ip2net = NULL;
2062         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
2063         char *traffic_class = NULL;
2064         struct cYAML *err_rc = NULL;
2065         int rc, opt, cpt_rc = -1;
2066         struct lnet_dlc_network_descr nw_descr;
2067         struct cfs_expr_list *global_cpts = NULL;
2068         struct lnet_ioctl_config_lnd_tunables tunables;
2069         bool found = false;
2070         bool skip_mr_route_setup = false;
2071         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:T:";
2072         static const struct option long_options[] = {
2073         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
2074         { .name = "peer-buffer-credits",
2075                                   .has_arg = required_argument, .val = 'b' },
2076         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
2077         { .name = "if",           .has_arg = required_argument, .val = 'i' },
2078         { .name = "skip-mr-route-setup",
2079                                   .has_arg = no_argument, .val = 'k' },
2080         { .name = "conns-per-peer",
2081                                   .has_arg = required_argument, .val = 'm' },
2082         { .name = "net",          .has_arg = required_argument, .val = 'n' },
2083         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
2084         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
2085         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
2086         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
2087         { .name = "traffic-class", .has_arg = required_argument, .val = 'T' },
2088         { .name = NULL } };
2089         char *net_id = NULL;
2090
2091         memset(&tunables, 0, sizeof(tunables));
2092         lustre_lnet_init_nw_descr(&nw_descr);
2093
2094         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
2095         if (rc)
2096                 return rc;
2097
2098         while ((opt = getopt_long(argc, argv, short_options,
2099                                    long_options, NULL)) != -1) {
2100                 switch (opt) {
2101                 case 'a':
2102                         rc = parse_long(optarg, &auth_key);
2103                         if (rc != 0) {
2104                                 /* ignore option */
2105                                 auth_key = -1;
2106                                 continue;
2107                         }
2108                         break;
2109                 case 'b':
2110                         rc = parse_long(optarg, &pbc);
2111                         if (rc != 0) {
2112                                 /* ignore option */
2113                                 pbc = -1;
2114                                 continue;
2115                         }
2116                         break;
2117                 case 'c':
2118                         rc = parse_long(optarg, &pc);
2119                         if (rc != 0) {
2120                                 /* ignore option */
2121                                 pc = -1;
2122                                 continue;
2123                         }
2124                         break;
2125                 case 'i':
2126                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2127                         if (rc != 0) {
2128                                 cYAML_build_error(-1, -1, "ni", "add",
2129                                                 "bad interface list",
2130                                                 &err_rc);
2131                                 goto failed;
2132                         }
2133                         break;
2134                 case 'k':
2135                         skip_mr_route_setup = true;
2136                         break;
2137                 case 'm':
2138                         rc = parse_long(optarg, &cpp);
2139                         if (rc != 0) {
2140                                 /* ignore option */
2141                                 cpp = -1;
2142                                 continue;
2143                         }
2144                         break;
2145
2146                 case 'n':
2147                         nw_descr.nw_id = libcfs_str2net(optarg);
2148                         net_id = optarg;
2149                         break;
2150                 case 'p':
2151                         ip2net = optarg;
2152                         break;
2153                 case 'r':
2154                         rc = parse_long(optarg, &cre);
2155                         if (rc != 0) {
2156                                 /* ignore option */
2157                                 cre = -1;
2158                                 continue;
2159                         }
2160                         break;
2161                 case 's':
2162                         cpt_rc = cfs_expr_list_parse(optarg,
2163                                                      strlen(optarg), 0,
2164                                                      UINT_MAX, &global_cpts);
2165                         break;
2166                 case 't':
2167                         rc = parse_long(optarg, &pto);
2168                         if (rc != 0) {
2169                                 /* ignore option */
2170                                 pto = -1;
2171                                 continue;
2172                         }
2173                         break;
2174                 case 'T':
2175                         traffic_class = optarg;
2176                         if (strlen(traffic_class) == 0 ||
2177                             strlen(traffic_class) >= LNET_MAX_STR_LEN) {
2178                                 cYAML_build_error(-1, -1, "ni", "add",
2179                                                   "Invalid traffic-class argument",
2180                                                   &err_rc);
2181                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2182                                 goto failed;
2183                         }
2184                         break;
2185                 case '?':
2186                         print_help(net_cmds, "net", "add");
2187                 default:
2188                         return 0;
2189                 }
2190         }
2191 #ifdef HAVE_KFILND
2192         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
2193                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
2194                 found = true;
2195         }
2196
2197         if (traffic_class && LNET_NETTYP(nw_descr.nw_id) == KFILND &&
2198             strlen(traffic_class) < LNET_MAX_STR_LEN) {
2199                 strcpy(&tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0],
2200                        traffic_class);
2201                 found = true;
2202         }
2203 #endif
2204
2205         if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1)) {
2206                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2207                 found = true;
2208         } else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1)) {
2209                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
2210                 found = true;
2211         }
2212
2213         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
2214                 tunables.lt_cmn.lct_peer_timeout = pto;
2215                 tunables.lt_cmn.lct_peer_tx_credits = pc;
2216                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
2217                 tunables.lt_cmn.lct_max_tx_credits = cre;
2218                 found = true;
2219         }
2220
2221         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
2222                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
2223
2224         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
2225                                  found ? &tunables : NULL,
2226                                  (cpt_rc == 0) ? global_cpts : NULL,
2227                                  LNET_GENL_VERSION, NLM_F_CREATE);
2228         if (rc <= 0) {
2229                 if (rc == -EOPNOTSUPP)
2230                         goto old_api;
2231                 if (global_cpts != NULL)
2232                         cfs_expr_list_free(global_cpts);
2233                 if (rc == 0 && !skip_mr_route_setup)
2234                         rc = lustre_lnet_setup_mrrouting(&err_rc);
2235                 return rc;
2236         }
2237 old_api:
2238         rc = lustre_lnet_config_ni(&nw_descr,
2239                                    (cpt_rc == 0) ? global_cpts: NULL,
2240                                    ip2net, (found) ? &tunables : NULL,
2241                                    cpp, &err_rc);
2242
2243         if (global_cpts != NULL)
2244                 cfs_expr_list_free(global_cpts);
2245
2246 failed:
2247         if (rc != LUSTRE_CFG_RC_NO_ERR)
2248                 cYAML_print_tree2file(stderr, err_rc);
2249
2250         cYAML_free_tree(err_rc);
2251
2252         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
2253                 err_rc = NULL;
2254                 rc = lustre_lnet_setup_mrrouting(&err_rc);
2255
2256                 if (rc != LUSTRE_CFG_RC_NO_ERR)
2257                         cYAML_print_tree2file(stderr, err_rc);
2258
2259                 cYAML_free_tree(err_rc);
2260         }
2261
2262         return rc;
2263 }
2264
2265 static int jt_del_route(int argc, char **argv)
2266 {
2267         char *network = NULL, *gateway = NULL;
2268         struct cYAML *err_rc = NULL;
2269         int rc, opt;
2270
2271         const char *const short_options = "n:g:";
2272         static const struct option long_options[] = {
2273                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2274                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
2275                 { .name = NULL } };
2276
2277         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
2278         if (rc)
2279                 return rc;
2280
2281         while ((opt = getopt_long(argc, argv, short_options,
2282                                    long_options, NULL)) != -1) {
2283                 switch (opt) {
2284                 case 'n':
2285                         network = optarg;
2286                         break;
2287                 case 'g':
2288                         gateway = optarg;
2289                         break;
2290                 case '?':
2291                         print_help(route_cmds, "route", "del");
2292                 default:
2293                         return 0;
2294                 }
2295         }
2296
2297         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
2298
2299         if (rc != LUSTRE_CFG_RC_NO_ERR)
2300                 cYAML_print_tree2file(stderr, err_rc);
2301
2302         cYAML_free_tree(err_rc);
2303
2304         return rc;
2305 }
2306
2307 static int jt_del_ni(int argc, char **argv)
2308 {
2309         struct cYAML *err_rc = NULL;
2310         int rc, opt;
2311         struct lnet_dlc_network_descr nw_descr;
2312         const char *const short_options = "n:i:";
2313         static const struct option long_options[] = {
2314         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
2315         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
2316         { .name = NULL } };
2317         char *net_id = NULL;
2318
2319         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
2320         if (rc)
2321                 return rc;
2322
2323         lustre_lnet_init_nw_descr(&nw_descr);
2324
2325         while ((opt = getopt_long(argc, argv, short_options,
2326                                    long_options, NULL)) != -1) {
2327                 switch (opt) {
2328                 case 'n':
2329                         nw_descr.nw_id = libcfs_str2net(optarg);
2330                         net_id = optarg;
2331                         break;
2332                 case 'i':
2333                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2334                         if (rc != 0) {
2335                                 cYAML_build_error(-1, -1, "ni", "add",
2336                                                 "bad interface list",
2337                                                 &err_rc);
2338                                 goto out;
2339                         }
2340                         break;
2341                 case '?':
2342                         print_help(net_cmds, "net", "del");
2343                 default:
2344                         return 0;
2345                 }
2346         }
2347
2348         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, NULL,
2349                                  LNET_GENL_VERSION, 0);
2350         if (rc <= 0) {
2351                 if (rc != -EOPNOTSUPP)
2352                         return rc;
2353         }
2354
2355         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
2356 out:
2357         if (rc != LUSTRE_CFG_RC_NO_ERR)
2358                 cYAML_print_tree2file(stderr, err_rc);
2359
2360         cYAML_free_tree(err_rc);
2361
2362         return rc;
2363 }
2364
2365 static int jt_show_route(int argc, char **argv)
2366 {
2367         char *network = NULL, *gateway = NULL;
2368         long int hop = -1, prio = -1;
2369         int detail = 0, rc, opt;
2370         struct cYAML *err_rc = NULL, *show_rc = NULL;
2371         const char *const short_options = "c:n:g:p:v";
2372         static const struct option long_options[] = {
2373                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
2374                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
2375                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
2376                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
2377                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
2378                 { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
2379                 { .name = NULL }
2380         };
2381
2382         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
2383         if (rc)
2384                 return rc;
2385
2386         while ((opt = getopt_long(argc, argv, short_options,
2387                                    long_options, NULL)) != -1) {
2388                 switch (opt) {
2389                 case 'n':
2390                         network = optarg;
2391                         break;
2392                 case 'g':
2393                         gateway = optarg;
2394                         break;
2395                 case 'c':
2396                         rc = parse_long(optarg, &hop);
2397                         if (rc != 0) {
2398                                 /* ignore option */
2399                                 hop = -1;
2400                                 continue;
2401                         }
2402                         break;
2403                 case 'p':
2404                         rc = parse_long(optarg, &prio);
2405                         if (rc != 0) {
2406                                 /* ignore option */
2407                                 prio = -1;
2408                                 continue;
2409                         }
2410                         break;
2411                 case 'v':
2412                         detail = 1;
2413                         break;
2414                 case '?':
2415                         print_help(route_cmds, "route", "show");
2416                 default:
2417                         return 0;
2418                 }
2419         }
2420
2421         rc = yaml_lnet_route(network, gateway, hop, prio, -1,
2422                              detail, NLM_F_DUMP);
2423         if (rc <= 0) {
2424                 if (rc == -EOPNOTSUPP)
2425                         goto old_api;
2426                 return rc;
2427         }
2428 old_api:
2429         rc = lustre_lnet_show_route(network, gateway, hop, prio,
2430                                     detail ? 1 : 0, -1,
2431                                     &show_rc, &err_rc, false);
2432
2433         if (rc != LUSTRE_CFG_RC_NO_ERR)
2434                 cYAML_print_tree2file(stderr, err_rc);
2435         else if (show_rc)
2436                 cYAML_print_tree(show_rc);
2437
2438         cYAML_free_tree(err_rc);
2439         cYAML_free_tree(show_rc);
2440
2441         return rc;
2442 }
2443
2444 static int set_value_helper(int argc, char **argv,
2445                             int (*cb)(int, bool, char*, int, int, struct cYAML**))
2446 {
2447         char *nid = NULL;
2448         long int healthv = -1;
2449         bool all = false;
2450         long int state = -1;
2451         int rc, opt;
2452         struct cYAML *err_rc = NULL;
2453         const char *const short_options = "t:n:s:a";
2454         static const struct option long_options[] = {
2455                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2456                 { .name = "health", .has_arg = required_argument, .val = 't' },
2457                 { .name = "state", .has_arg = required_argument, .val = 's' },
2458                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2459                 { .name = NULL }
2460         };
2461
2462         while ((opt = getopt_long(argc, argv, short_options,
2463                                   long_options, NULL)) != -1) {
2464                 switch (opt) {
2465                 case 'n':
2466                         nid = optarg;
2467                         break;
2468                 case 't':
2469                         if (parse_long(optarg, &healthv) != 0)
2470                                 healthv = -1;
2471                         break;
2472                 case 's':
2473                         if (parse_long(optarg, &state) != 0)
2474                                 state = -1;
2475                         break;
2476                 case 'a':
2477                         all = true;
2478                         break;
2479                 default:
2480                         return 0;
2481                 }
2482         }
2483
2484         rc = cb(healthv, all, nid, state, -1, &err_rc);
2485         if (rc != LUSTRE_CFG_RC_NO_ERR)
2486                 cYAML_print_tree2file(stderr, err_rc);
2487
2488         cYAML_free_tree(err_rc);
2489
2490         return rc;
2491 }
2492
2493 static int jt_set_ni_value(int argc, char **argv)
2494 {
2495         char *nid = NULL;
2496         long int healthv = -1, cpp = -1;
2497         bool all = false;
2498         int rc, opt;
2499         struct cYAML *err_rc = NULL;
2500
2501         const char *const short_options = "a:m:n:t:";
2502         static const struct option long_options[] = {
2503         { .name = "all",            .has_arg = no_argument,       .val = 'a' },
2504         { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2505         { .name = "nid",            .has_arg = required_argument, .val = 'n' },
2506         { .name = "health",         .has_arg = required_argument, .val = 't' },
2507         { .name = NULL } };
2508
2509         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2510         if (rc)
2511                 return rc;
2512
2513         while ((opt = getopt_long(argc, argv, short_options,
2514                                    long_options, NULL)) != -1) {
2515                 switch (opt) {
2516                 case 'a':
2517                         all = true;
2518                         break;
2519                 case 'm':
2520                         rc = parse_long(optarg, &cpp);
2521                         if (rc != 0) {
2522                                 /* ignore option */
2523                                 cpp = -1;
2524                                 continue;
2525                         }
2526                         break;
2527                 case 'n':
2528                         nid = optarg;
2529                         break;
2530                 case 't':
2531                         if (parse_long(optarg, &healthv) != 0) {
2532                                 /* ignore option */
2533                                 healthv = -1;
2534                                 continue;
2535                         }
2536                         break;
2537                 default:
2538                         return 0;
2539                 }
2540         }
2541
2542         if (cpp > -1)
2543                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
2544                                                           -1, &err_rc);
2545         if (healthv > -1)
2546                 rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
2547                                                    -1, &err_rc);
2548
2549         if (rc != LUSTRE_CFG_RC_NO_ERR)
2550                 cYAML_print_tree2file(stderr, err_rc);
2551
2552         cYAML_free_tree(err_rc);
2553
2554         return rc;
2555 }
2556
2557 static int yaml_lnet_peer_display(yaml_parser_t *reply, bool list_only)
2558 {
2559         yaml_emitter_t debug;
2560         int rc;
2561
2562         rc = yaml_emitter_initialize(&debug);
2563         if (rc == 0)
2564                 goto out_err;
2565
2566         yaml_emitter_set_indent(&debug, 6);
2567         yaml_emitter_set_output_file(&debug, stdout);
2568
2569         if (list_only) {
2570                 bool done = false;
2571
2572                 while (!done) {
2573                         yaml_event_t event;
2574                         char *value;
2575
2576                         rc = yaml_parser_parse(reply, &event);
2577                         if (rc == 0)
2578                                 goto report_reply_error;
2579
2580                         if (event.type != YAML_SCALAR_EVENT)
2581                                 goto merge_event;
2582
2583                         value = (char *)event.data.scalar.value;
2584                         if (strcmp(value, "peer") == 0) {
2585                                 yaml_event_delete(&event);
2586
2587                                 yaml_scalar_event_initialize(&event, NULL,
2588                                                              (yaml_char_t *)YAML_STR_TAG,
2589                                                              (yaml_char_t *)"peer list",
2590                                                              strlen("peer list"),
2591                                                              1, 0,
2592                                                              YAML_PLAIN_SCALAR_STYLE);
2593                         } else if (strcmp(value, "primary nid") == 0) {
2594                                 yaml_event_delete(&event);
2595
2596                                 yaml_scalar_event_initialize(&event, NULL,
2597                                                              (yaml_char_t *)YAML_STR_TAG,
2598                                                              (yaml_char_t *)"nid",
2599                                                              strlen("nid"),
2600                                                              1, 0,
2601                                                              YAML_PLAIN_SCALAR_STYLE);
2602                                 rc = yaml_emitter_emit(&debug, &event);
2603                                 if (rc == 0)
2604                                         break;
2605
2606                                 /* Now print NID address */
2607                                 rc = yaml_parser_parse(reply, &event);
2608                                 if (rc == 0)
2609                                         goto report_reply_error;
2610
2611                                 rc = yaml_emitter_emit(&debug, &event);
2612                                 if (rc == 0)
2613                                         break;
2614
2615                                 /* skip reset */
2616                                 while (event.type != YAML_MAPPING_END_EVENT) {
2617                                         rc = yaml_parser_parse(reply, &event);
2618                                         if (rc == 0)
2619                                                 goto report_reply_error;
2620                                 }
2621
2622                                 /* we can have map end, seq end, map end or
2623                                  * just map end event. If we see seq end event
2624                                  * then skip to next mapping end event
2625                                  */
2626                                 rc = yaml_parser_parse(reply, &event);
2627                                 if (rc == 0)
2628                                         goto report_reply_error;
2629
2630                                 if (event.type == YAML_SEQUENCE_END_EVENT) {
2631                                         yaml_event_delete(&event);
2632
2633                                         rc = yaml_parser_parse(reply, &event);
2634                                         if (rc == 0)
2635                                                 goto report_reply_error;
2636                                 }
2637                         }
2638 merge_event:
2639                         rc = yaml_emitter_emit(&debug, &event);
2640                         if (rc == 0)
2641                                 break;
2642
2643                         done = (event.type == YAML_DOCUMENT_END_EVENT);
2644                 }
2645         } else {
2646                 yaml_document_t errmsg;
2647
2648                 rc = yaml_parser_load(reply, &errmsg);
2649                 if (rc == 1)
2650                         rc = yaml_emitter_dump(&debug, &errmsg);
2651                 yaml_document_delete(&errmsg);
2652         }
2653 out_err:
2654         if (rc == 0)
2655                 yaml_emitter_log_error(&debug, stderr);
2656 report_reply_error:
2657         yaml_emitter_delete(&debug);
2658
2659         return rc;
2660 }
2661
2662 static int yaml_lnet_peer(char *prim_nid, char *nidstr, bool disable_mr,
2663                           int health_value, int state, bool list_only,
2664                           int version, int flags)
2665 {
2666         struct nl_sock *sk = NULL;
2667         const char *msg = NULL;
2668         yaml_emitter_t output;
2669         yaml_parser_t reply;
2670         yaml_event_t event;
2671         int rc;
2672
2673         /* Create Netlink emitter to send request to kernel */
2674         sk = nl_socket_alloc();
2675         if (!sk)
2676                 return -EOPNOTSUPP;
2677
2678         /* Setup parser to receive Netlink packets */
2679         rc = yaml_parser_initialize(&reply);
2680         if (rc == 0) {
2681                 nl_socket_free(sk);
2682                 return -EOPNOTSUPP;
2683         }
2684
2685         rc = yaml_parser_set_input_netlink(&reply, sk, false);
2686         if (rc == 0) {
2687                 msg = yaml_parser_get_reader_error(&reply);
2688                 goto free_reply;
2689         }
2690
2691         /* Create Netlink emitter to send request to kernel */
2692         rc = yaml_emitter_initialize(&output);
2693         if (rc == 0) {
2694                 msg = "failed to initialize emitter";
2695                 goto free_reply;
2696         }
2697
2698         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
2699                                              version, LNET_CMD_PEERS, flags);
2700         if (rc == 0)
2701                 goto emitter_error;
2702
2703         yaml_emitter_open(&output);
2704         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
2705         rc = yaml_emitter_emit(&output, &event);
2706         if (rc == 0)
2707                 goto emitter_error;
2708
2709         yaml_mapping_start_event_initialize(&event, NULL,
2710                                             (yaml_char_t *)YAML_MAP_TAG,
2711                                             1, YAML_ANY_MAPPING_STYLE);
2712         rc = yaml_emitter_emit(&output, &event);
2713         if (rc == 0)
2714                 goto emitter_error;
2715
2716         yaml_scalar_event_initialize(&event, NULL,
2717                                      (yaml_char_t *)YAML_STR_TAG,
2718                                      (yaml_char_t *)"peer",
2719                                      strlen("peer"), 1, 0,
2720                                      YAML_PLAIN_SCALAR_STYLE);
2721         rc = yaml_emitter_emit(&output, &event);
2722         if (rc == 0)
2723                 goto emitter_error;
2724
2725         if (prim_nid) {
2726                 yaml_sequence_start_event_initialize(&event, NULL,
2727                                                      (yaml_char_t *)YAML_SEQ_TAG,
2728                                                      1,
2729                                                      YAML_BLOCK_SEQUENCE_STYLE);
2730                 rc = yaml_emitter_emit(&output, &event);
2731                 if (rc == 0)
2732                         goto emitter_error;
2733
2734                 yaml_mapping_start_event_initialize(&event, NULL,
2735                                                     (yaml_char_t *)YAML_MAP_TAG,
2736                                                     1,
2737                                                     YAML_BLOCK_MAPPING_STYLE);
2738                 rc = yaml_emitter_emit(&output, &event);
2739                 if (rc == 0)
2740                         goto emitter_error;
2741
2742                 yaml_scalar_event_initialize(&event, NULL,
2743                                              (yaml_char_t *)YAML_STR_TAG,
2744                                              (yaml_char_t *)"primary nid",
2745                                              strlen("primary nid"), 1, 0,
2746                                              YAML_PLAIN_SCALAR_STYLE);
2747                 rc = yaml_emitter_emit(&output, &event);
2748                 if (rc == 0)
2749                         goto emitter_error;
2750
2751                 yaml_scalar_event_initialize(&event, NULL,
2752                                              (yaml_char_t *)YAML_STR_TAG,
2753                                              (yaml_char_t *)prim_nid,
2754                                              strlen(prim_nid), 1, 0,
2755                                              YAML_PLAIN_SCALAR_STYLE);
2756                 rc = yaml_emitter_emit(&output, &event);
2757                 if (rc == 0)
2758                         goto emitter_error;
2759
2760                 if (disable_mr) {
2761                         yaml_scalar_event_initialize(&event, NULL,
2762                                                      (yaml_char_t *)YAML_STR_TAG,
2763                                                      (yaml_char_t *)"Multi-Rail",
2764                                                      strlen("Multi-Rail"), 1, 0,
2765                                                      YAML_PLAIN_SCALAR_STYLE);
2766                         rc = yaml_emitter_emit(&output, &event);
2767                         if (rc == 0)
2768                                 goto emitter_error;
2769
2770                         yaml_scalar_event_initialize(&event, NULL,
2771                                                      (yaml_char_t *)YAML_BOOL_TAG,
2772                                                      (yaml_char_t *)"False",
2773                                                      strlen("False"), 1, 0,
2774                                                      YAML_PLAIN_SCALAR_STYLE);
2775                         rc = yaml_emitter_emit(&output, &event);
2776                         if (rc == 0)
2777                                 goto emitter_error;
2778                 }
2779
2780                 if (state != -1) {
2781                         char peer_state[INT_STRING_LEN];
2782
2783                         yaml_scalar_event_initialize(&event, NULL,
2784                                                      (yaml_char_t *)YAML_STR_TAG,
2785                                                      (yaml_char_t *)"peer state",
2786                                                      strlen("peer state"), 1, 0,
2787                                                      YAML_PLAIN_SCALAR_STYLE);
2788                         rc = yaml_emitter_emit(&output, &event);
2789                         if (rc == 0)
2790                                 goto emitter_error;
2791
2792                         snprintf(peer_state, sizeof(peer_state), "%d", state);
2793                         yaml_scalar_event_initialize(&event, NULL,
2794                                                      (yaml_char_t *)YAML_INT_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
2803                 if (!nidstr && health_value == -1)
2804                         goto skip_peer_nis;
2805
2806                 yaml_scalar_event_initialize(&event, NULL,
2807                                              (yaml_char_t *)YAML_STR_TAG,
2808                                              (yaml_char_t *)"peer ni",
2809                                              strlen("peer ni"), 1, 0,
2810                                              YAML_PLAIN_SCALAR_STYLE);
2811                 rc = yaml_emitter_emit(&output, &event);
2812                 if (rc == 0)
2813                         goto emitter_error;
2814
2815                 yaml_sequence_start_event_initialize(&event, NULL,
2816                                                      (yaml_char_t *)YAML_SEQ_TAG,
2817                                                      1, YAML_BLOCK_SEQUENCE_STYLE);
2818                 rc = yaml_emitter_emit(&output, &event);
2819                 if (rc == 0)
2820                         goto emitter_error;
2821
2822                 if (nidstr) {
2823                         struct nid_node head, *entry;
2824                         int count = 0;
2825
2826                         /* If we have LNET_ANY_NID and its NLM_F_REPLACE we
2827                          * treat it as the all flag case for lnetctl peer set
2828                          */
2829                         if (strcmp(nidstr, "<?>") == 0) {
2830                                 yaml_mapping_start_event_initialize(&event, NULL,
2831                                                                     (yaml_char_t *)YAML_MAP_TAG,
2832                                                                     1, YAML_BLOCK_MAPPING_STYLE);
2833                                 rc = yaml_emitter_emit(&output, &event);
2834                                 if (rc == 0)
2835                                         goto emitter_error;
2836
2837                                 yaml_scalar_event_initialize(&event, NULL,
2838                                                              (yaml_char_t *)YAML_STR_TAG,
2839                                                              (yaml_char_t *)"nid",
2840                                                              strlen("nid"), 1, 0,
2841                                                              YAML_PLAIN_SCALAR_STYLE);
2842                                 rc = yaml_emitter_emit(&output, &event);
2843                                 if (rc == 0)
2844                                         goto emitter_error;
2845
2846                                 yaml_scalar_event_initialize(&event, NULL,
2847                                                              (yaml_char_t *)YAML_STR_TAG,
2848                                                              (yaml_char_t *)nidstr,
2849                                                              strlen(nidstr), 1, 0,
2850                                                      YAML_PLAIN_SCALAR_STYLE);
2851                                 rc = yaml_emitter_emit(&output, &event);
2852                                 if (rc == 0)
2853                                         goto emitter_error;
2854
2855                                 yaml_mapping_end_event_initialize(&event);
2856                                 rc = yaml_emitter_emit(&output, &event);
2857                                 if (rc == 0)
2858                                         goto emitter_error;
2859
2860                                 goto handle_health;
2861                         }
2862
2863                         NL_INIT_LIST_HEAD(&head.children);
2864                         nl_init_list_head(&head.list);
2865                         rc = lustre_lnet_parse_nid_range(&head, nidstr, &msg);
2866                         if (rc < 0) {
2867                                 fprintf(stdout, "can't parse nidrange: \"%s\"\n", nidstr);
2868                                 lustre_lnet_free_list(&head);
2869                                 yaml_emitter_delete(&output);
2870                                 errno = rc;
2871                                 rc = 0;
2872                                 goto free_reply;
2873                         }
2874
2875                         if (nl_list_empty(&head.children)) {
2876                                 lustre_lnet_free_list(&head);
2877                                 yaml_emitter_delete(&output);
2878                                 msg = "Unable to parse nidlist: did not expand to any nids";
2879                                 errno = -ENOENT;
2880                                 rc = 0;
2881                                 goto free_reply;
2882                         }
2883                         rc = 1; /* one means its working */
2884
2885                         nl_list_for_each_entry(entry, &head.children, list) {
2886                                 char *nid = entry->nidstr;
2887
2888                                 if (count++ > LNET_MAX_NIDS_PER_PEER) {
2889                                         lustre_lnet_free_list(&head);
2890                                         yaml_emitter_delete(&output);
2891                                         msg = "Unable to parse nidlist: specifies more NIDs than allowed";
2892                                         errno = -E2BIG;
2893                                         rc = 0;
2894                                         goto free_reply;
2895                                 }
2896
2897                                 yaml_mapping_start_event_initialize(&event, NULL,
2898                                                                     (yaml_char_t *)YAML_MAP_TAG,
2899                                                                     1, YAML_BLOCK_MAPPING_STYLE);
2900                                 rc = yaml_emitter_emit(&output, &event);
2901                                 if (rc == 0)
2902                                         goto emitter_error;
2903
2904                                 yaml_scalar_event_initialize(&event, NULL,
2905                                                              (yaml_char_t *)YAML_STR_TAG,
2906                                                              (yaml_char_t *)"nid",
2907                                                              strlen("nid"), 1, 0,
2908                                                              YAML_PLAIN_SCALAR_STYLE);
2909                                 rc = yaml_emitter_emit(&output, &event);
2910                                 if (rc == 0)
2911                                         goto emitter_error;
2912
2913                                 yaml_scalar_event_initialize(&event, NULL,
2914                                                              (yaml_char_t *)YAML_STR_TAG,
2915                                                              (yaml_char_t *)nid,
2916                                                              strlen(nid), 1, 0,
2917                                                      YAML_PLAIN_SCALAR_STYLE);
2918                                 rc = yaml_emitter_emit(&output, &event);
2919                                 if (rc == 0)
2920                                         goto emitter_error;
2921
2922                                 yaml_mapping_end_event_initialize(&event);
2923                                 rc = yaml_emitter_emit(&output, &event);
2924                                 if (rc == 0)
2925                                         goto emitter_error;
2926                         }
2927                         lustre_lnet_free_list(&head);
2928                 }
2929 handle_health:
2930                 if (health_value >= 0) {
2931                         char health[INT_STRING_LEN];
2932
2933                         /* Create the mapping for 'health stats'. The value field for
2934                          * the mapping is not provided so its treated as a empty string.
2935                          */
2936                         yaml_mapping_start_event_initialize(&event, NULL,
2937                                                             (yaml_char_t *)YAML_MAP_TAG,
2938                                                             1, YAML_BLOCK_MAPPING_STYLE);
2939                         rc = yaml_emitter_emit(&output, &event);
2940                         if (rc == 0)
2941                                 goto emitter_error;
2942
2943                         yaml_scalar_event_initialize(&event, NULL,
2944                                                      (yaml_char_t *)YAML_STR_TAG,
2945                                                      (yaml_char_t *)"health stats",
2946                                                      strlen("health stats"), 1, 0,
2947                                                      YAML_PLAIN_SCALAR_STYLE);
2948                         rc = yaml_emitter_emit(&output, &event);
2949                         if (rc == 0)
2950                                 goto emitter_error;
2951
2952                         /* Setup all mappings for data related to the 'health stats' */
2953                         yaml_mapping_start_event_initialize(&event, NULL,
2954                                                             (yaml_char_t *)YAML_MAP_TAG,
2955                                                             1, YAML_BLOCK_MAPPING_STYLE);
2956                         rc = yaml_emitter_emit(&output, &event);
2957                         if (rc == 0)
2958                                 goto emitter_error;
2959
2960                         yaml_scalar_event_initialize(&event, NULL,
2961                                                      (yaml_char_t *)YAML_STR_TAG,
2962                                                      (yaml_char_t *)"health value",
2963                                                      strlen("health value"), 1, 0,
2964                                                      YAML_PLAIN_SCALAR_STYLE);
2965                         rc = yaml_emitter_emit(&output, &event);
2966                         if (rc == 0)
2967                                 goto emitter_error;
2968
2969                         snprintf(health, sizeof(health), "%d", health_value);
2970                         yaml_scalar_event_initialize(&event, NULL,
2971                                                      (yaml_char_t *)YAML_INT_TAG,
2972                                                      (yaml_char_t *)health,
2973                                                      strlen(health), 1, 0,
2974                                                      YAML_PLAIN_SCALAR_STYLE);
2975                         rc = yaml_emitter_emit(&output, &event);
2976                         if (rc == 0)
2977                                 goto emitter_error;
2978
2979                         yaml_mapping_end_event_initialize(&event);
2980                         rc = yaml_emitter_emit(&output, &event);
2981                         if (rc == 0)
2982                                 goto emitter_error;
2983
2984                         yaml_mapping_end_event_initialize(&event);
2985                         rc = yaml_emitter_emit(&output, &event);
2986                         if (rc == 0)
2987                                 goto emitter_error;
2988                 }
2989
2990                 yaml_sequence_end_event_initialize(&event);
2991                 rc = yaml_emitter_emit(&output, &event);
2992                 if (rc == 0)
2993                         goto emitter_error;
2994 skip_peer_nis:
2995                 yaml_mapping_end_event_initialize(&event);
2996                 rc = yaml_emitter_emit(&output, &event);
2997                 if (rc == 0)
2998                         goto emitter_error;
2999
3000                 yaml_sequence_end_event_initialize(&event);
3001                 rc = yaml_emitter_emit(&output, &event);
3002                 if (rc == 0)
3003                         goto emitter_error;
3004         } else {
3005                 yaml_scalar_event_initialize(&event, NULL,
3006                                              (yaml_char_t *)YAML_STR_TAG,
3007                                              (yaml_char_t *)"",
3008                                              strlen(""), 1, 0,
3009                                              YAML_PLAIN_SCALAR_STYLE);
3010                 rc = yaml_emitter_emit(&output, &event);
3011                 if (rc == 0)
3012                         goto emitter_error;
3013         }
3014
3015         yaml_mapping_end_event_initialize(&event);
3016         rc = yaml_emitter_emit(&output, &event);
3017         if (rc == 0)
3018                 goto emitter_error;
3019
3020         yaml_document_end_event_initialize(&event, 0);
3021         rc = yaml_emitter_emit(&output, &event);
3022         if (rc == 0)
3023                 goto emitter_error;
3024
3025         rc = yaml_emitter_close(&output);
3026 emitter_error:
3027         if (rc == 0) {
3028                 yaml_emitter_log_error(&output, stderr);
3029                 rc = -EINVAL;
3030         } else {
3031                 rc = yaml_lnet_peer_display(&reply, list_only);
3032                 if (rc == 0) {
3033                         msg = yaml_parser_get_reader_error(&reply);
3034                         /* If we didn't find any peers just be silent */
3035                         if (msg && strcmp(msg, "No peers found") == 0)
3036                                 rc = 1;
3037                 }
3038
3039         }
3040         yaml_emitter_delete(&output);
3041 free_reply:
3042         if (rc == 0) {
3043                 yaml_lnet_print_error(flags, "peer", msg);
3044                 rc = -EINVAL;
3045         }
3046         yaml_parser_delete(&reply);
3047         nl_socket_free(sk);
3048
3049         return rc == 1 ? 0 : rc;
3050 }
3051
3052 int yaml_lnet_config_peer_ni_healthv(int healthv, bool all, char *lpni_nid,
3053                                      int state, int seq_no, struct cYAML **err_rc)
3054 {
3055         int rc;
3056
3057         rc = yaml_lnet_peer(lpni_nid ? lpni_nid : "<?>", all ? "<?>" : NULL,
3058                             false, healthv, state, false, LNET_GENL_VERSION,
3059                             NLM_F_REPLACE);
3060         if (rc <= 0) {
3061                 if (rc == -EOPNOTSUPP)
3062                         goto old_api;
3063                 return rc;
3064         }
3065 old_api:
3066         if (state == -1)
3067                 rc = lustre_lnet_config_peer_ni_healthv(healthv, all, lpni_nid,
3068                                                         seq_no, err_rc);
3069         else
3070                 rc = lustre_lnet_set_peer_state(state, lpni_nid, -1, err_rc);
3071         if (rc != LUSTRE_CFG_RC_NO_ERR)
3072                 cYAML_print_tree2file(stderr, *err_rc);
3073
3074         cYAML_free_tree(*err_rc);
3075
3076         return rc;
3077 }
3078
3079 static int jt_set_peer_ni_value(int argc, char **argv)
3080 {
3081         int rc = check_cmd(peer_cmds, "peer", "set", 0, argc, argv);
3082
3083         if (rc < 0)
3084                 return rc;
3085
3086         return set_value_helper(argc, argv, yaml_lnet_config_peer_ni_healthv);
3087 }
3088
3089 static int jt_show_recovery(int argc, char **argv)
3090 {
3091         int rc, opt;
3092         struct cYAML *err_rc = NULL, *show_rc = NULL;
3093         const char *const short_options = "lp";
3094         static const struct option long_options[] = {
3095                 { .name = "local", .has_arg = no_argument, .val = 'l' },
3096                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
3097                 { .name = NULL } };
3098
3099         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
3100         if (rc)
3101                 return rc;
3102
3103         while ((opt = getopt_long(argc, argv, short_options,
3104                                    long_options, NULL)) != -1) {
3105                 switch (opt) {
3106                 case 'l':
3107                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
3108                         break;
3109                 case 'p':
3110                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
3111                         break;
3112                 default:
3113                         return 0;
3114                 }
3115         }
3116
3117         if (rc != LUSTRE_CFG_RC_NO_ERR)
3118                 cYAML_print_tree2file(stderr, err_rc);
3119         else if (show_rc)
3120                 cYAML_print_tree(show_rc);
3121
3122         cYAML_free_tree(err_rc);
3123         cYAML_free_tree(show_rc);
3124
3125         return rc;
3126 }
3127
3128 static int jt_show_peer_debug_info(int argc, char **argv)
3129 {
3130         int rc, opt;
3131         struct cYAML *err_rc = NULL;
3132         char *peer_nid = optarg;
3133         const char *const short_opts = "k";
3134         const struct option long_opts[] = {
3135         { .name = "nid", .has_arg = required_argument, .val = 'k' },
3136         { .name = NULL } };
3137
3138         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
3139
3140         if (rc)
3141                 return rc;
3142
3143         while ((opt = getopt_long(argc, argv, short_opts,
3144                                    long_opts, NULL)) != -1) {
3145                 switch (opt) {
3146                 case 'k':
3147                         peer_nid = optarg;
3148                         break;
3149                 default:
3150                         return 0;
3151                 }
3152         }
3153
3154         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
3155
3156         if (rc != LUSTRE_CFG_RC_NO_ERR)
3157                 cYAML_print_tree2file(stderr, err_rc);
3158
3159         cYAML_free_tree(err_rc);
3160
3161         return rc;
3162 }
3163
3164 static int jt_show_net(int argc, char **argv)
3165 {
3166         char *network = NULL;
3167         int rc, opt;
3168         struct cYAML *err_rc = NULL, *show_rc = NULL;
3169         long int detail = 0;
3170         const char *const short_options = "n:v";
3171         static const struct option long_options[] = {
3172                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
3173                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
3174                 { .name = NULL } };
3175
3176         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
3177         if (rc)
3178                 return rc;
3179
3180         while ((opt = getopt_long(argc, argv, short_options,
3181                                    long_options, NULL)) != -1) {
3182                 switch (opt) {
3183                 case 'n':
3184                         network = optarg;
3185                         break;
3186                 case 'v':
3187                         if ((!optarg) && (argv[optind] != NULL) &&
3188                             (argv[optind][0] != '-')) {
3189                                 if (parse_long(argv[optind++], &detail) != 0)
3190                                         detail = 1;
3191                         } else {
3192                                 detail = 1;
3193                         }
3194                         break;
3195                 case '?':
3196                         print_help(net_cmds, "net", "show");
3197                 default:
3198                         return 0;
3199                 }
3200         }
3201
3202         rc = yaml_lnet_config_ni(network, NULL, NULL, NULL, NULL,
3203                                  detail, NLM_F_DUMP);
3204         if (rc <= 0) {
3205                 if (rc != -EOPNOTSUPP)
3206                         return rc;
3207         }
3208
3209         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
3210                                   false);
3211
3212         if (rc != LUSTRE_CFG_RC_NO_ERR)
3213                 cYAML_print_tree2file(stderr, err_rc);
3214         else if (show_rc)
3215                 cYAML_print_tree(show_rc);
3216
3217         cYAML_free_tree(err_rc);
3218         cYAML_free_tree(show_rc);
3219
3220         return rc;
3221 }
3222
3223 static int jt_show_routing(int argc, char **argv)
3224 {
3225         struct cYAML *err_rc = NULL, *show_rc = NULL;
3226         int rc;
3227
3228         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
3229         if (rc)
3230                 return rc;
3231
3232         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
3233
3234         if (rc != LUSTRE_CFG_RC_NO_ERR)
3235                 cYAML_print_tree2file(stderr, err_rc);
3236         else if (show_rc)
3237                 cYAML_print_tree(show_rc);
3238
3239         cYAML_free_tree(err_rc);
3240         cYAML_free_tree(show_rc);
3241
3242         return rc;
3243 }
3244
3245 static int jt_show_stats(int argc, char **argv)
3246 {
3247         int rc;
3248         struct cYAML *show_rc = NULL, *err_rc = NULL;
3249
3250         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
3251         if (rc)
3252                 return rc;
3253
3254         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
3255
3256         if (rc != LUSTRE_CFG_RC_NO_ERR)
3257                 cYAML_print_tree2file(stderr, err_rc);
3258         else if (show_rc)
3259                 cYAML_print_tree(show_rc);
3260
3261         cYAML_free_tree(err_rc);
3262         cYAML_free_tree(show_rc);
3263
3264         return rc;
3265 }
3266
3267 static int jt_show_udsp(int argc, char **argv)
3268 {
3269         long int idx = -1;
3270         int rc, opt;
3271         struct cYAML *err_rc = NULL, *show_rc = NULL;
3272
3273         const char *const short_options = "i:";
3274         static const struct option long_options[] = {
3275                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
3276                 { .name = NULL }
3277         };
3278
3279         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
3280         if (rc)
3281                 return rc;
3282
3283         while ((opt = getopt_long(argc, argv, short_options,
3284                                    long_options, NULL)) != -1) {
3285                 switch (opt) {
3286                 case 'i':
3287                         rc = parse_long(optarg, &idx);
3288                         if (rc != 0 || idx < -1) {
3289                                 printf("Invalid index \"%s\"\n", optarg);
3290                                 return -EINVAL;
3291                         }
3292                         break;
3293                 case '?':
3294                         print_help(net_cmds, "net", "show");
3295                 default:
3296                         return 0;
3297                 }
3298         }
3299
3300         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
3301
3302         if (rc != LUSTRE_CFG_RC_NO_ERR)
3303                 cYAML_print_tree2file(stderr, err_rc);
3304         else if (show_rc)
3305                 cYAML_print_tree(show_rc);
3306
3307         cYAML_free_tree(err_rc);
3308         cYAML_free_tree(show_rc);
3309
3310         return rc;
3311 }
3312
3313 static int jt_show_global(int argc, char **argv)
3314 {
3315         int rc;
3316         struct cYAML *show_rc = NULL, *err_rc = NULL;
3317
3318         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
3319         if (rc)
3320                 return rc;
3321
3322         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3323         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3324                 cYAML_print_tree2file(stderr, err_rc);
3325                 goto out;
3326         }
3327
3328         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3329         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3330                 cYAML_print_tree2file(stderr, err_rc);
3331                 goto out;
3332         }
3333
3334         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3335         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3336                 cYAML_print_tree2file(stderr, err_rc);
3337                 goto out;
3338         }
3339
3340         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3341         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3342                 cYAML_print_tree2file(stderr, err_rc);
3343                 goto out;
3344         }
3345
3346         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3347         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3348                 cYAML_print_tree2file(stderr, err_rc);
3349                 goto out;
3350         }
3351
3352         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3353         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3354                 cYAML_print_tree2file(stderr, err_rc);
3355                 goto out;
3356         }
3357
3358         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3359         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3360                 cYAML_print_tree2file(stderr, err_rc);
3361                 goto out;
3362         }
3363
3364         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3365         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3366                 cYAML_print_tree2file(stderr, err_rc);
3367                 goto out;
3368         }
3369
3370         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3371         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3372                 cYAML_print_tree2file(stderr, err_rc);
3373                 goto out;
3374         }
3375
3376         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3377         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3378                 cYAML_print_tree2file(stderr, err_rc);
3379                 goto out;
3380         }
3381
3382         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3383         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3384                 cYAML_print_tree2file(stderr, err_rc);
3385                 goto out;
3386         }
3387
3388         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3389         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3390                 cYAML_print_tree2file(stderr, err_rc);
3391                 goto out;
3392         }
3393
3394         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3395         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3396                 cYAML_print_tree2file(stderr, err_rc);
3397                 goto out;
3398         }
3399
3400         if (show_rc)
3401                 cYAML_print_tree(show_rc);
3402
3403 out:
3404         cYAML_free_tree(err_rc);
3405         cYAML_free_tree(show_rc);
3406
3407         return rc;
3408 }
3409
3410 static int jt_lnet(int argc, char **argv)
3411 {
3412         int rc;
3413
3414         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
3415         if (rc)
3416                 return rc;
3417
3418         return cfs_parser(argc, argv, lnet_cmds);
3419 }
3420
3421 static int jt_route(int argc, char **argv)
3422 {
3423         int rc;
3424
3425         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
3426         if (rc)
3427                 return rc;
3428
3429         return cfs_parser(argc, argv, route_cmds);
3430 }
3431
3432 static int jt_net(int argc, char **argv)
3433 {
3434         int rc;
3435
3436         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
3437         if (rc)
3438                 return rc;
3439
3440         return cfs_parser(argc, argv, net_cmds);
3441 }
3442
3443 static int jt_routing(int argc, char **argv)
3444 {
3445         int rc;
3446
3447         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
3448         if (rc)
3449                 return rc;
3450
3451         return cfs_parser(argc, argv, routing_cmds);
3452 }
3453
3454 static int jt_stats(int argc, char **argv)
3455 {
3456         int rc;
3457
3458         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
3459         if (rc)
3460                 return rc;
3461
3462         return cfs_parser(argc, argv, stats_cmds);
3463 }
3464
3465 static int jt_debug(int argc, char **argv)
3466 {
3467         int rc;
3468
3469         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
3470         if (rc)
3471                 return rc;
3472
3473         return cfs_parser(argc, argv, debug_cmds);
3474 }
3475
3476 static int jt_global(int argc, char **argv)
3477 {
3478         int rc;
3479
3480         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
3481         if (rc)
3482                 return rc;
3483
3484         return cfs_parser(argc, argv, global_cmds);
3485 }
3486
3487 static int jt_peers(int argc, char **argv)
3488 {
3489         int rc;
3490
3491         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
3492         if (rc)
3493                 return rc;
3494
3495         return cfs_parser(argc, argv, peer_cmds);
3496 }
3497
3498 static int jt_set(int argc, char **argv)
3499 {
3500         int rc;
3501
3502         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
3503         if (rc)
3504                 return rc;
3505
3506         return cfs_parser(argc, argv, set_cmds);
3507 }
3508
3509 static int jt_udsp(int argc, char **argv)
3510 {
3511         int rc;
3512
3513         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
3514         if (rc)
3515                 return rc;
3516
3517         return cfs_parser(argc, argv, udsp_cmds);
3518 }
3519
3520 static int jt_import(int argc, char **argv)
3521 {
3522         char *file = NULL;
3523         struct cYAML *err_rc = NULL;
3524         struct cYAML *show_rc = NULL;
3525         int rc = 0, return_rc = 0, opt, opt_found = 0;
3526         char cmd = 'a';
3527
3528         const char *const short_options = "adseh";
3529         static const struct option long_options[] = {
3530                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
3531                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
3532                 { .name = "show", .has_arg = no_argument, .val = 's' },
3533                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
3534                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3535                 { .name = NULL } };
3536
3537         while ((opt = getopt_long(argc, argv, short_options,
3538                                    long_options, NULL)) != -1) {
3539                 opt_found = 1;
3540                 switch (opt) {
3541                 case 'a':
3542                         cmd = opt;
3543                         break;
3544                 case 'd':
3545                 case 's':
3546                         cmd = opt;
3547                         break;
3548                 case 'e':
3549                         cmd = opt;
3550                         break;
3551                 case 'h':
3552                         printf("import FILE\n"
3553                                "import < FILE : import a file\n"
3554                                "\t--add: add configuration\n"
3555                                "\t--del: delete configuration\n"
3556                                "\t--show: show configuration\n"
3557                                "\t--exec: execute command\n"
3558                                "\t--help: display this help\n"
3559                                "If no command option is given then --add"
3560                                " is assumed by default\n");
3561                         return 0;
3562                 default:
3563                         return 0;
3564                 }
3565         }
3566
3567         /* grab the file name if one exists */
3568         if (opt_found && argc == 3)
3569                 file = argv[2];
3570         else if (!opt_found && argc == 2)
3571                 file = argv[1];
3572
3573         switch (cmd) {
3574         case 'a':
3575                 rc = lustre_yaml_config(file, &err_rc);
3576                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3577                 cYAML_print_tree(show_rc);
3578                 cYAML_free_tree(show_rc);
3579                 break;
3580         case 'd':
3581                 rc = lustre_yaml_del(file, &err_rc);
3582                 break;
3583         case 's':
3584                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
3585                 cYAML_print_tree(show_rc);
3586                 cYAML_free_tree(show_rc);
3587                 break;
3588         case 'e':
3589                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3590                 cYAML_print_tree(show_rc);
3591                 cYAML_free_tree(show_rc);
3592                 break;
3593         }
3594
3595         if (rc || return_rc) {
3596                 cYAML_print_tree2file(stderr, err_rc);
3597                 cYAML_free_tree(err_rc);
3598         }
3599
3600         return rc;
3601 }
3602
3603 static int jt_export(int argc, char **argv)
3604 {
3605         struct cYAML *show_rc = NULL;
3606         struct cYAML *err_rc = NULL;
3607         int rc;
3608         FILE *f = NULL;
3609         int opt;
3610         bool backup = false;
3611         char *file = NULL;
3612
3613         const char *const short_options = "bh";
3614         static const struct option long_options[] = {
3615                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
3616                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3617                 { .name = NULL } };
3618
3619         while ((opt = getopt_long(argc, argv, short_options,
3620                                    long_options, NULL)) != -1) {
3621                 switch (opt) {
3622                 case 'b':
3623                         backup = true;
3624                         break;
3625                 case 'h':
3626                 default:
3627                         printf("export > FILE.yaml : export configuration\n"
3628                                "\t--backup: export only what's necessary for reconfig\n"
3629                                "\t--help: display this help\n");
3630                         return 0;
3631                 }
3632         }
3633
3634         if (backup && argc >= 3)
3635                 file = argv[2];
3636         else if (!backup && argc >= 2)
3637                 file = argv[1];
3638         else
3639                 f = stdout;
3640
3641         if (file) {
3642                 f = fopen(file, "w");
3643                 if (f == NULL)
3644                         return -1;
3645         }
3646
3647         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
3648         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3649                 cYAML_print_tree2file(stderr, err_rc);
3650                 cYAML_free_tree(err_rc);
3651                 err_rc = NULL;
3652         }
3653
3654         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
3655                                     &err_rc, backup);
3656         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3657                 cYAML_print_tree2file(stderr, err_rc);
3658                 cYAML_free_tree(err_rc);
3659                 err_rc = NULL;
3660         }
3661
3662         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
3663         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3664                 cYAML_print_tree2file(stderr, err_rc);
3665                 cYAML_free_tree(err_rc);
3666                 err_rc = NULL;
3667         }
3668
3669         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
3670         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3671                 cYAML_print_tree2file(stderr, err_rc);
3672                 cYAML_free_tree(err_rc);
3673                 err_rc = NULL;
3674         }
3675
3676         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3677         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3678                 cYAML_print_tree2file(stderr, err_rc);
3679                 cYAML_free_tree(err_rc);
3680                 err_rc = NULL;
3681         }
3682
3683         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3684         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3685                 cYAML_print_tree2file(stderr, err_rc);
3686                 cYAML_free_tree(err_rc);
3687                 err_rc = NULL;
3688         }
3689
3690         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3691         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3692                 cYAML_print_tree2file(stderr, err_rc);
3693                 cYAML_free_tree(err_rc);
3694                 err_rc = NULL;
3695         }
3696
3697         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3698         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3699                 cYAML_print_tree2file(stderr, err_rc);
3700                 cYAML_free_tree(err_rc);
3701                 err_rc = NULL;
3702         }
3703
3704         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3705         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3706                 cYAML_print_tree2file(stderr, err_rc);
3707                 err_rc = NULL;
3708         }
3709
3710         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3711         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3712                 cYAML_print_tree2file(stderr, err_rc);
3713                 err_rc = NULL;
3714         }
3715
3716         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3717         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3718                 cYAML_print_tree2file(stderr, err_rc);
3719                 err_rc = NULL;
3720         }
3721
3722         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3723         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3724                 cYAML_print_tree2file(stderr, err_rc);
3725                 err_rc = NULL;
3726         }
3727
3728         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3729         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3730                 cYAML_print_tree2file(stderr, err_rc);
3731                 err_rc = NULL;
3732         }
3733
3734         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3735         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3736                 cYAML_print_tree2file(stderr, err_rc);
3737                 err_rc = NULL;
3738         }
3739
3740         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3741         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3742                 cYAML_print_tree2file(stderr, err_rc);
3743                 cYAML_free_tree(err_rc);
3744                 err_rc = NULL;
3745         }
3746
3747         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3748         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3749                 cYAML_print_tree2file(stderr, err_rc);
3750                 cYAML_free_tree(err_rc);
3751                 err_rc = NULL;
3752         }
3753
3754         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3755         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3756                 cYAML_print_tree2file(stderr, err_rc);
3757                 cYAML_free_tree(err_rc);
3758                 err_rc = NULL;
3759         }
3760
3761         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
3762         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3763                 cYAML_print_tree2file(stderr, err_rc);
3764                 cYAML_free_tree(err_rc);
3765                 err_rc = NULL;
3766         }
3767
3768         if (show_rc != NULL) {
3769                 cYAML_print_tree2file(f, show_rc);
3770                 cYAML_free_tree(show_rc);
3771         }
3772
3773         if (argc >= 2)
3774                 fclose(f);
3775
3776         return 0;
3777 }
3778
3779 static int jt_peer_nid_common(int argc, char **argv, int cmd)
3780 {
3781         int flags = cmd == LNETCTL_ADD_CMD ? NLM_F_CREATE : 0;
3782         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
3783         bool is_mr = true;
3784         char *prim_nid = NULL, *nidstr = NULL;
3785         char err_str[LNET_MAX_STR_LEN] = "Error";
3786         struct cYAML *err_rc = NULL;
3787         int force_lock = 0;
3788         const char *const short_opts = "k:m:n:f:l";
3789         const struct option long_opts[] = {
3790         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
3791         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
3792         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3793         { .name = "force",      .has_arg = no_argument,         .val = 'f' },
3794         { .name = "lock_prim",  .has_arg = no_argument,         .val = 'l' },
3795         { .name = NULL } };
3796
3797         rc = check_cmd(peer_cmds, "peer",
3798                        cmd == LNETCTL_ADD_CMD ? "add" : "del", 2, argc, argv);
3799         if (rc)
3800                 return rc;
3801
3802         while ((opt = getopt_long(argc, argv, short_opts,
3803                                   long_opts, NULL)) != -1) {
3804                 switch (opt) {
3805                 case 'k':
3806                         prim_nid = optarg;
3807                         break;
3808                 case 'n':
3809                         nidstr = optarg;
3810                         break;
3811                 case 'm':
3812                         if (cmd == LNETCTL_DEL_CMD) {
3813                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3814                                 snprintf(err_str, LNET_MAX_STR_LEN,
3815                                          "Unrecognized option '-%c'", opt);
3816                                 goto build_error;
3817                         }
3818                         is_mr = false;
3819                         break;
3820                 case 'f':
3821                         if (cmd == LNETCTL_ADD_CMD) {
3822                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3823                                 snprintf(err_str, LNET_MAX_STR_LEN,
3824                                          "Unrecognized option '-%c'", opt);
3825                         }
3826                         force_lock = 1;
3827                         flags |= NLM_F_EXCL;
3828                         break;
3829                 case 'l':
3830                         if (cmd == LNETCTL_DEL_CMD) {
3831                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3832                                 snprintf(err_str, LNET_MAX_STR_LEN,
3833                                          "Unrecognized option '-%c'", opt);
3834                         }
3835                         force_lock = 1;
3836                         flags |= NLM_F_EXCL;
3837                         break;
3838                 case '?':
3839                         print_help(peer_cmds, "peer",
3840                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
3841                 default:
3842                         return 0;
3843                 }
3844         }
3845
3846         rc = yaml_lnet_peer(prim_nid, nidstr, !is_mr, -1, -1, false,
3847                             LNET_GENL_VERSION, flags);
3848         if (rc <= 0) {
3849                 if (rc == -EOPNOTSUPP)
3850                         goto old_api;
3851                 return rc;
3852         }
3853 old_api:
3854         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
3855                                      force_lock, -1, &err_rc);
3856         if (rc != LUSTRE_CFG_RC_NO_ERR)
3857                 goto out;
3858
3859 build_error:
3860         cYAML_build_error(rc, -1, "peer",
3861                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
3862                           err_str, &err_rc);
3863
3864 out:
3865         if (rc != LUSTRE_CFG_RC_NO_ERR)
3866                 cYAML_print_tree2file(stderr, err_rc);
3867
3868         cYAML_free_tree(err_rc);
3869
3870         return rc;
3871 }
3872
3873 static int jt_add_peer_nid(int argc, char **argv)
3874 {
3875         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
3876 }
3877
3878 static int jt_del_peer_nid(int argc, char **argv)
3879 {
3880         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
3881 }
3882
3883 static int jt_show_peer(int argc, char **argv)
3884 {
3885         char *nid = NULL;
3886         int rc, opt;
3887         struct cYAML *err_rc = NULL, *show_rc = NULL;
3888         long int detail = 0;
3889         const char *const short_opts = "hn:v::";
3890         const struct option long_opts[] = {
3891                 { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3892                 { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3893                 { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
3894                 { .name = NULL }
3895         };
3896
3897         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
3898         if (rc)
3899                 return rc;
3900
3901         while ((opt = getopt_long(argc, argv, short_opts,
3902                                   long_opts, NULL)) != -1) {
3903                 switch (opt) {
3904                 case 'n':
3905                         nid = optarg;
3906                         break;
3907                 case 'v':
3908                         if ((!optarg) && (argv[optind] != NULL) &&
3909                             (argv[optind][0] != '-')) {
3910                                 if (parse_long(argv[optind++], &detail) != 0)
3911                                         detail = 1;
3912                         } else {
3913                                 detail = 1;
3914                         }
3915                         break;
3916                 case '?':
3917                         print_help(peer_cmds, "peer", "show");
3918                 default:
3919                         return 0;
3920                 }
3921         }
3922
3923         rc = yaml_lnet_peer(nid, NULL, false, -1, -1, false, detail,
3924                             NLM_F_DUMP);
3925         if (rc <= 0) {
3926                 if (rc == -EOPNOTSUPP)
3927                         goto old_api;
3928                 return rc;
3929         }
3930 old_api:
3931         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
3932                                    false);
3933
3934         if (rc != LUSTRE_CFG_RC_NO_ERR)
3935                 cYAML_print_tree2file(stderr, err_rc);
3936         else if (show_rc)
3937                 cYAML_print_tree(show_rc);
3938
3939         cYAML_free_tree(err_rc);
3940         cYAML_free_tree(show_rc);
3941
3942         return rc;
3943 }
3944
3945 static int jt_list_peer(int argc, char **argv)
3946 {
3947         int rc;
3948         struct cYAML *err_rc = NULL, *list_rc = NULL;
3949
3950         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
3951         if (rc)
3952                 return rc;
3953
3954         rc = yaml_lnet_peer(NULL, NULL, false, -1, -1, true, 0, NLM_F_DUMP);
3955         if (rc <= 0) {
3956                 if (rc == -EOPNOTSUPP)
3957                         goto old_api;
3958                 return rc;
3959         }
3960 old_api:
3961         if (rc != LUSTRE_CFG_RC_NO_ERR)
3962                 cYAML_print_tree2file(stderr, err_rc);
3963         else if (list_rc)
3964                 cYAML_print_tree(list_rc);
3965
3966         cYAML_free_tree(err_rc);
3967         cYAML_free_tree(list_rc);
3968
3969         return rc;
3970 }
3971
3972 static int jt_ping(int argc, char **argv)
3973 {
3974         struct cYAML *err_rc = NULL;
3975         struct cYAML *show_rc = NULL;
3976         int timeout = 1000;
3977         int rc = 0, opt;
3978         char *src_nidstr = NULL;
3979
3980         const char *const short_options = "hs:t:";
3981         const struct option long_options[] = {
3982         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3983         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
3984         { .name = "source",     .has_arg = required_argument,   .val = 's' },
3985         { .name = NULL } };
3986
3987         while ((opt = getopt_long(argc, argv, short_options,
3988                                   long_options, NULL)) != -1) {
3989                 switch (opt) {
3990                 case 's':
3991                         src_nidstr = optarg;
3992                         break;
3993                 case 't':
3994                         timeout = 1000 * atol(optarg);
3995                         break;
3996                 case 'h':
3997                         printf("ping nid[,nid,...]\n"
3998                                "\t --source: source nid\n"
3999                                "\t --timeout: ping timeout\n"
4000                                "\t --help: display this help\n");
4001                         return 0;
4002                 default:
4003                         return 0;
4004                 }
4005         }
4006
4007         for (; optind < argc; optind++)
4008                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
4009                                           &show_rc, &err_rc);
4010
4011         if (show_rc)
4012                 cYAML_print_tree(show_rc);
4013
4014         if (err_rc)
4015                 cYAML_print_tree2file(stderr, err_rc);
4016
4017         cYAML_free_tree(err_rc);
4018         cYAML_free_tree(show_rc);
4019
4020         return rc;
4021 }
4022
4023 static int jt_discover(int argc, char **argv)
4024 {
4025         struct cYAML *err_rc = NULL;
4026         struct cYAML *show_rc = NULL;
4027         int force = 0;
4028         int rc = 0, opt;
4029
4030         const char *const short_options = "fh";
4031         const struct option long_options[] = {
4032                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
4033                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
4034                 { .name = NULL } };
4035
4036         while ((opt = getopt_long(argc, argv, short_options,
4037                                   long_options, NULL)) != -1) {
4038                 switch (opt) {
4039                 case 'f':
4040                         force = 1;
4041                         break;
4042                 case 'h':
4043                         printf("discover nid[,nid,...]\n"
4044                                "\t --force: force discovery\n"
4045                                "\t --help: display this help\n");
4046                         return 0;
4047                 default:
4048                         return 0;
4049                 }
4050         }
4051
4052         if (optind == argc) {
4053                 printf("Missing nid argument\n");
4054                 return -1;
4055         }
4056
4057         for (; optind < argc; optind++)
4058                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
4059                                               &err_rc);
4060
4061         if (show_rc)
4062                 cYAML_print_tree(show_rc);
4063
4064         if (err_rc)
4065                 cYAML_print_tree2file(stderr, err_rc);
4066
4067         cYAML_free_tree(err_rc);
4068         cYAML_free_tree(show_rc);
4069
4070         return rc;
4071 }
4072
4073 static int jt_add_udsp(int argc, char **argv)
4074 {
4075         char *src = NULL, *dst = NULL, *rte = NULL;
4076         struct cYAML *err_rc = NULL;
4077         union lnet_udsp_action udsp_action;
4078         long int idx = -1, priority = -1;
4079         int opt, rc = 0;
4080         char *action_type = "pref";
4081
4082         const char *const short_options = "s:d:r:p:i:";
4083         static const struct option long_options[] = {
4084         { .name = "src",         .has_arg = required_argument, .val = 's' },
4085         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
4086         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
4087         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
4088         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
4089         { .name = NULL } };
4090
4091         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
4092         if (rc)
4093                 return rc;
4094
4095         while ((opt = getopt_long(argc, argv, short_options,
4096                                   long_options, NULL)) != -1) {
4097                 switch (opt) {
4098                 case 's':
4099                         src = optarg;
4100                         break;
4101                 case 'd':
4102                         dst = optarg;
4103                         break;
4104                 case 'r':
4105                         rte = optarg;
4106                         break;
4107                 case 'p':
4108                         rc = parse_long(optarg, &priority);
4109                         if (rc != 0 || priority < 0) {
4110                                 printf("Invalid priority \"%s\"\n", optarg);
4111                                 return -EINVAL;
4112                         }
4113                         action_type = "priority";
4114                         udsp_action.udsp_priority = priority;
4115                         break;
4116                 case 'i':
4117                         rc = parse_long(optarg, &idx);
4118                         if (rc != 0 || idx < 0) {
4119                                 printf("Invalid index \"%s\"\n", optarg);
4120                                 return -EINVAL;
4121                         }
4122                         break;
4123                 case '?':
4124                         print_help(udsp_cmds, "udsp", "add");
4125                 default:
4126                         return 0;
4127                 }
4128         }
4129
4130         if (!(src || dst || rte)) {
4131                 print_help(udsp_cmds, "udsp", "add");
4132                 return 0;
4133         }
4134
4135         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
4136                                   idx, -1, &err_rc);
4137
4138         if (rc != LUSTRE_CFG_RC_NO_ERR)
4139                 cYAML_print_tree2file(stderr, err_rc);
4140
4141         cYAML_free_tree(err_rc);
4142
4143         return rc;
4144 }
4145
4146 static int jt_del_udsp(int argc, char **argv)
4147 {
4148         struct cYAML *err_rc = NULL;
4149         long int idx = -2;
4150         int opt, rc = 0;
4151         bool all = false;
4152
4153         const char *const short_options = "ai:";
4154         static const struct option long_options[] = {
4155         { .name = "all",        .has_arg = no_argument, .val = 'a' },
4156         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
4157         { .name = NULL } };
4158
4159         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
4160         if (rc)
4161                 return rc;
4162
4163         while ((opt = getopt_long(argc, argv, short_options,
4164                                   long_options, NULL)) != -1) {
4165                 switch (opt) {
4166                 case 'a':
4167                         all = true;
4168                         break;
4169                 case 'i':
4170                         rc = parse_long(optarg, &idx);
4171                         if (rc != 0 || idx < -1) {
4172                                 printf("Invalid index \"%s\"\n", optarg);
4173                                 return -EINVAL;
4174                         }
4175                         break;
4176                 case '?':
4177                         print_help(udsp_cmds, "udsp", "del");
4178                 default:
4179                         return 0;
4180                 }
4181         }
4182
4183         if (all && idx != -2) {
4184                 printf("Cannot combine --all with --idx\n");
4185                 return -EINVAL;
4186         } else if (all) {
4187                 idx = -1;
4188         } else if (idx == -2) {
4189                 printf("Must specify --idx or --all\n");
4190                 return -EINVAL;
4191         }
4192
4193         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
4194         if (rc != LUSTRE_CFG_RC_NO_ERR)
4195                 cYAML_print_tree2file(stderr, err_rc);
4196
4197         cYAML_free_tree(err_rc);
4198
4199         return rc;
4200 }
4201
4202 int main(int argc, char **argv)
4203 {
4204         int rc = 0;
4205         struct cYAML *err_rc = NULL;
4206
4207         rc = lustre_lnet_config_lib_init();
4208         if (rc < 0) {
4209                 cYAML_build_error(-1, -1, "lnetctl", "startup",
4210                                   "cannot register LNet device", &err_rc);
4211                 cYAML_print_tree2file(stderr, err_rc);
4212                 return rc;
4213         }
4214
4215         return cfs_parser(argc, argv, cmd_list);
4216 }