Whamcloud - gitweb
LU-17638 utils: break up Netlink error handling
[fs/lustre-release.git] / lnet / utils / lnetctl.c
1 // SPDX-License-Identifier: LGPL-2.0
2
3 /*
4  * Copyright (c) 2014, 2017, Intel Corporation.
5  */
6
7 /*
8  * This file is part of Lustre, http://www.lustre.org/
9  *
10  * Author: Amir Shehata <amir.shehata@intel.com>
11  */
12
13 #include <getopt.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <limits.h>
19 #include <libcfs/util/ioctl.h>
20 #include <libcfs/util/parser.h>
21 #include "lnetconfig/cyaml.h"
22 #include "lnetconfig/liblnetconfig.h"
23
24 #define LNET_CONFIGURE          true
25 #define LNET_UNCONFIGURE        false
26
27 #ifndef NLM_F_DUMP_FILTERED
28 #define NLM_F_DUMP_FILTERED    0x20
29 #endif
30
31 static int jt_config_lnet(int argc, char **argv);
32 static int jt_unconfig_lnet(int argc, char **argv);
33 static int jt_add_route(int argc, char **argv);
34 static int jt_add_ni(int argc, char **argv);
35 static int jt_set_routing(int argc, char **argv);
36 static int jt_del_route(int argc, char **argv);
37 static int jt_del_ni(int argc, char **argv);
38 static int jt_show_route(int argc, char **argv);
39 static int jt_show_net(int argc, char **argv);
40 static int jt_show_routing(int argc, char **argv);
41 static int jt_show_stats(int argc, char **argv);
42 static int jt_show_peer(int argc, char **argv);
43 static int jt_show_recovery(int argc, char **argv);
44 static int jt_show_global(int argc, char **argv);
45 static int jt_show_udsp(int argc, char **argv);
46 static int jt_set_tiny(int argc, char **argv);
47 static int jt_set_small(int argc, char **argv);
48 static int jt_set_large(int argc, char **argv);
49 static int jt_set_numa(int argc, char **argv);
50 static int jt_set_retry_count(int argc, char **argv);
51 static int jt_set_transaction_to(int argc, char **argv);
52 static int jt_set_recov_intrv(int argc, char **argv);
53 static int jt_set_rtr_sensitivity(int argc, char **argv);
54 static int jt_set_hsensitivity(int argc, char **argv);
55 static int jt_set_max_recovery_ping_interval(int argc, char **argv);
56 static int jt_reset_stats(int argc, char **argv);
57 static int jt_add_peer_nid(int argc, char **argv);
58 static int jt_del_peer_nid(int argc, char **argv);
59 static int jt_set_max_intf(int argc, char **argv);
60 static int jt_set_discovery(int argc, char **argv);
61 static int jt_set_drop_asym_route(int argc, char **argv);
62 static int jt_list_peer(int argc, char **argv);
63 static int jt_add_udsp(int argc, char **argv);
64 static int jt_del_udsp(int argc, char **argv);
65 /*static int jt_show_peer(int argc, char **argv);*/
66 static int jt_import(int argc, char **argv);
67 static int jt_export(int argc, char **argv);
68 static int jt_ping(int argc, char **argv);
69 static int jt_discover(int argc, char **argv);
70 static int jt_lnet(int argc, char **argv);
71 static int jt_route(int argc, char **argv);
72 static int jt_net(int argc, char **argv);
73 static int jt_routing(int argc, char **argv);
74 static int jt_set(int argc, char **argv);
75 static int jt_debug(int argc, char **argv);
76 static int jt_stats(int argc, char **argv);
77 static int jt_global(int argc, char **argv);
78 static int jt_peers(int argc, char **argv);
79 static int jt_set_ni_value(int argc, char **argv);
80 static int jt_set_peer_ni_value(int argc, char **argv);
81 static int jt_calc_service_id(int argc, char **argv);
82 static int jt_set_response_tracking(int argc, char **argv);
83 static int jt_set_recovery_limit(int argc, char **argv);
84 static int jt_udsp(int argc, char **argv);
85 static int jt_setup_mrrouting(int argc, char **argv);
86 static int jt_calc_cpt_of_nid(int argc, char **argv);
87 static int jt_show_peer_debug_info(int argc, char **argv);
88
89 command_t cmd_list[] = {
90         {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
91         {"route", jt_route, 0, "route {add | del | show | help}"},
92         {"net", jt_net, 0, "net {add | del | show | set | help}"},
93         {"routing", jt_routing, 0, "routing {show | help}"},
94         {"set", jt_set, 0, "set {tiny_buffers | small_buffers | large_buffers"
95                            " | routing | numa_range | max_interfaces"
96                            " | discovery | drop_asym_route | retry_count"
97                            " | transaction_timeout | health_sensitivity"
98                            " | recovery_interval | router_sensitivity"
99                            " | response_tracking | recovery_limit}"},
100         {"import", jt_import, 0, "import FILE.yaml"},
101         {"export", jt_export, 0, "export FILE.yaml"},
102         {"stats", jt_stats, 0, "stats {show | help}"},
103         {"debug", jt_debug, 0, "debug {recovery {local | peer} | peer}"},
104         {"global", jt_global, 0, "global {show | help}"},
105         {"peer", jt_peers, 0, "peer {add | del | show | list | set | help}"},
106         {"ping", jt_ping, 0, "ping nid,[nid,...]"},
107         {"discover", jt_discover, 0, "discover nid[,nid,...]"},
108         {"service-id", jt_calc_service_id, 0, "Calculate IB Lustre service ID\n"},
109         {"udsp", jt_udsp, 0, "udsp {add | del | help}"},
110         {"setup-mrrouting", jt_setup_mrrouting, 0,
111          "setup linux routing tables\n"},
112         {"cpt-of-nid", jt_calc_cpt_of_nid, 0,
113          "Calculate the CPTs associated with NIDs\n"
114          " usage:\n\tlnetctl cpt-of-nid nid[ nid ...]\n"},
115         { 0, 0, 0, NULL }
116 };
117
118 command_t lnet_cmds[] = {
119         {"configure", jt_config_lnet, 0, "configure lnet\n"
120          "\t--all: load NI configuration from module parameters\n"},
121         {"unconfigure", jt_unconfig_lnet, 0, "unconfigure lnet\n"},
122         { 0, 0, 0, NULL }
123 };
124
125 command_t route_cmds[] = {
126         {"add", jt_add_route, 0, "add a route\n"
127          "\t--net: net name (e.g. tcp0)\n"
128          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"
129          "\t--hop|hop-count: number to final destination (1 <= hops <= 255)\n"
130          "\t--priority: priority of route (0 - highest prio\n"
131          "\t--health_sensitivity: gateway health sensitivity (>= 1)\n"},
132         {"del", jt_del_route, 0, "delete a route\n"
133          "\t--net: net name (e.g. tcp0)\n"
134          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp)\n"},
135         {"show", jt_show_route, 0, "show routes\n"
136          "\t--net: net name (e.g. tcp0) to filter on\n"
137          "\t--gateway: gateway nid (e.g. 10.1.1.2@tcp) to filter on\n"
138          "\t--hop|hop-count: number to final destination (1 <= hops <= 255) to filter on\n"
139          "\t--priority: priority of route (0 - highest prio to filter on\n"
140          "\t--verbose: display detailed output per route\n"},
141         { 0, 0, 0, NULL }
142 };
143
144 command_t net_cmds[] = {
145         {"add", jt_add_ni, 0, "add a network\n"
146          "\t--net: net name (e.g. tcp0)\n"
147          "\t--if: physical interface (e.g. eth0)\n"
148          "\t--nid: bring up NI based on the address of the specified LNet NID\n"
149          "\t--ip2net: specify networks based on IP address patterns\n"
150          "\t--peer-timeout: time to wait before declaring a peer dead\n"
151          "\t--peer-credits: define the max number of inflight messages\n"
152          "\t--peer-buffer-credits: the number of buffer credits per peer\n"
153          "\t--credits: Network Interface credits\n"
154          "\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"
155          "\t--conns-per-peer: number of connections per peer\n"
156          "\t--skip-mr-route-setup: do not add linux route for the ni\n"
157          "\t--auth-key: Network authorization key (kfilnd only)\n"
158          "\t--traffic-class: Traffic class (kfilnd only)\n"},
159         {"del", jt_del_ni, 0, "delete a network\n"
160          "\t--net: net name (e.g. tcp0)\n"
161          "\t--nid: shutdown NI based on the address of the specified LNet NID\n"
162          "\t--if: physical interface (e.g. eth0)\n"},
163         {"show", jt_show_net, 0, "show networks\n"
164          "\t--net: net name (e.g. tcp0) to filter on\n"
165          "\t--verbose: display detailed output per network."
166                        " Optional argument of '2' outputs more stats\n"},
167         {"set", jt_set_ni_value, 0, "set local NI specific parameter\n"
168          "\t--nid: NI NID to set the\n"
169          "\t--health: specify health value to set\n"
170          "\t--conns-per-peer: number of connections per peer\n"
171          "\t--all: set all NIs value to the one specified\n"},
172         { 0, 0, 0, NULL }
173 };
174
175 command_t routing_cmds[] = {
176         {"show", jt_show_routing, 0, "show routing information\n"},
177         { 0, 0, 0, NULL }
178 };
179
180 command_t stats_cmds[] = {
181         {"show", jt_show_stats, 0, "show LNET statistics\n"},
182         {"reset", jt_reset_stats, 0, "reset LNET statistics\n"},
183         { 0, 0, 0, NULL }
184 };
185
186 command_t debug_cmds[] = {
187         {"recovery", jt_show_recovery, 0, "list recovery queues\n"
188                 "\t--local : list local recovery queue\n"
189                 "\t--peer : list peer recovery queue\n"},
190         {"peer", jt_show_peer_debug_info, 0, "show peer debug info\n"
191                 "\t--nid: peer's NID\n"},
192         { 0, 0, 0, NULL }
193 };
194
195 command_t global_cmds[] = {
196         {"show", jt_show_global, 0, "show global variables\n"},
197         { 0, 0, 0, NULL }
198 };
199
200 command_t set_cmds[] = {
201         {"tiny_buffers", jt_set_tiny, 0, "set tiny routing buffers\n"
202          "\tVALUE must be greater than 0\n"},
203         {"small_buffers", jt_set_small, 0, "set small routing buffers\n"
204          "\tVALUE must be greater than 0\n"},
205         {"large_buffers", jt_set_large, 0, "set large routing buffers\n"
206          "\tVALUE must be greater than 0\n"},
207         {"routing", jt_set_routing, 0, "enable/disable routing\n"
208          "\t0 - disable routing\n"
209          "\t1 - enable routing\n"},
210         {"numa_range", jt_set_numa, 0, "set NUMA range for NI selection\n"
211          "\tVALUE must be at least 0\n"},
212         {"max_interfaces", jt_set_max_intf, 0, "set the default value for "
213                 "max interfaces\n"
214          "\tValue must be greater than 16\n"},
215         {"discovery", jt_set_discovery, 0, "enable/disable peer discovery\n"
216          "\t0 - disable peer discovery\n"
217          "\t1 - enable peer discovery (default)\n"},
218         {"drop_asym_route", jt_set_drop_asym_route, 0,
219          "drop/accept asymmetrical route messages\n"
220          "\t0 - accept asymmetrical route messages (default)\n"
221          "\t1 - drop asymmetrical route messages\n"},
222         {"retry_count", jt_set_retry_count, 0, "number of retries\n"
223          "\t0 - turn of retries\n"
224          "\t>0 - number of retries\n"},
225         {"transaction_timeout", jt_set_transaction_to, 0, "Message/Response timeout\n"
226          "\t>0 - timeout in seconds\n"},
227         {"health_sensitivity", jt_set_hsensitivity, 0, "sensitivity to failure\n"
228          "\t0 - turn off health evaluation\n"
229          "\t>0 - sensitivity value not more than 1000\n"},
230         {"recovery_interval", jt_set_recov_intrv, 0, "interval to ping in seconds (at least 1)\n"
231          "\t>0 - time in seconds between pings\n"},
232         {"router_sensitivity", jt_set_rtr_sensitivity, 0, "router sensitivity %\n"
233          "\t100 - router interfaces need to be fully healthy to be used\n"
234          "\t<100 - router interfaces can be used even if not healthy\n"},
235         {"response_tracking", jt_set_response_tracking, 0,
236          "Set the behavior of response tracking\n"
237          "\t0 - Only LNet pings and discovery pushes utilize response tracking\n"
238          "\t1 - GETs are eligible for response tracking\n"
239          "\t2 - PUTs are eligible for response tracking\n"
240          "\t3 - Both PUTs and GETs are eligible for response tracking (default)\n"
241          "\tNote: Regardless of the value of the response_tracking parameter LNet\n"
242          "\t      pings and discovery pushes always utilize response tracking\n"},
243         {"recovery_limit", jt_set_recovery_limit, 0,
244          "Set how long LNet will attempt to recover unhealthy interfaces.\n"
245          "\t0 - Recover indefinitely (default)\n"
246          "\t>0 - Recover for the specified number of seconds.\n"},
247         {"max_recovery_ping_interval", jt_set_max_recovery_ping_interval, 0,
248          "maximum recovery ping interval\n"
249          "\t>0 - maximum recovery ping interval in seconds\n"},
250         { 0, 0, 0, NULL }
251 };
252
253 command_t peer_cmds[] = {
254         {"add", jt_add_peer_nid, 0, "add a peer NID\n"
255          "\t--prim_nid: Primary NID of the peer.\n"
256          "\t--nid: one or more peer NIDs\n"
257          "\t--non_mr: create this peer as not Multi-Rail capable\n"
258          "\t--ip2nets: specify a range of nids per peer\n"
259          "\t--lock_prim: lock primary nid\n"},
260         {"del", jt_del_peer_nid, 0, "delete a peer NID\n"
261          "\t--prim_nid: Primary NID of the peer.\n"
262          "\t--nid: list of NIDs to remove. If none provided,\n"
263          "\t       peer is deleted\n"
264          "\t--ip2nets: specify a range of nids per peer\n"
265          "\t--force: force-delete locked primary NID\n"},
266         {"show", jt_show_peer, 0, "show peer information\n"
267          "\t--nid: NID of peer to filter on.\n"
268          "\t--verbose: display detailed output per peer."
269                        " Optional argument of '2' outputs more stats\n"},
270         {"list", jt_list_peer, 0, "list all peers\n"},
271         {"set", jt_set_peer_ni_value, 0, "set peer ni specific parameter\n"
272          "\t--nid: Peer NI NID to set the\n"
273          "\t--health: specify health value to set\n"
274          "\t--all: set all peer_nis values to the one specified\n"
275          "\t--state: set peer state (DANGEROUS: for test/debug only)"},
276         { 0, 0, 0, NULL }
277 };
278
279 command_t udsp_cmds[] = {
280         {"add", jt_add_udsp, 0, "add a udsp\n"
281          "\t--src nid|net: ip2nets syntax specifying the local NID or network to match.\n"
282          "\t--dst nid:     ip2nets syntax specifying the remote NID to match.\n"
283          "\t--rte nid:     ip2nets syntax specifying the router NID to match.\n"
284          "\t--priority p:  Assign priority value p where p >= 0.\n"
285          "\t               Note: 0 is the highest priority.\n"
286          "\t--idx n:       Insert the rule in the n'th position on the list of rules.\n"
287          "\t               By default, rules are appended to the end of the rule list.\n"},
288         {"del", jt_del_udsp, 0, "delete a udsp\n"
289          "\t--all:   Delete all rules.\n"
290          "\t--idx n: Delete the rule at index n.\n"},
291         {"show", jt_show_udsp, 0, "show udsps\n"
292          "\t--idx n: Show the rule at at index n.\n"
293          "\t         By default, all rules are shown.\n"},
294         { 0, 0, 0, NULL }
295 };
296
297 static int parse_long(const char *number, long int *value)
298 {
299         char *end;
300
301         if (!number)
302                 return -1;
303
304         *value = strtol(number,  &end, 0);
305         if (end != NULL && *end != 0)
306                 return -1;
307
308         return 0;
309 }
310
311 static int jt_setup_mrrouting(int argc, char **argv)
312 {
313         int rc;
314         struct cYAML *err_rc = NULL;
315
316         rc = lustre_lnet_setup_mrrouting(&err_rc);
317
318         if (rc != LUSTRE_CFG_RC_NO_ERR)
319                 cYAML_print_tree2file(stderr, err_rc);
320
321         cYAML_free_tree(err_rc);
322
323         return rc;
324 }
325
326 static inline void print_help(const command_t cmds[], const char *cmd_type,
327                               const char *pc_name)
328 {
329         const command_t *cmd;
330
331         for (cmd = cmds; cmd->pc_name; cmd++) {
332                 if (pc_name != NULL &&
333                     strcmp(cmd->pc_name, pc_name) == 0) {
334                         printf("%s %s: %s\n", cmd_type, cmd->pc_name,
335                                cmd->pc_help);
336                         return;
337                 } else if (pc_name != NULL) {
338                         continue;
339                 }
340                 printf("%s %s: %s\n", cmd_type, cmd->pc_name, cmd->pc_help);
341         }
342 }
343
344 static int check_cmd(const command_t *cmd_list, const char *cmd,
345                      const char *sub_cmd, const int min_args,
346                      int argc, char **argv)
347 {
348         int opt;
349         int rc = 0;
350         optind = 0;
351         opterr = 0;
352
353         const char *const short_options = "h";
354         static const struct option long_options[] = {
355                 { .name = "help", .has_arg = no_argument, .val = 'h' },
356                 { .name = NULL }
357         };
358
359         if (argc < min_args) {
360                 print_help(cmd_list, cmd, sub_cmd);
361                 rc = LUSTRE_CFG_RC_BAD_PARAM;
362                 goto out;
363         } else if (argc > 2) {
364                 return 0;
365         }
366
367         while ((opt = getopt_long(argc, argv, short_options,
368                                   long_options, NULL)) != -1) {
369                 switch (opt) {
370                 case 'h':
371                         print_help(cmd_list, cmd, sub_cmd);
372                         rc = 1;
373                         break;
374                 default:
375                         rc = 0;
376                         break;
377                 }
378         }
379
380 out:
381         opterr = 1;
382         optind = 0;
383         return rc;
384 }
385
386 static int jt_set_response_tracking(int argc, char **argv)
387 {
388         long int value;
389         int rc;
390         struct cYAML *err_rc = NULL;
391
392         rc = check_cmd(set_cmds, "set", "response_tracking", 2, argc, argv);
393         if (rc)
394                 return rc;
395
396         rc = parse_long(argv[1], &value);
397         if (rc != 0) {
398                 cYAML_build_error(-1, -1, "parser", "set",
399                                   "cannot parse response_tracking value",
400                                   &err_rc);
401                 cYAML_print_tree2file(stderr, err_rc);
402                 cYAML_free_tree(err_rc);
403                 return -1;
404         }
405
406         rc = lustre_lnet_config_response_tracking(value, -1, &err_rc);
407         if (rc != LUSTRE_CFG_RC_NO_ERR)
408                 cYAML_print_tree2file(stderr, err_rc);
409
410         cYAML_free_tree(err_rc);
411
412         return rc;
413 }
414
415 static int jt_calc_service_id(int argc, char **argv)
416 {
417         int rc;
418         __u64 service_id;
419
420         rc = lustre_lnet_calc_service_id(&service_id);
421         if (rc != LUSTRE_CFG_RC_NO_ERR)
422                 return rc;
423
424         /* cYAML currently doesn't support printing hex values.
425          * Therefore just print it locally here
426          */
427         printf("service_id:\n    value: 0x%llx\n",
428                (unsigned long long)(service_id));
429
430         return rc;
431 }
432
433 static int jt_set_recovery_limit(int argc, char **argv)
434 {
435         long int value;
436         int rc;
437         struct cYAML *err_rc = NULL;
438
439         rc = check_cmd(set_cmds, "set", "recovery_limit", 2, argc, argv);
440         if (rc)
441                 return rc;
442
443         rc = parse_long(argv[1], &value);
444         if (rc != 0) {
445                 cYAML_build_error(-1, -1, "parser", "set",
446                                   "cannot parse recovery_limit value",
447                                   &err_rc);
448                 cYAML_print_tree2file(stderr, err_rc);
449                 cYAML_free_tree(err_rc);
450                 return -1;
451         }
452
453         rc = lustre_lnet_config_recovery_limit(value, -1, &err_rc);
454         if (rc != LUSTRE_CFG_RC_NO_ERR)
455                 cYAML_print_tree2file(stderr, err_rc);
456
457         cYAML_free_tree(err_rc);
458
459         return rc;
460 }
461
462 static int jt_set_max_intf(int argc, char **argv)
463 {
464         long int value;
465         int rc;
466         struct cYAML *err_rc = NULL;
467
468         rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
469         if (rc)
470                 return rc;
471
472         rc = parse_long(argv[1], &value);
473         if (rc != 0) {
474                 cYAML_build_error(-1, -1, "parser", "set",
475                                   "cannot parse max_interfaces value", &err_rc);
476                 cYAML_print_tree2file(stderr, err_rc);
477                 cYAML_free_tree(err_rc);
478                 return -1;
479         }
480
481         rc = lustre_lnet_config_max_intf(value, -1, &err_rc);
482         if (rc != LUSTRE_CFG_RC_NO_ERR)
483                 cYAML_print_tree2file(stderr, err_rc);
484
485         cYAML_free_tree(err_rc);
486
487         return rc;
488 }
489
490 static int jt_set_numa(int argc, char **argv)
491 {
492         long int value;
493         int rc;
494         struct cYAML *err_rc = NULL;
495
496         rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
497         if (rc)
498                 return rc;
499
500         rc = parse_long(argv[1], &value);
501         if (rc != 0) {
502                 cYAML_build_error(-1, -1, "parser", "set",
503                                   "cannot parse numa_range value", &err_rc);
504                 cYAML_print_tree2file(stderr, err_rc);
505                 cYAML_free_tree(err_rc);
506                 return -1;
507         }
508
509         rc = lustre_lnet_config_numa_range(value, -1, &err_rc);
510         if (rc != LUSTRE_CFG_RC_NO_ERR)
511                 cYAML_print_tree2file(stderr, err_rc);
512
513         cYAML_free_tree(err_rc);
514
515         return rc;
516 }
517
518 static int jt_set_recov_intrv(int argc, char **argv)
519 {
520         long int value;
521         int rc;
522         struct cYAML *err_rc = NULL;
523
524         rc = check_cmd(set_cmds, "set", "recovery_interval", 2, argc, argv);
525         if (rc)
526                 return rc;
527
528         rc = parse_long(argv[1], &value);
529         if (rc != 0) {
530                 cYAML_build_error(-1, -1, "parser", "set",
531                                   "cannot parse recovery interval value", &err_rc);
532                 cYAML_print_tree2file(stderr, err_rc);
533                 cYAML_free_tree(err_rc);
534                 return -1;
535         }
536
537         rc = lustre_lnet_config_recov_intrv(value, -1, &err_rc);
538         if (rc != LUSTRE_CFG_RC_NO_ERR)
539                 cYAML_print_tree2file(stderr, err_rc);
540
541         cYAML_free_tree(err_rc);
542
543         return rc;
544 }
545
546 static int jt_set_rtr_sensitivity(int argc, char **argv)
547 {
548         long int value;
549         int rc;
550         struct cYAML *err_rc = NULL;
551
552         rc = check_cmd(set_cmds, "set", "router_sensitivity", 2, argc, argv);
553         if (rc)
554                 return rc;
555
556         rc = parse_long(argv[1], &value);
557         if (rc != 0) {
558                 cYAML_build_error(-1, -1, "parser", "set",
559                                   "cannot parse router sensitivity value", &err_rc);
560                 cYAML_print_tree2file(stderr, err_rc);
561                 cYAML_free_tree(err_rc);
562                 return -1;
563         }
564
565         rc = lustre_lnet_config_rtr_sensitivity(value, -1, &err_rc);
566         if (rc != LUSTRE_CFG_RC_NO_ERR)
567                 cYAML_print_tree2file(stderr, err_rc);
568
569         cYAML_free_tree(err_rc);
570
571         return rc;
572 }
573
574 static int jt_set_hsensitivity(int argc, char **argv)
575 {
576         long int value;
577         int rc;
578         struct cYAML *err_rc = NULL;
579
580         rc = check_cmd(set_cmds, "set", "health_sensitivity", 2, argc, argv);
581         if (rc)
582                 return rc;
583
584         rc = parse_long(argv[1], &value);
585         if (rc != 0) {
586                 cYAML_build_error(-1, -1, "parser", "set",
587                                   "cannot parse health sensitivity value", &err_rc);
588                 cYAML_print_tree2file(stderr, err_rc);
589                 cYAML_free_tree(err_rc);
590                 return -1;
591         }
592
593         rc = lustre_lnet_config_hsensitivity(value, -1, &err_rc);
594         if (rc != LUSTRE_CFG_RC_NO_ERR)
595                 cYAML_print_tree2file(stderr, err_rc);
596
597         cYAML_free_tree(err_rc);
598
599         return rc;
600 }
601
602 static int jt_reset_stats(int argc, char **argv)
603 {
604         int rc;
605         struct cYAML *err_rc = NULL;
606
607         rc = check_cmd(stats_cmds, "stats", "reset", 0, argc, argv);
608         if (rc)
609                 return rc;
610
611         rc = lustre_lnet_reset_stats(-1, &err_rc);
612         if (rc != LUSTRE_CFG_RC_NO_ERR)
613                 cYAML_print_tree2file(stderr, err_rc);
614
615         cYAML_free_tree(err_rc);
616
617         return rc;
618 }
619
620 static int jt_set_transaction_to(int argc, char **argv)
621 {
622         long int value;
623         int rc;
624         struct cYAML *err_rc = NULL;
625
626         rc = check_cmd(set_cmds, "set", "transaction_timeout", 2, argc, argv);
627         if (rc)
628                 return rc;
629
630         rc = parse_long(argv[1], &value);
631         if (rc != 0) {
632                 cYAML_build_error(-1, -1, "parser", "set",
633                                   "cannot parse transaction timeout value", &err_rc);
634                 cYAML_print_tree2file(stderr, err_rc);
635                 cYAML_free_tree(err_rc);
636                 return -1;
637         }
638
639         rc = lustre_lnet_config_transaction_to(value, -1, &err_rc);
640         if (rc != LUSTRE_CFG_RC_NO_ERR)
641                 cYAML_print_tree2file(stderr, err_rc);
642
643         cYAML_free_tree(err_rc);
644
645         return rc;
646 }
647
648 static int jt_set_retry_count(int argc, char **argv)
649 {
650         long int value;
651         int rc;
652         struct cYAML *err_rc = NULL;
653
654         rc = check_cmd(set_cmds, "set", "retry_count", 2, argc, argv);
655         if (rc)
656                 return rc;
657
658         rc = parse_long(argv[1], &value);
659         if (rc != 0) {
660                 cYAML_build_error(-1, -1, "parser", "set",
661                                   "cannot parse retry_count value", &err_rc);
662                 cYAML_print_tree2file(stderr, err_rc);
663                 cYAML_free_tree(err_rc);
664                 return -1;
665         }
666
667         rc = lustre_lnet_config_retry_count(value, -1, &err_rc);
668         if (rc != LUSTRE_CFG_RC_NO_ERR)
669                 cYAML_print_tree2file(stderr, err_rc);
670
671         cYAML_free_tree(err_rc);
672
673         return rc;
674 }
675
676 static int jt_set_discovery(int argc, char **argv)
677 {
678         long int value;
679         int rc;
680         struct cYAML *err_rc = NULL;
681
682         rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
683         if (rc)
684                 return rc;
685
686         rc = parse_long(argv[1], &value);
687         if (rc != 0) {
688                 cYAML_build_error(-1, -1, "parser", "set",
689                                   "cannot parse discovery value", &err_rc);
690                 cYAML_print_tree2file(stderr, err_rc);
691                 cYAML_free_tree(err_rc);
692                 return -1;
693         }
694
695         rc = lustre_lnet_config_discovery(value, -1, &err_rc);
696         if (rc != LUSTRE_CFG_RC_NO_ERR)
697                 cYAML_print_tree2file(stderr, err_rc);
698
699         cYAML_free_tree(err_rc);
700
701         return rc;
702 }
703
704 static int jt_set_drop_asym_route(int argc, char **argv)
705 {
706         long int value;
707         int rc;
708         struct cYAML *err_rc = NULL;
709
710         rc = check_cmd(set_cmds, "set", "drop_asym_route", 2, argc, argv);
711         if (rc)
712                 return rc;
713
714         rc = parse_long(argv[1], &value);
715         if (rc != 0) {
716                 cYAML_build_error(-1, -1, "parser", "set",
717                                   "cannot parse drop_asym_route value",
718                                   &err_rc);
719                 cYAML_print_tree2file(stderr, err_rc);
720                 cYAML_free_tree(err_rc);
721                 return -1;
722         }
723
724         rc = lustre_lnet_config_drop_asym_route(value, -1, &err_rc);
725         if (rc != LUSTRE_CFG_RC_NO_ERR)
726                 cYAML_print_tree2file(stderr, err_rc);
727
728         cYAML_free_tree(err_rc);
729
730         return rc;
731 }
732
733 static int jt_set_tiny(int argc, char **argv)
734 {
735         long int value;
736         int rc;
737         struct cYAML *err_rc = NULL;
738
739         rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
740         if (rc)
741                 return rc;
742
743         rc = parse_long(argv[1], &value);
744         if (rc != 0) {
745                 cYAML_build_error(-1, -1, "parser", "set",
746                                   "cannot parse tiny_buffers value", &err_rc);
747                 cYAML_print_tree2file(stderr, err_rc);
748                 cYAML_free_tree(err_rc);
749                 return -1;
750         }
751
752         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
753         if (rc != LUSTRE_CFG_RC_NO_ERR)
754                 cYAML_print_tree2file(stderr, err_rc);
755
756         cYAML_free_tree(err_rc);
757
758         return rc;
759 }
760
761 static int jt_set_small(int argc, char **argv)
762 {
763         long int value;
764         int rc;
765         struct cYAML *err_rc = NULL;
766
767         rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
768         if (rc)
769                 return rc;
770
771         rc = parse_long(argv[1], &value);
772         if (rc != 0) {
773                 cYAML_build_error(-1, -1, "parser", "set",
774                                   "cannot parse small_buffers value", &err_rc);
775                 cYAML_print_tree2file(stderr, err_rc);
776                 cYAML_free_tree(err_rc);
777                 return -1;
778         }
779
780         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
781         if (rc != LUSTRE_CFG_RC_NO_ERR)
782                 cYAML_print_tree2file(stderr, err_rc);
783
784         cYAML_free_tree(err_rc);
785
786         return rc;
787 }
788
789 static int jt_set_large(int argc, char **argv)
790 {
791         long int value;
792         int rc;
793         struct cYAML *err_rc = NULL;
794
795         rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
796         if (rc)
797                 return rc;
798
799         rc = parse_long(argv[1], &value);
800         if (rc != 0) {
801                 cYAML_build_error(-1, -1, "parser", "set",
802                                   "cannot parse large_buffers value", &err_rc);
803                 cYAML_print_tree2file(stderr, err_rc);
804                 cYAML_free_tree(err_rc);
805                 return -1;
806         }
807
808         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
809         if (rc != LUSTRE_CFG_RC_NO_ERR)
810                 cYAML_print_tree2file(stderr, err_rc);
811
812         cYAML_free_tree(err_rc);
813
814         return rc;
815 }
816
817 static int jt_set_routing(int argc, char **argv)
818 {
819         long int value;
820         struct cYAML *err_rc = NULL;
821         int rc;
822
823         rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
824         if (rc)
825                 return rc;
826
827         rc = parse_long(argv[1], &value);
828         if (rc != 0 || (value != 0 && value != 1)) {
829                 cYAML_build_error(-1, -1, "parser", "set",
830                                   "cannot parse routing value.\n"
831                                   "must be 0 for disable or 1 for enable",
832                                   &err_rc);
833                 cYAML_print_tree2file(stderr, err_rc);
834                 cYAML_free_tree(err_rc);
835                 return -1;
836         }
837
838         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
839
840         if (rc != LUSTRE_CFG_RC_NO_ERR)
841                 cYAML_print_tree2file(stderr, err_rc);
842
843         cYAML_free_tree(err_rc);
844
845         return rc;
846 }
847
848 static int jt_set_max_recovery_ping_interval(int argc, char **argv)
849 {
850         long int value;
851         int rc;
852         struct cYAML *err_rc = NULL;
853
854         rc = check_cmd(set_cmds, "set", "maximum recovery_interval", 2, argc, argv);
855         if (rc)
856                 return rc;
857
858         rc = parse_long(argv[1], &value);
859         if (rc != 0) {
860                 cYAML_build_error(-1, -1, "parser", "set",
861                                   "cannot parse maximum recovery interval value",
862                                   &err_rc);
863                 cYAML_print_tree2file(stderr, err_rc);
864                 cYAML_free_tree(err_rc);
865                 return -1;
866         }
867
868         rc = lustre_lnet_config_max_recovery_ping_interval(value, -1, &err_rc);
869         if (rc != LUSTRE_CFG_RC_NO_ERR)
870                 cYAML_print_tree2file(stderr, err_rc);
871
872         cYAML_free_tree(err_rc);
873
874         return rc;
875 }
876
877 static void yaml_lnet_print_error(int op, char *cmd, const char *errstr)
878 {
879         char errcode[INT_STRING_LEN];
880         yaml_emitter_t log;
881         yaml_event_t event;
882         const char *flag;
883         int rc;
884
885         snprintf(errcode, sizeof(errcode), "%d", errno);
886
887         yaml_emitter_initialize(&log);
888         yaml_emitter_set_indent(&log, LNET_DEFAULT_INDENT);
889         yaml_emitter_set_output_file(&log, stderr);
890
891         yaml_emitter_open(&log);
892         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
893         rc = yaml_emitter_emit(&log, &event);
894         if (rc == 0)
895                 goto emitter_error;
896
897         yaml_mapping_start_event_initialize(&event, NULL,
898                                             (yaml_char_t *)YAML_MAP_TAG,
899                                             1, YAML_ANY_MAPPING_STYLE);
900         rc = yaml_emitter_emit(&log, &event);
901         if (rc == 0)
902                 goto emitter_error;
903
904         if (strcmp(cmd, "lnet") == 0) {
905                 flag = "configure";
906                 goto skip_op;
907         }
908
909         switch (op) {
910         case NLM_F_CREATE:
911                 flag = "add";
912                 break;
913         case NLM_F_REPLACE:
914                 flag = "set";
915                 break;
916         case 0:
917                 flag = "del";
918                 break;
919         case -1:
920                 flag = "manage";
921                 break;
922         case NLM_F_DUMP:
923         default:
924                 flag = "show";
925                 break;
926         }
927 skip_op:
928         yaml_scalar_event_initialize(&event, NULL,
929                                      (yaml_char_t *)YAML_STR_TAG,
930                                      (yaml_char_t *)flag,
931                                      strlen(flag), 1, 0,
932                                      YAML_PLAIN_SCALAR_STYLE);
933         rc = yaml_emitter_emit(&log, &event);
934         if (rc == 0)
935                 goto emitter_error;
936
937         yaml_sequence_start_event_initialize(&event, NULL,
938                                              (yaml_char_t *)YAML_SEQ_TAG,
939                                              1, YAML_ANY_SEQUENCE_STYLE);
940         rc = yaml_emitter_emit(&log, &event);
941         if (rc == 0)
942                 goto emitter_error;
943
944         yaml_mapping_start_event_initialize(&event, NULL,
945                                             (yaml_char_t *)YAML_MAP_TAG,
946                                             1, YAML_ANY_MAPPING_STYLE);
947         rc = yaml_emitter_emit(&log, &event);
948         if (rc == 0)
949                 goto emitter_error;
950
951         yaml_scalar_event_initialize(&event, NULL,
952                                      (yaml_char_t *)YAML_STR_TAG,
953                                      (yaml_char_t *)cmd,
954                                      strlen(cmd),
955                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
956         rc = yaml_emitter_emit(&log, &event);
957         if (rc == 0)
958                 goto emitter_error;
959
960         yaml_scalar_event_initialize(&event, NULL,
961                                      (yaml_char_t *)YAML_STR_TAG,
962                                      (yaml_char_t *)"",
963                                      strlen(""),
964                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
965         rc = yaml_emitter_emit(&log, &event);
966         if (rc == 0)
967                 goto emitter_error;
968
969         yaml_scalar_event_initialize(&event, NULL,
970                                      (yaml_char_t *)YAML_STR_TAG,
971                                      (yaml_char_t *)"errno",
972                                      strlen("errno"), 1, 0,
973                                      YAML_PLAIN_SCALAR_STYLE);
974         rc = yaml_emitter_emit(&log, &event);
975         if (rc == 0)
976                 goto emitter_error;
977
978         yaml_scalar_event_initialize(&event, NULL,
979                                      (yaml_char_t *)YAML_INT_TAG,
980                                      (yaml_char_t *)errcode,
981                                      strlen(errcode), 1, 0,
982                                      YAML_PLAIN_SCALAR_STYLE);
983         rc = yaml_emitter_emit(&log, &event);
984         if (rc == 0)
985                 goto emitter_error;
986
987
988         yaml_scalar_event_initialize(&event, NULL,
989                                      (yaml_char_t *)YAML_STR_TAG,
990                                      (yaml_char_t *)"descr",
991                                      strlen("descr"), 1, 0,
992                                      YAML_PLAIN_SCALAR_STYLE);
993         rc = yaml_emitter_emit(&log, &event);
994         if (rc == 0)
995                 goto emitter_error;
996
997         yaml_scalar_event_initialize(&event, NULL,
998                                      (yaml_char_t *)YAML_STR_TAG,
999                                      (yaml_char_t *)errstr,
1000                                      strlen(errstr), 1, 0,
1001                                      YAML_DOUBLE_QUOTED_SCALAR_STYLE);
1002         rc = yaml_emitter_emit(&log, &event);
1003         if (rc == 0)
1004                 goto emitter_error;
1005
1006         yaml_mapping_end_event_initialize(&event);
1007         rc = yaml_emitter_emit(&log, &event);
1008         if (rc == 0)
1009                 goto emitter_error;
1010
1011         yaml_sequence_end_event_initialize(&event);
1012         rc = yaml_emitter_emit(&log, &event);
1013         if (rc == 0)
1014                 goto emitter_error;
1015
1016         yaml_mapping_end_event_initialize(&event);
1017         rc = yaml_emitter_emit(&log, &event);
1018         if (rc == 0)
1019                 goto emitter_error;
1020
1021         yaml_document_end_event_initialize(&event, 0);
1022         rc = yaml_emitter_emit(&log, &event);
1023         if (rc == 0)
1024                 goto emitter_error;
1025
1026         rc = yaml_emitter_close(&log);
1027 emitter_error:
1028         if (rc == 0)
1029                 yaml_emitter_log_error(&log, stdout);
1030         yaml_emitter_delete(&log);
1031 }
1032
1033 static int yaml_lnet_cpt_of_nid_display(yaml_parser_t *reply)
1034 {
1035         yaml_document_t results;
1036         yaml_emitter_t output;
1037         int rc;
1038
1039         rc = yaml_parser_load(reply, &results);
1040         if (rc == 0) {
1041                 yaml_lnet_print_error(NLM_F_DUMP, "cpt-of-nid",
1042                                       yaml_parser_get_reader_error(reply));
1043                 yaml_document_delete(&results);
1044                 return -EINVAL;
1045         }
1046
1047         rc = yaml_emitter_initialize(&output);
1048         if (rc == 1) {
1049                 yaml_emitter_set_output_file(&output, stdout);
1050
1051                 rc = yaml_emitter_dump(&output, &results);
1052         }
1053
1054         yaml_document_delete(&results);
1055         if (rc == 0) {
1056                 yaml_emitter_log_error(&output, stderr);
1057                 rc = -EINVAL;
1058         }
1059         yaml_emitter_delete(&output);
1060
1061         return 1;
1062 }
1063
1064 static int yaml_lnet_cpt_of_nid(int start, int end, char **nids)
1065 {
1066         struct nl_sock *sk = NULL;
1067         yaml_emitter_t request;
1068         yaml_parser_t reply;
1069         yaml_event_t event;
1070         int i, rc;
1071
1072         /* Create Netlink emitter to send request to kernel */
1073         sk = nl_socket_alloc();
1074         if (!sk)
1075                 return -EOPNOTSUPP;
1076
1077         /* Setup parser to receive Netlink packets */
1078         rc = yaml_parser_initialize(&reply);
1079         if (rc == 0) {
1080                 nl_socket_free(sk);
1081                 return -EOPNOTSUPP;
1082         }
1083
1084         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1085         if (rc == 0)
1086                 goto free_reply;
1087
1088         /* Create Netlink emitter to send request to kernel */
1089         rc = yaml_emitter_initialize(&request);
1090         if (rc == 0)
1091                 goto free_reply;
1092
1093         rc = yaml_emitter_set_output_netlink(&request, sk, LNET_GENL_NAME,
1094                                              LNET_GENL_VERSION,
1095                                              LNET_CMD_CPT_OF_NID, NLM_F_DUMP);
1096         if (rc == 0)
1097                 goto emitter_error;
1098
1099         yaml_emitter_open(&request);
1100         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1101         rc = yaml_emitter_emit(&request, &event);
1102         if (rc == 0)
1103                 goto emitter_error;
1104
1105         yaml_mapping_start_event_initialize(&event, NULL,
1106                                             (yaml_char_t *)YAML_MAP_TAG,
1107                                             1, YAML_ANY_MAPPING_STYLE);
1108         rc = yaml_emitter_emit(&request, &event);
1109         if (rc == 0)
1110                 goto emitter_error;
1111
1112         yaml_scalar_event_initialize(&event, NULL,
1113                                      (yaml_char_t *)YAML_STR_TAG,
1114                                      (yaml_char_t *)"cpt-of-nid",
1115                                      strlen("cpt-of-nid"), 1, 0,
1116                                      YAML_PLAIN_SCALAR_STYLE);
1117         rc = yaml_emitter_emit(&request, &event);
1118         if (rc == 0)
1119                 goto emitter_error;
1120
1121         yaml_mapping_start_event_initialize(&event, NULL,
1122                                             (yaml_char_t *)YAML_MAP_TAG,
1123                                             1, YAML_ANY_MAPPING_STYLE);
1124         rc = yaml_emitter_emit(&request, &event);
1125         if (rc == 0)
1126                 goto emitter_error;
1127
1128         yaml_scalar_event_initialize(&event, NULL,
1129                                      (yaml_char_t *)YAML_STR_TAG,
1130                                      (yaml_char_t *)"nids",
1131                                      strlen("nids"), 1, 0,
1132                                      YAML_PLAIN_SCALAR_STYLE);
1133         rc = yaml_emitter_emit(&request, &event);
1134         if (rc == 0)
1135                 goto emitter_error;
1136
1137         yaml_sequence_start_event_initialize(&event, NULL,
1138                                              (yaml_char_t *)YAML_SEQ_TAG,
1139                                              1, YAML_FLOW_SEQUENCE_STYLE);
1140         rc = yaml_emitter_emit(&request, &event);
1141         if (rc == 0)
1142                 goto emitter_error;
1143
1144         for (i = start; i < end; i++) {
1145                 yaml_scalar_event_initialize(&event, NULL,
1146                                              (yaml_char_t *)YAML_STR_TAG,
1147                                              (yaml_char_t *)nids[i],
1148                                              strlen(nids[i]), 1, 0,
1149                                              YAML_PLAIN_SCALAR_STYLE);
1150                 rc = yaml_emitter_emit(&request, &event);
1151                 if (rc == 0)
1152                         goto emitter_error;
1153         }
1154
1155         yaml_sequence_end_event_initialize(&event);
1156         rc = yaml_emitter_emit(&request, &event);
1157         if (rc == 0)
1158                 goto emitter_error;
1159
1160         yaml_mapping_end_event_initialize(&event);
1161         rc = yaml_emitter_emit(&request, &event);
1162         if (rc == 0)
1163                 goto emitter_error;
1164
1165         yaml_mapping_end_event_initialize(&event);
1166         rc = yaml_emitter_emit(&request, &event);
1167         if (rc == 0)
1168                 goto emitter_error;
1169
1170         yaml_document_end_event_initialize(&event, 0);
1171         rc = yaml_emitter_emit(&request, &event);
1172         if (rc == 0)
1173                 goto emitter_error;
1174
1175         rc = yaml_emitter_close(&request);
1176 emitter_error:
1177         if (rc == 0) {
1178                 yaml_emitter_log_error(&request, stderr);
1179                 rc = -EINVAL;
1180         } else {
1181                 rc = yaml_lnet_cpt_of_nid_display(&reply);
1182         }
1183         yaml_emitter_delete(&request);
1184 free_reply:
1185         if (rc == 0) {
1186                 yaml_lnet_print_error(NLM_F_DUMP, "cpt-of-nid",
1187                                       yaml_parser_get_reader_error(&reply));
1188                 rc = -EINVAL;
1189         }
1190
1191         yaml_parser_delete(&reply);
1192         nl_socket_free(sk);
1193
1194         return rc == 1 ? 0 : rc;
1195 }
1196
1197 static int jt_calc_cpt_of_nid(int argc, char **argv)
1198 {
1199         int rc, opt;
1200         const char *const short_options = "h";
1201         static const struct option long_options[] = {
1202         { .name = "help", .val = 'h' },
1203         { .name = NULL } };
1204
1205         rc = check_cmd(cmd_list, "", "cpt-of-nid", 2, argc, argv);
1206         if (rc)
1207                 return rc;
1208
1209         while ((opt = getopt_long(argc, argv, short_options,
1210                                    long_options, NULL)) != -1) {
1211                 switch (opt) {
1212                 case 'h':
1213                 case '?':
1214                         print_help(cmd_list, "", "cpt-of-nid");
1215                 default:
1216                         return 0;
1217                 }
1218         }
1219
1220         rc = yaml_lnet_cpt_of_nid(optind, argc, argv);
1221         if (rc == -EOPNOTSUPP)
1222                 printf("Operation not supported\n");
1223
1224         return rc;
1225 }
1226
1227 static int jt_config_lnet(int argc, char **argv)
1228 {
1229         struct cYAML *err_rc = NULL;
1230         bool load_mod_params = false;
1231         int flags = NLM_F_CREATE;
1232         const char *msg = NULL;
1233         int rc, opt;
1234
1235         const char *const short_options = "a";
1236         static const struct option long_options[] = {
1237                 { .name = "all",  .has_arg = no_argument, .val = 'a' },
1238                 { .name = NULL }
1239         };
1240
1241         rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
1242         if (rc)
1243                 return rc;
1244
1245         while ((opt = getopt_long(argc, argv, short_options,
1246                                    long_options, NULL)) != -1) {
1247                 switch (opt) {
1248                 case 'a':
1249                         load_mod_params = true;
1250                         break;
1251                 default:
1252                         return 0;
1253                 }
1254         }
1255
1256         if (!load_mod_params)
1257                 flags |= NLM_F_EXCL;
1258
1259         rc = yaml_lnet_configure(flags, &msg);
1260         if (rc != -EOPNOTSUPP) {
1261                 if (rc < 0) {
1262                         char errstr[256];
1263
1264                         snprintf(errstr, sizeof(errstr),
1265                                  "LNet configure error: %s", msg);
1266                         yaml_lnet_print_error(flags, "lnet", errstr);
1267                 }
1268                 return rc;
1269         }
1270
1271         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
1272                                           -1, &err_rc);
1273
1274         if (rc != LUSTRE_CFG_RC_NO_ERR)
1275                 cYAML_print_tree2file(stderr, err_rc);
1276
1277         cYAML_free_tree(err_rc);
1278
1279         return rc;
1280 }
1281
1282 static int jt_unconfig_lnet(int argc, char **argv)
1283 {
1284         struct cYAML *err_rc = NULL;
1285         const char *msg = NULL;
1286         int rc;
1287
1288         rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
1289         if (rc)
1290                 return rc;
1291
1292         rc = yaml_lnet_configure(0, &msg);
1293         if (rc != -EOPNOTSUPP) {
1294                 if (rc < 0) {
1295                         char errstr[256];
1296
1297                         snprintf(errstr, sizeof(errstr),
1298                                  "LNet configure error: %s", msg);
1299                         yaml_lnet_print_error(0, "lnet", errstr);
1300                 }
1301                 return rc;
1302         }
1303
1304         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
1305
1306         if (rc != LUSTRE_CFG_RC_NO_ERR)
1307                 cYAML_print_tree2file(stderr, err_rc);
1308
1309         cYAML_free_tree(err_rc);
1310
1311         return rc;
1312 }
1313
1314 static int yaml_lnet_router_gateways(yaml_emitter_t *output, const char *nw,
1315                                      const char *gw, int hops, int prio,
1316                                      int sen)
1317 {
1318         char num[INT_STRING_LEN];
1319         yaml_event_t event;
1320         int rc;
1321
1322         yaml_mapping_start_event_initialize(&event, NULL,
1323                                             (yaml_char_t *)YAML_MAP_TAG, 1,
1324                                             YAML_BLOCK_MAPPING_STYLE);
1325         rc = yaml_emitter_emit(output, &event);
1326         if (rc == 0)
1327                 goto emitter_error;
1328
1329         if (nw) {
1330                 yaml_scalar_event_initialize(&event, NULL,
1331                                              (yaml_char_t *)YAML_STR_TAG,
1332                                              (yaml_char_t *)"net",
1333                                              strlen("net"), 1, 0,
1334                                              YAML_PLAIN_SCALAR_STYLE);
1335                 rc = yaml_emitter_emit(output, &event);
1336                 if (rc == 0)
1337                         goto emitter_error;
1338
1339                 yaml_scalar_event_initialize(&event, NULL,
1340                                              (yaml_char_t *)YAML_STR_TAG,
1341                                              (yaml_char_t *)nw,
1342                                              strlen(nw), 1, 0,
1343                                              YAML_PLAIN_SCALAR_STYLE);
1344                 rc = yaml_emitter_emit(output, &event);
1345                 if (rc == 0)
1346                         goto emitter_error;
1347         }
1348
1349         if (gw) {
1350                 yaml_scalar_event_initialize(&event, NULL,
1351                                              (yaml_char_t *)YAML_STR_TAG,
1352                                              (yaml_char_t *)"gateway",
1353                                              strlen("gateway"), 1, 0,
1354                                              YAML_PLAIN_SCALAR_STYLE);
1355                 rc = yaml_emitter_emit(output, &event);
1356                 if (rc == 0)
1357                         goto emitter_error;
1358
1359                 yaml_scalar_event_initialize(&event, NULL,
1360                                              (yaml_char_t *)YAML_STR_TAG,
1361                                              (yaml_char_t *)gw,
1362                                              strlen(gw), 1, 0,
1363                                              YAML_PLAIN_SCALAR_STYLE);
1364                 rc = yaml_emitter_emit(output, &event);
1365                 if (rc == 0)
1366                         goto emitter_error;
1367         }
1368
1369         if (hops != -1) {
1370                 yaml_scalar_event_initialize(&event, NULL,
1371                                              (yaml_char_t *)YAML_STR_TAG,
1372                                              (yaml_char_t *)"hop",
1373                                              strlen("hop"), 1, 0,
1374                                              YAML_PLAIN_SCALAR_STYLE);
1375                 rc = yaml_emitter_emit(output, &event);
1376                 if (rc == 0)
1377                         goto emitter_error;
1378
1379                 snprintf(num, sizeof(num), "%d", hops);
1380                 yaml_scalar_event_initialize(&event, NULL,
1381                                              (yaml_char_t *)YAML_INT_TAG,
1382                                              (yaml_char_t *)num,
1383                                              strlen(num), 1, 0,
1384                                              YAML_PLAIN_SCALAR_STYLE);
1385                 rc = yaml_emitter_emit(output, &event);
1386                 if (rc == 0)
1387                         goto emitter_error;
1388         }
1389
1390         if (prio != -1) {
1391                 yaml_scalar_event_initialize(&event, NULL,
1392                                              (yaml_char_t *)YAML_STR_TAG,
1393                                              (yaml_char_t *)"priority",
1394                                              strlen("priority"), 1, 0,
1395                                              YAML_PLAIN_SCALAR_STYLE);
1396                 rc = yaml_emitter_emit(output, &event);
1397                 if (rc == 0)
1398                         goto emitter_error;
1399
1400                 snprintf(num, sizeof(num), "%d", prio);
1401                 yaml_scalar_event_initialize(&event, NULL,
1402                                              (yaml_char_t *)YAML_INT_TAG,
1403                                              (yaml_char_t *)num,
1404                                              strlen(num), 1, 0,
1405                                              YAML_PLAIN_SCALAR_STYLE);
1406                 rc = yaml_emitter_emit(output, &event);
1407                 if (rc == 0)
1408                         goto emitter_error;
1409         }
1410
1411         if (sen != -1) {
1412                 yaml_scalar_event_initialize(&event, NULL,
1413                                              (yaml_char_t *)YAML_STR_TAG,
1414                                              (yaml_char_t *)"health_sensitivity",
1415                                              strlen("health_sensitivity"),
1416                                              1, 0,
1417                                              YAML_PLAIN_SCALAR_STYLE);
1418                 rc = yaml_emitter_emit(output, &event);
1419                 if (rc == 0)
1420                         goto emitter_error;
1421
1422                 snprintf(num, sizeof(num), "%d", sen);
1423                 yaml_scalar_event_initialize(&event, NULL,
1424                                              (yaml_char_t *)YAML_INT_TAG,
1425                                              (yaml_char_t *)num,
1426                                              strlen(num), 1, 0,
1427                                              YAML_PLAIN_SCALAR_STYLE);
1428                 rc = yaml_emitter_emit(output, &event);
1429                 if (rc == 0)
1430                         goto emitter_error;
1431         }
1432
1433         yaml_mapping_end_event_initialize(&event);
1434         rc = yaml_emitter_emit(output, &event);
1435 emitter_error:
1436         return rc;
1437 }
1438
1439 static int yaml_lnet_route(char *nw, char *gw, int hops, int prio, int sen,
1440                            int version, int flags, FILE *fp)
1441 {
1442         struct nid_node head, *entry;
1443         struct nl_sock *sk = NULL;
1444         const char *msg = NULL;
1445         yaml_emitter_t output;
1446         yaml_parser_t reply;
1447         yaml_event_t event;
1448         int rc;
1449
1450         if (!(flags & NLM_F_DUMP) && (!nw || !gw)) {
1451                 fprintf(stdout, "missing mandatory parameters:'%s'\n",
1452                         (!nw && !gw) ? "net , gateway" :
1453                         !nw ? "net" : "gateway");
1454                 return -EINVAL;
1455         }
1456
1457         /* Create Netlink emitter to send request to kernel */
1458         sk = nl_socket_alloc();
1459         if (!sk)
1460                 return -EOPNOTSUPP;
1461
1462         /* Setup parser to receive Netlink packets */
1463         rc = yaml_parser_initialize(&reply);
1464         if (rc == 0) {
1465                 nl_socket_free(sk);
1466                 return -EOPNOTSUPP;
1467         }
1468
1469         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1470         if (rc == 0) {
1471                 msg = yaml_parser_get_reader_error(&reply);
1472                 goto free_reply;
1473         }
1474
1475         /* Create Netlink emitter to send request to kernel */
1476         rc = yaml_emitter_initialize(&output);
1477         if (rc == 0) {
1478                 msg = "failed to initialize emitter";
1479                 goto free_reply;
1480         }
1481
1482         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1483                                              version, LNET_CMD_ROUTES, flags);
1484         if (rc == 0)
1485                 goto emitter_error;
1486
1487         yaml_emitter_open(&output);
1488         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1489         rc = yaml_emitter_emit(&output, &event);
1490         if (rc == 0)
1491                 goto emitter_error;
1492
1493         yaml_mapping_start_event_initialize(&event, NULL,
1494                                             (yaml_char_t *)YAML_MAP_TAG,
1495                                             1, YAML_ANY_MAPPING_STYLE);
1496         rc = yaml_emitter_emit(&output, &event);
1497         if (rc == 0)
1498                 goto emitter_error;
1499
1500         yaml_scalar_event_initialize(&event, NULL,
1501                                      (yaml_char_t *)YAML_STR_TAG,
1502                                      (yaml_char_t *)"route",
1503                                      strlen("route"), 1, 0,
1504                                      YAML_PLAIN_SCALAR_STYLE);
1505         rc = yaml_emitter_emit(&output, &event);
1506         if (rc == 0)
1507                 goto emitter_error;
1508
1509         /* NLM_F_DUMP can have no arguments */
1510         if (nw || gw) {
1511                 NL_INIT_LIST_HEAD(&head.children);
1512                 nl_init_list_head(&head.list);
1513                 if (gw) {
1514                         rc = lustre_lnet_parse_nid_range(&head, gw, &msg);
1515                         if (rc < 0) {
1516                                 lustre_lnet_free_list(&head);
1517                                 yaml_emitter_delete(&output);
1518                                 errno = rc;
1519                                 rc = 0;
1520                                 goto free_reply;
1521                         }
1522                 }
1523
1524                 yaml_sequence_start_event_initialize(&event, NULL,
1525                                                      (yaml_char_t *)YAML_SEQ_TAG,
1526                                                      1,
1527                                                      YAML_BLOCK_SEQUENCE_STYLE);
1528                 rc = yaml_emitter_emit(&output, &event);
1529                 if (rc == 0)
1530                         goto emitter_error;
1531
1532                 if (!nl_list_empty(&head.children)) {
1533                         nl_list_for_each_entry(entry, &head.children, list) {
1534                                 const char *nid = entry->nidstr;
1535
1536                                 rc = yaml_lnet_router_gateways(&output, nw, nid,
1537                                                                hops, prio, sen);
1538                                 if (rc == 0)
1539                                         goto emitter_error;
1540                         }
1541                 } else {
1542                         rc = yaml_lnet_router_gateways(&output, nw, NULL, hops,
1543                                                        prio, sen);
1544                         if (rc == 0)
1545                                 goto emitter_error;
1546                 }
1547
1548                 yaml_sequence_end_event_initialize(&event);
1549                 rc = yaml_emitter_emit(&output, &event);
1550                 if (rc == 0)
1551                         goto emitter_error;
1552         } else {
1553                 yaml_scalar_event_initialize(&event, NULL,
1554                                              (yaml_char_t *)YAML_STR_TAG,
1555                                              (yaml_char_t *)"",
1556                                              strlen(""), 1, 0,
1557                                              YAML_PLAIN_SCALAR_STYLE);
1558                 rc = yaml_emitter_emit(&output, &event);
1559                 if (rc == 0)
1560                         goto emitter_error;
1561         }
1562
1563         yaml_mapping_end_event_initialize(&event);
1564         rc = yaml_emitter_emit(&output, &event);
1565         if (rc == 0)
1566                 goto emitter_error;
1567
1568         yaml_document_end_event_initialize(&event, 0);
1569         rc = yaml_emitter_emit(&output, &event);
1570         if (rc == 0)
1571                 goto emitter_error;
1572
1573         rc = yaml_emitter_close(&output);
1574 emitter_error:
1575         if (rc == 0) {
1576                 yaml_emitter_log_error(&output, stderr);
1577                 rc = -EINVAL;
1578         } else {
1579                 yaml_document_t errmsg;
1580
1581                 rc = yaml_parser_load(&reply, &errmsg);
1582                 if (rc == 1 && (flags & NLM_F_DUMP)) {
1583                         yaml_emitter_t debug;
1584
1585                         rc = yaml_emitter_initialize(&debug);
1586                         if (rc == 1) {
1587                                 yaml_emitter_set_indent(&debug,
1588                                                         LNET_DEFAULT_INDENT);
1589                                 yaml_emitter_set_output_file(&debug, fp);
1590                                 rc = yaml_emitter_dump(&debug, &errmsg);
1591                         }
1592                         yaml_emitter_delete(&debug);
1593                 } else {
1594                         msg = yaml_parser_get_reader_error(&reply);
1595                         /* If we didn't find any routes just be silent */
1596                         if (msg && strcmp(msg, "No routes found") == 0)
1597                                 rc = 1;
1598                 }
1599                 yaml_document_delete(&errmsg);
1600         }
1601         yaml_emitter_delete(&output);
1602 free_reply:
1603         if (rc == 0) {
1604                 yaml_lnet_print_error(flags, "route", msg);
1605                 rc = -EINVAL;
1606         }
1607         yaml_parser_delete(&reply);
1608         nl_socket_free(sk);
1609
1610         return rc == 1 ? 0 : rc;
1611 }
1612
1613 static int jt_add_route(int argc, char **argv)
1614 {
1615         char *network = NULL, *gateway = NULL;
1616         long int hop = -1, prio = -1, sen = -1;
1617         struct cYAML *err_rc = NULL;
1618         int rc, opt;
1619
1620         const char *const short_options = "n:g:c:p:";
1621         static const struct option long_options[] = {
1622                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
1623                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1624                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
1625                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1626                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1627                 { .name = "health_sensitivity",  .has_arg = required_argument, .val = 's' },
1628                 { .name = NULL }
1629         };
1630
1631         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
1632         if (rc)
1633                 return rc;
1634
1635         while ((opt = getopt_long(argc, argv, short_options,
1636                                    long_options, NULL)) != -1) {
1637                 switch (opt) {
1638                 case 'n':
1639                         network = optarg;
1640                         break;
1641                 case 'g':
1642                         gateway = optarg;
1643                         break;
1644                 case 'c':
1645                         rc = parse_long(optarg, &hop);
1646                         if (rc != 0) {
1647                                 /* ignore option */
1648                                 hop = -1;
1649                                 continue;
1650                         }
1651                         break;
1652                 case 'p':
1653                         rc = parse_long(optarg, &prio);
1654                         if (rc != 0) {
1655                                 /* ingore option */
1656                                 prio = -1;
1657                                 continue;
1658                         }
1659                         break;
1660                 case 's':
1661                         rc = parse_long(optarg, &sen);
1662                         if (rc != 0) {
1663                                 /* ingore option */
1664                                 sen = -1;
1665                                 continue;
1666                         }
1667                         break;
1668
1669                 case '?':
1670                         print_help(route_cmds, "route", "add");
1671                 default:
1672                         return 0;
1673                 }
1674         }
1675
1676         rc = yaml_lnet_route(network, gateway, hop, prio, sen,
1677                              LNET_GENL_VERSION, NLM_F_CREATE, stdout);
1678         if (rc <= 0) {
1679                 if (rc == -EOPNOTSUPP)
1680                         goto old_api;
1681                 return rc;
1682         }
1683 old_api:
1684         rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
1685                                       &err_rc);
1686
1687         if (rc != LUSTRE_CFG_RC_NO_ERR)
1688                 cYAML_print_tree2file(stderr, err_rc);
1689
1690         cYAML_free_tree(err_rc);
1691
1692         return rc;
1693 }
1694
1695 static int yaml_add_ni_tunables(yaml_emitter_t *output,
1696                                 struct lnet_ioctl_config_lnd_tunables *tunables,
1697                                 struct lnet_dlc_network_descr *nw_descr)
1698 {
1699         char num[INT_STRING_LEN];
1700         yaml_event_t event;
1701         int rc = 0;
1702
1703         if (tunables->lt_cmn.lct_peer_timeout < 0 &&
1704             tunables->lt_cmn.lct_peer_tx_credits <= 0 &&
1705             tunables->lt_cmn.lct_peer_rtr_credits <= 0 &&
1706             tunables->lt_cmn.lct_max_tx_credits <= 0)
1707                 goto skip_general_settings;
1708
1709         yaml_scalar_event_initialize(&event, NULL,
1710                                      (yaml_char_t *)YAML_STR_TAG,
1711                                      (yaml_char_t *)"tunables",
1712                                      strlen("tunables"), 1, 0,
1713                                      YAML_PLAIN_SCALAR_STYLE);
1714         rc = yaml_emitter_emit(output, &event);
1715         if (rc == 0)
1716                 goto error;
1717
1718         yaml_mapping_start_event_initialize(&event, NULL,
1719                                             (yaml_char_t *)YAML_MAP_TAG,
1720                                             1, YAML_ANY_MAPPING_STYLE);
1721         rc = yaml_emitter_emit(output, &event);
1722         if (rc == 0)
1723                 goto error;
1724
1725         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1726                 yaml_scalar_event_initialize(&event, NULL,
1727                                              (yaml_char_t *)YAML_STR_TAG,
1728                                              (yaml_char_t *)"peer_timeout",
1729                                              strlen("peer_timeout"), 1, 0,
1730                                              YAML_PLAIN_SCALAR_STYLE);
1731                 rc = yaml_emitter_emit(output, &event);
1732                 if (rc == 0)
1733                         goto error;
1734
1735                 snprintf(num, sizeof(num), "%u",
1736                          tunables->lt_cmn.lct_peer_timeout);
1737                 yaml_scalar_event_initialize(&event, NULL,
1738                                              (yaml_char_t *)YAML_INT_TAG,
1739                                              (yaml_char_t *)num,
1740                                              strlen(num), 1, 0,
1741                                              YAML_PLAIN_SCALAR_STYLE);
1742                 rc = yaml_emitter_emit(output, &event);
1743                 if (rc == 0)
1744                         goto error;
1745         }
1746
1747         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1748                 yaml_scalar_event_initialize(&event, NULL,
1749                                              (yaml_char_t *)YAML_STR_TAG,
1750                                              (yaml_char_t *)"peer_credits",
1751                                              strlen("peer_credits"), 1, 0,
1752                                              YAML_PLAIN_SCALAR_STYLE);
1753                 rc = yaml_emitter_emit(output, &event);
1754                 if (rc == 0)
1755                         goto error;
1756
1757                 snprintf(num, sizeof(num), "%u",
1758                          tunables->lt_cmn.lct_peer_tx_credits);
1759                 yaml_scalar_event_initialize(&event, NULL,
1760                                              (yaml_char_t *)YAML_INT_TAG,
1761                                              (yaml_char_t *)num,
1762                                              strlen(num), 1, 0,
1763                                              YAML_PLAIN_SCALAR_STYLE);
1764                 rc = yaml_emitter_emit(output, &event);
1765                 if (rc == 0)
1766                         goto error;
1767         }
1768
1769         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1770                 yaml_scalar_event_initialize(&event, NULL,
1771                                              (yaml_char_t *)YAML_STR_TAG,
1772                                              (yaml_char_t *)"peer_buffer_credits",
1773                                              strlen("peer_buffer_credits"), 1, 0,
1774                                              YAML_PLAIN_SCALAR_STYLE);
1775                 rc = yaml_emitter_emit(output, &event);
1776                 if (rc == 0)
1777                         goto error;
1778
1779                 snprintf(num, sizeof(num), "%u",
1780                          tunables->lt_cmn.lct_peer_rtr_credits);
1781                 yaml_scalar_event_initialize(&event, NULL,
1782                                              (yaml_char_t *)YAML_INT_TAG,
1783                                              (yaml_char_t *)num,
1784                                              strlen(num), 1, 0,
1785                                              YAML_PLAIN_SCALAR_STYLE);
1786                 rc = yaml_emitter_emit(output, &event);
1787                 if (rc == 0)
1788                         goto error;
1789         }
1790
1791         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1792                 yaml_scalar_event_initialize(&event, NULL,
1793                                              (yaml_char_t *)YAML_STR_TAG,
1794                                              (yaml_char_t *)"credits",
1795                                              strlen("credits"), 1, 0,
1796                                              YAML_PLAIN_SCALAR_STYLE);
1797                 rc = yaml_emitter_emit(output, &event);
1798                 if (rc == 0)
1799                         goto error;
1800
1801                 snprintf(num, sizeof(num), "%u",
1802                          tunables->lt_cmn.lct_max_tx_credits);
1803                 yaml_scalar_event_initialize(&event, NULL,
1804                                              (yaml_char_t *)YAML_INT_TAG,
1805                                              (yaml_char_t *)num,
1806                                              strlen(num), 1, 0,
1807                                              YAML_PLAIN_SCALAR_STYLE);
1808                 rc = yaml_emitter_emit(output, &event);
1809                 if (rc == 0)
1810                         goto error;
1811         }
1812
1813         yaml_mapping_end_event_initialize(&event);
1814         rc = yaml_emitter_emit(output, &event);
1815         if (rc == 0)
1816                 goto error;
1817
1818 skip_general_settings:
1819         if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1820 #ifdef HAVE_KFILND
1821             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0 ||
1822             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0] ||
1823 #endif
1824             tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1825                 yaml_scalar_event_initialize(&event, NULL,
1826                                              (yaml_char_t *)YAML_STR_TAG,
1827                                              (yaml_char_t *)"lnd tunables",
1828                                              strlen("lnd tunables"), 1, 0,
1829                                              YAML_PLAIN_SCALAR_STYLE);
1830                 rc = yaml_emitter_emit(output, &event);
1831                 if (rc == 0)
1832                         goto 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 error;
1840 #ifdef HAVE_KFILND
1841                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1842                         yaml_scalar_event_initialize(&event, NULL,
1843                                                      (yaml_char_t *)YAML_STR_TAG,
1844                                                      (yaml_char_t *)"auth_key",
1845                                                      strlen("auth_key"), 1, 0,
1846                                                      YAML_PLAIN_SCALAR_STYLE);
1847                         rc = yaml_emitter_emit(output, &event);
1848                         if (rc == 0)
1849                                 goto error;
1850
1851                         snprintf(num, sizeof(num), "%u",
1852                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1853
1854                         yaml_scalar_event_initialize(&event, NULL,
1855                                                      (yaml_char_t *)YAML_INT_TAG,
1856                                                      (yaml_char_t *)num,
1857                                                      strlen(num), 1, 0,
1858                                                      YAML_PLAIN_SCALAR_STYLE);
1859                         rc = yaml_emitter_emit(output, &event);
1860                         if (rc == 0)
1861                                 goto error;
1862                 }
1863
1864                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0]) {
1865                         char *tc = &tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0];
1866
1867                         yaml_scalar_event_initialize(&event, NULL,
1868                                                      (yaml_char_t *)YAML_STR_TAG,
1869                                                      (yaml_char_t *)"traffic_class",
1870                                                      strlen("traffic_class"), 1, 0,
1871                                                      YAML_PLAIN_SCALAR_STYLE);
1872                         rc = yaml_emitter_emit(output, &event);
1873                         if (rc == 0)
1874                                 goto error;
1875
1876                         yaml_scalar_event_initialize(&event, NULL,
1877                                                      (yaml_char_t *)YAML_INT_TAG,
1878                                                      (yaml_char_t *)tc,
1879                                                      strlen(tc), 1, 0,
1880                                                      YAML_PLAIN_SCALAR_STYLE);
1881
1882                         rc = yaml_emitter_emit(output, &event);
1883                         if (rc == 0)
1884                                 goto error;
1885                 }
1886 #endif
1887                 if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1888                     tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1889                         int cpp = 0;
1890
1891                         yaml_scalar_event_initialize(&event, NULL,
1892                                                      (yaml_char_t *)YAML_STR_TAG,
1893                                                      (yaml_char_t *)"conns_per_peer",
1894                                                      strlen("conns_per_peer"), 1, 0,
1895                                                      YAML_PLAIN_SCALAR_STYLE);
1896                         rc = yaml_emitter_emit(output, &event);
1897                         if (rc == 0)
1898                                 goto error;
1899
1900                         if (nw_descr->nw_id == LNET_NET_ANY)
1901                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1902                         else if (LNET_NETTYP(nw_descr->nw_id) == SOCKLND)
1903                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1904                         else if (LNET_NETTYP(nw_descr->nw_id) == O2IBLND)
1905                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer;
1906                         snprintf(num, sizeof(num), "%u", cpp);
1907
1908                         yaml_scalar_event_initialize(&event, NULL,
1909                                                      (yaml_char_t *)YAML_INT_TAG,
1910                                                      (yaml_char_t *)num,
1911                                                      strlen(num), 1, 0,
1912                                                      YAML_PLAIN_SCALAR_STYLE);
1913                         rc = yaml_emitter_emit(output, &event);
1914                         if (rc == 0)
1915                                 goto error;
1916                 }
1917
1918                 yaml_mapping_end_event_initialize(&event);
1919                 rc = yaml_emitter_emit(output, &event);
1920         }
1921 error:
1922         return rc;
1923 }
1924
1925 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1926                                struct lnet_dlc_network_descr *nw_descr,
1927                                struct lnet_ioctl_config_lnd_tunables *tunables,
1928                                int healthv, struct cfs_expr_list *global_cpts,
1929                                int version, int flags, FILE *fp)
1930 {
1931         struct lnet_dlc_intf_descr *intf;
1932         struct nl_sock *sk = NULL;
1933         const char *msg = NULL;
1934         yaml_emitter_t output;
1935         yaml_parser_t reply;
1936         yaml_event_t event;
1937         int rc;
1938
1939         if (!(flags & NLM_F_DUMP) && !ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1940                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'\n",
1941                         (!nw_descr) ? "network , interface" :
1942                         (nw_descr->nw_id == 0) ? "network" : "interface");
1943                 return -EINVAL;
1944         }
1945
1946         if ((flags == NLM_F_CREATE) && !ip2net && list_empty(&nw_descr->nw_intflist)) {
1947                 fprintf(stdout, "creating a local NI needs at least one interface\n");
1948                 return -EINVAL;
1949         }
1950
1951         if ((flags == NLM_F_REPLACE) && list_empty(&nw_descr->nw_intflist)) {
1952                 fprintf(stdout, "updating a local NI needs at least one address\n");
1953                 return -EINVAL;
1954         }
1955
1956         /* Create Netlink emitter to send request to kernel */
1957         sk = nl_socket_alloc();
1958         if (!sk)
1959                 return -EOPNOTSUPP;
1960
1961         /* Setup parser to receive Netlink packets */
1962         rc = yaml_parser_initialize(&reply);
1963         if (rc == 0) {
1964                 nl_socket_free(sk);
1965                 return -EOPNOTSUPP;
1966         }
1967
1968         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1969         if (rc == 0) {
1970                 msg = yaml_parser_get_reader_error(&reply);
1971                 goto free_reply;
1972         }
1973
1974         /* Create Netlink emitter to send request to kernel */
1975         rc = yaml_emitter_initialize(&output);
1976         if (rc == 0) {
1977                 msg = "failed to initialize emitter";
1978                 goto free_reply;
1979         }
1980
1981         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1982                                              version, LNET_CMD_NETS, flags);
1983         if (rc == 0)
1984                 goto emitter_error;
1985
1986         yaml_emitter_open(&output);
1987         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1988         rc = yaml_emitter_emit(&output, &event);
1989         if (rc == 0)
1990                 goto emitter_error;
1991
1992         yaml_mapping_start_event_initialize(&event, NULL,
1993                                             (yaml_char_t *)YAML_MAP_TAG,
1994                                             1, YAML_ANY_MAPPING_STYLE);
1995         rc = yaml_emitter_emit(&output, &event);
1996         if (rc == 0)
1997                 goto emitter_error;
1998
1999         yaml_scalar_event_initialize(&event, NULL,
2000                                      (yaml_char_t *)YAML_STR_TAG,
2001                                      (yaml_char_t *)"net",
2002                                      strlen("net"), 1, 0,
2003                                      YAML_PLAIN_SCALAR_STYLE);
2004         rc = yaml_emitter_emit(&output, &event);
2005         if (rc == 0)
2006                 goto emitter_error;
2007
2008         if (net_id || ip2net) {
2009                 char *key = net_id ? "net type" : "ip2net";
2010                 char *value = net_id ? net_id : ip2net;
2011
2012                 yaml_sequence_start_event_initialize(&event, NULL,
2013                                                      (yaml_char_t *)YAML_SEQ_TAG,
2014                                                      1, YAML_ANY_SEQUENCE_STYLE);
2015                 rc = yaml_emitter_emit(&output, &event);
2016                 if (rc == 0)
2017                         goto emitter_error;
2018
2019                 yaml_mapping_start_event_initialize(&event, NULL,
2020                                                     (yaml_char_t *)YAML_MAP_TAG,
2021                                                     1, YAML_ANY_MAPPING_STYLE);
2022                 rc = yaml_emitter_emit(&output, &event);
2023                 if (rc == 0)
2024                         goto emitter_error;
2025
2026                 yaml_scalar_event_initialize(&event, NULL,
2027                                              (yaml_char_t *)YAML_STR_TAG,
2028                                              (yaml_char_t *)key,
2029                                              strlen(key),
2030                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
2031                 rc = yaml_emitter_emit(&output, &event);
2032                 if (rc == 0)
2033                         goto emitter_error;
2034
2035                 yaml_scalar_event_initialize(&event, NULL,
2036                                              (yaml_char_t *)YAML_STR_TAG,
2037                                              (yaml_char_t *)value,
2038                                              strlen(value), 1, 0,
2039                                              YAML_PLAIN_SCALAR_STYLE);
2040                 rc = yaml_emitter_emit(&output, &event);
2041                 if (rc == 0)
2042                         goto emitter_error;
2043         } else {
2044                 yaml_scalar_event_initialize(&event, NULL,
2045                                              (yaml_char_t *)YAML_STR_TAG,
2046                                              (yaml_char_t *)"",
2047                                              strlen(""), 1, 0,
2048                                              YAML_PLAIN_SCALAR_STYLE);
2049                 rc = yaml_emitter_emit(&output, &event);
2050                 if (rc == 0)
2051                         goto emitter_error;
2052
2053                 goto no_net_id;
2054         }
2055
2056         if (!nw_descr || list_empty(&nw_descr->nw_intflist))
2057                 goto skip_intf;
2058
2059         yaml_scalar_event_initialize(&event, NULL,
2060                                      (yaml_char_t *)YAML_STR_TAG,
2061                                      (yaml_char_t *)"local NI(s)",
2062                                      strlen("local NI(s)"), 1, 0,
2063                                      YAML_PLAIN_SCALAR_STYLE);
2064         rc = yaml_emitter_emit(&output, &event);
2065         if (rc == 0)
2066                 goto emitter_error;
2067
2068         yaml_sequence_start_event_initialize(&event, NULL,
2069                                              (yaml_char_t *)YAML_SEQ_TAG,
2070                                              1, YAML_ANY_SEQUENCE_STYLE);
2071         rc = yaml_emitter_emit(&output, &event);
2072         if (rc == 0)
2073                 goto emitter_error;
2074
2075         list_for_each_entry(intf, &nw_descr->nw_intflist,
2076                             intf_on_network) {
2077                 yaml_mapping_start_event_initialize(&event, NULL,
2078                                                     (yaml_char_t *)YAML_MAP_TAG,
2079                                                     1, YAML_ANY_MAPPING_STYLE);
2080                 rc = yaml_emitter_emit(&output, &event);
2081                 if (rc == 0)
2082                         goto emitter_error;
2083
2084                 /* Use NI addresses instead of interface */
2085                 if (strchr(intf->intf_name, '@') ||
2086                     (strcmp(intf->intf_name, "<?>") == 0 &&
2087 -                    flags == NLM_F_REPLACE)) {
2088                         yaml_scalar_event_initialize(&event, NULL,
2089                                                      (yaml_char_t *)YAML_STR_TAG,
2090                                                      (yaml_char_t *)"nid",
2091                                                      strlen("nid"), 1, 0,
2092                                                      YAML_PLAIN_SCALAR_STYLE);
2093                         rc = yaml_emitter_emit(&output, &event);
2094                         if (rc == 0)
2095                                 goto emitter_error;
2096
2097                         yaml_scalar_event_initialize(&event, NULL,
2098                                                      (yaml_char_t *)YAML_STR_TAG,
2099                                                      (yaml_char_t *)intf->intf_name,
2100                                                      strlen(intf->intf_name), 1, 0,
2101                                                      YAML_PLAIN_SCALAR_STYLE);
2102                         rc = yaml_emitter_emit(&output, &event);
2103                         if (rc == 0)
2104                                 goto emitter_error;
2105                 } else {
2106                         yaml_scalar_event_initialize(&event, NULL,
2107                                                      (yaml_char_t *)YAML_STR_TAG,
2108                                                      (yaml_char_t *)"interfaces",
2109                                                      strlen("interfaces"), 1, 0,
2110                                                      YAML_PLAIN_SCALAR_STYLE);
2111                         rc = yaml_emitter_emit(&output, &event);
2112                         if (rc == 0)
2113                                 goto emitter_error;
2114
2115                         yaml_mapping_start_event_initialize(&event, NULL,
2116                                                             (yaml_char_t *)YAML_MAP_TAG,
2117                                                             1, YAML_ANY_MAPPING_STYLE);
2118                         rc = yaml_emitter_emit(&output, &event);
2119                         if (rc == 0)
2120                                 goto emitter_error;
2121
2122                         yaml_scalar_event_initialize(&event, NULL,
2123                                                      (yaml_char_t *)YAML_STR_TAG,
2124                                                      (yaml_char_t *)"0",
2125                                                      strlen("0"), 1, 0,
2126                                                      YAML_PLAIN_SCALAR_STYLE);
2127                         rc = yaml_emitter_emit(&output, &event);
2128                         if (rc == 0)
2129                                 goto emitter_error;
2130
2131                         yaml_scalar_event_initialize(&event, NULL,
2132                                                      (yaml_char_t *)YAML_STR_TAG,
2133                                                      (yaml_char_t *)intf->intf_name,
2134                                                      strlen(intf->intf_name), 1, 0,
2135                                                      YAML_PLAIN_SCALAR_STYLE);
2136                         rc = yaml_emitter_emit(&output, &event);
2137                         if (rc == 0)
2138                                 goto emitter_error;
2139
2140                         yaml_mapping_end_event_initialize(&event);
2141                         rc = yaml_emitter_emit(&output, &event);
2142                         if (rc == 0)
2143                                 goto emitter_error;
2144                 }
2145
2146                 if (tunables) {
2147                         rc = yaml_add_ni_tunables(&output, tunables, nw_descr);
2148                         if (rc == 0)
2149                                 goto emitter_error;
2150                 }
2151
2152                 if (flags == NLM_F_REPLACE && healthv > -1) {
2153                         char health[INT_STRING_LEN];
2154
2155                         yaml_scalar_event_initialize(&event, NULL,
2156                                                      (yaml_char_t *)YAML_STR_TAG,
2157                                                      (yaml_char_t *)"health stats",
2158                                                      strlen("health stats"), 1, 0,
2159                                                      YAML_PLAIN_SCALAR_STYLE);
2160                         rc = yaml_emitter_emit(&output, &event);
2161                         if (rc == 0)
2162                                 goto emitter_error;
2163
2164                         /* Setup all mappings for data related to the 'health stats' */
2165                         yaml_mapping_start_event_initialize(&event, NULL,
2166                                                             (yaml_char_t *)YAML_MAP_TAG,
2167                                                             1, YAML_BLOCK_MAPPING_STYLE);
2168                         rc = yaml_emitter_emit(&output, &event);
2169                         if (rc == 0)
2170                                 goto emitter_error;
2171
2172                         yaml_scalar_event_initialize(&event, NULL,
2173                                                      (yaml_char_t *)YAML_STR_TAG,
2174                                                      (yaml_char_t *)"health value",
2175                                                      strlen("health value"), 1, 0,
2176                                                      YAML_PLAIN_SCALAR_STYLE);
2177                         rc = yaml_emitter_emit(&output, &event);
2178                         if (rc == 0)
2179                                 goto emitter_error;
2180
2181                         snprintf(health, sizeof(health), "%d", healthv);
2182                         yaml_scalar_event_initialize(&event, NULL,
2183                                                      (yaml_char_t *)YAML_INT_TAG,
2184                                                      (yaml_char_t *)health,
2185                                                      strlen(health), 1, 0,
2186                                                      YAML_PLAIN_SCALAR_STYLE);
2187                         rc = yaml_emitter_emit(&output, &event);
2188                         if (rc == 0)
2189                                 goto emitter_error;
2190
2191                         yaml_mapping_end_event_initialize(&event);
2192                         rc = yaml_emitter_emit(&output, &event);
2193                         if (rc == 0)
2194                                 goto emitter_error;
2195                 }
2196
2197                 if (global_cpts) {
2198                         __u32 *cpt_array;
2199                         int count, i;
2200
2201                         yaml_scalar_event_initialize(&event, NULL,
2202                                                      (yaml_char_t *)YAML_STR_TAG,
2203                                                      (yaml_char_t *)"CPT",
2204                                                      strlen("CPT"), 1, 0,
2205                                                      YAML_PLAIN_SCALAR_STYLE);
2206                         rc = yaml_emitter_emit(&output, &event);
2207                         if (rc == 0)
2208                                 goto emitter_error;
2209
2210                         yaml_sequence_start_event_initialize(&event, NULL,
2211                                                              (yaml_char_t *)YAML_SEQ_TAG,
2212                                                              1,
2213                                                              YAML_FLOW_SEQUENCE_STYLE);
2214                         rc = yaml_emitter_emit(&output, &event);
2215                         if (rc == 0)
2216                                 goto emitter_error;
2217
2218                         count = cfs_expr_list_values(global_cpts,
2219                                                      LNET_MAX_SHOW_NUM_CPT,
2220                                                      &cpt_array);
2221                         for (i = 0; i < count; i++) {
2222                                 char core[INT_STRING_LEN];
2223
2224                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
2225                                 yaml_scalar_event_initialize(&event, NULL,
2226                                                              (yaml_char_t *)YAML_STR_TAG,
2227                                                              (yaml_char_t *)core,
2228                                                              strlen(core), 1, 0,
2229                                                              YAML_PLAIN_SCALAR_STYLE);
2230                                 rc = yaml_emitter_emit(&output, &event);
2231                                 if (rc == 0)
2232                                         goto emitter_error;
2233                         }
2234
2235                         yaml_sequence_end_event_initialize(&event);
2236                         rc = yaml_emitter_emit(&output, &event);
2237                         if (rc == 0)
2238                                 goto emitter_error;
2239
2240                         cfs_expr_list_free(global_cpts);
2241                         free(cpt_array);
2242                 }
2243
2244                 yaml_mapping_end_event_initialize(&event);
2245                 rc = yaml_emitter_emit(&output, &event);
2246                 if (rc == 0)
2247                         goto emitter_error;
2248         }
2249
2250         yaml_sequence_end_event_initialize(&event);
2251         rc = yaml_emitter_emit(&output, &event);
2252         if (rc == 0)
2253                 goto emitter_error;
2254 skip_intf:
2255         yaml_mapping_end_event_initialize(&event);
2256         rc = yaml_emitter_emit(&output, &event);
2257         if (rc == 0)
2258                 goto emitter_error;
2259
2260         yaml_sequence_end_event_initialize(&event);
2261         rc = yaml_emitter_emit(&output, &event);
2262         if (rc == 0)
2263                 goto emitter_error;
2264 no_net_id:
2265         yaml_mapping_end_event_initialize(&event);
2266         rc = yaml_emitter_emit(&output, &event);
2267         if (rc == 0)
2268                 goto emitter_error;
2269
2270         yaml_document_end_event_initialize(&event, 0);
2271         rc = yaml_emitter_emit(&output, &event);
2272         if (rc == 0)
2273                 goto emitter_error;
2274
2275         rc = yaml_emitter_close(&output);
2276 emitter_error:
2277         if (rc == 0) {
2278                 yaml_emitter_log_error(&output, stderr);
2279                 rc = -EINVAL;
2280         } else {
2281                 yaml_document_t errmsg;
2282
2283                 rc = yaml_parser_load(&reply, &errmsg);
2284                 if (rc == 1 && (flags & NLM_F_DUMP)) {
2285                         yaml_emitter_t debug;
2286
2287                         rc = yaml_emitter_initialize(&debug);
2288                         if (rc == 1) {
2289                                 yaml_emitter_set_indent(&debug,
2290                                                         LNET_DEFAULT_INDENT);
2291                                 yaml_emitter_set_output_file(&debug, fp);
2292                                 rc = yaml_emitter_dump(&debug, &errmsg);
2293                         }
2294                         yaml_emitter_delete(&debug);
2295                 } else {
2296                         msg = yaml_parser_get_reader_error(&reply);
2297                 }
2298                 yaml_document_delete(&errmsg);
2299         }
2300         yaml_emitter_delete(&output);
2301 free_reply:
2302         if (rc == 0) {
2303                 yaml_lnet_print_error(flags, "net", msg);
2304                 rc = -EINVAL;
2305         }
2306         yaml_parser_delete(&reply);
2307         nl_socket_free(sk);
2308
2309         return rc == 1 ? 0 : rc;
2310 }
2311
2312 static int jt_add_ni(int argc, char **argv)
2313 {
2314         char *ip2net = NULL;
2315         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
2316         char *traffic_class = NULL;
2317         struct cYAML *err_rc = NULL;
2318         int rc, opt, cpt_rc = -1;
2319         struct lnet_dlc_network_descr nw_descr;
2320         struct cfs_expr_list *global_cpts = NULL;
2321         struct lnet_ioctl_config_lnd_tunables tunables;
2322         bool found = false;
2323         bool skip_mr_route_setup = false;
2324         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:T:";
2325         static const struct option long_options[] = {
2326         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
2327         { .name = "peer-buffer-credits",
2328                                   .has_arg = required_argument, .val = 'b' },
2329         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
2330         { .name = "if",           .has_arg = required_argument, .val = 'i' },
2331         { .name = "skip-mr-route-setup",
2332                                   .has_arg = no_argument, .val = 'k' },
2333         { .name = "conns-per-peer",
2334                                   .has_arg = required_argument, .val = 'm' },
2335         { .name = "net",          .has_arg = required_argument, .val = 'n' },
2336         { .name = "nid",          .has_arg = required_argument, .val = 'N' },
2337         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
2338         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
2339         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
2340         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
2341         { .name = "traffic-class", .has_arg = required_argument, .val = 'T' },
2342         { .name = NULL } };
2343         bool nid_request = false;
2344         char *net_id = NULL;
2345
2346         memset(&tunables, 0, sizeof(tunables));
2347         lustre_lnet_init_nw_descr(&nw_descr);
2348
2349         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
2350         if (rc)
2351                 return rc;
2352
2353         while ((opt = getopt_long(argc, argv, short_options,
2354                                    long_options, NULL)) != -1) {
2355                 switch (opt) {
2356                 case 'a':
2357                         rc = parse_long(optarg, &auth_key);
2358                         if (rc != 0) {
2359                                 /* ignore option */
2360                                 auth_key = -1;
2361                                 continue;
2362                         }
2363                         break;
2364                 case 'b':
2365                         rc = parse_long(optarg, &pbc);
2366                         if (rc != 0) {
2367                                 /* ignore option */
2368                                 pbc = -1;
2369                                 continue;
2370                         }
2371                         break;
2372                 case 'c':
2373                         rc = parse_long(optarg, &pc);
2374                         if (rc != 0) {
2375                                 /* ignore option */
2376                                 pc = -1;
2377                                 continue;
2378                         }
2379                         break;
2380                 case 'i':
2381                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2382                         if (rc != 0) {
2383                                 cYAML_build_error(-1, -1, "ni", "add",
2384                                                 "bad interface list",
2385                                                 &err_rc);
2386                                 goto failed;
2387                         }
2388                         break;
2389                 case 'k':
2390                         skip_mr_route_setup = true;
2391                         break;
2392                 case 'm':
2393                         rc = parse_long(optarg, &cpp);
2394                         if (rc != 0) {
2395                                 /* ignore option */
2396                                 cpp = -1;
2397                                 continue;
2398                         }
2399                         break;
2400
2401                 case 'n':
2402                         nw_descr.nw_id = libcfs_str2net(optarg);
2403                         net_id = optarg;
2404                         break;
2405                 case 'N':
2406                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2407                         if (rc != 0) {
2408                                 cYAML_build_error(-1, -1, "ni", "add",
2409                                                 "bad NID list",
2410                                                 &err_rc);
2411                                 goto failed;
2412                         }
2413                         nid_request = true;
2414                         break;
2415                 case 'p':
2416                         ip2net = optarg;
2417                         break;
2418                 case 'r':
2419                         rc = parse_long(optarg, &cre);
2420                         if (rc != 0) {
2421                                 /* ignore option */
2422                                 cre = -1;
2423                                 continue;
2424                         }
2425                         break;
2426                 case 's':
2427                         cpt_rc = cfs_expr_list_parse(optarg,
2428                                                      strlen(optarg), 0,
2429                                                      UINT_MAX, &global_cpts);
2430                         break;
2431                 case 't':
2432                         rc = parse_long(optarg, &pto);
2433                         if (rc != 0) {
2434                                 /* ignore option */
2435                                 pto = -1;
2436                                 continue;
2437                         }
2438                         break;
2439                 case 'T':
2440                         traffic_class = optarg;
2441                         if (strlen(traffic_class) == 0 ||
2442                             strlen(traffic_class) >= LNET_MAX_STR_LEN) {
2443                                 cYAML_build_error(-1, -1, "ni", "add",
2444                                                   "Invalid traffic-class argument",
2445                                                   &err_rc);
2446                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2447                                 goto failed;
2448                         }
2449                         break;
2450                 case '?':
2451                         print_help(net_cmds, "net", "add");
2452                 default:
2453                         return 0;
2454                 }
2455         }
2456
2457         if (nid_request) {
2458                 if (net_id) {
2459                         fprintf(stdout, "--net is invalid with --nid option\n");
2460                         return -EINVAL;
2461                 }
2462                 net_id = libcfs_net2str(nw_descr.nw_id);
2463         }
2464 #ifdef HAVE_KFILND
2465         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
2466                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
2467                 found = true;
2468         }
2469
2470         if (traffic_class && LNET_NETTYP(nw_descr.nw_id) == KFILND &&
2471             strlen(traffic_class) < LNET_MAX_STR_LEN) {
2472                 strcpy(&tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0],
2473                        traffic_class);
2474                 found = true;
2475         }
2476 #endif
2477
2478         if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1)) {
2479                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2480                 found = true;
2481         } else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1)) {
2482                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
2483                 found = true;
2484         }
2485
2486         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
2487                 tunables.lt_cmn.lct_peer_timeout = pto;
2488                 tunables.lt_cmn.lct_peer_tx_credits = pc;
2489                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
2490                 tunables.lt_cmn.lct_max_tx_credits = cre;
2491                 found = true;
2492         }
2493
2494         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
2495                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
2496
2497         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
2498                                  found ? &tunables : NULL, -1,
2499                                  (cpt_rc == 0) ? global_cpts : NULL,
2500                                  LNET_GENL_VERSION, NLM_F_CREATE, stdout);
2501         if (rc <= 0) {
2502                 if (rc == -EOPNOTSUPP)
2503                         goto old_api;
2504                 if (global_cpts != NULL)
2505                         cfs_expr_list_free(global_cpts);
2506                 if (rc == 0 && !skip_mr_route_setup)
2507                         rc = lustre_lnet_setup_mrrouting(&err_rc);
2508                 return rc;
2509         }
2510 old_api:
2511         rc = lustre_lnet_config_ni(&nw_descr,
2512                                    (cpt_rc == 0) ? global_cpts: NULL,
2513                                    ip2net, (found) ? &tunables : NULL,
2514                                    cpp, &err_rc);
2515
2516         if (global_cpts != NULL)
2517                 cfs_expr_list_free(global_cpts);
2518
2519 failed:
2520         if (rc != LUSTRE_CFG_RC_NO_ERR)
2521                 cYAML_print_tree2file(stderr, err_rc);
2522
2523         cYAML_free_tree(err_rc);
2524
2525         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
2526                 err_rc = NULL;
2527                 rc = lustre_lnet_setup_mrrouting(&err_rc);
2528
2529                 if (rc != LUSTRE_CFG_RC_NO_ERR)
2530                         cYAML_print_tree2file(stderr, err_rc);
2531
2532                 cYAML_free_tree(err_rc);
2533         }
2534
2535         return rc;
2536 }
2537
2538 static int jt_del_route(int argc, char **argv)
2539 {
2540         char *network = NULL, *gateway = NULL;
2541         struct cYAML *err_rc = NULL;
2542         int rc, opt;
2543         const char *const short_options = "n:g:";
2544         static const struct option long_options[] = {
2545                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2546                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
2547                 { .name = NULL }
2548         };
2549
2550         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
2551         if (rc)
2552                 return rc;
2553
2554         while ((opt = getopt_long(argc, argv, short_options,
2555                                    long_options, NULL)) != -1) {
2556                 switch (opt) {
2557                 case 'n':
2558                         network = optarg;
2559                         break;
2560                 case 'g':
2561                         gateway = optarg;
2562                         break;
2563                 case '?':
2564                         print_help(route_cmds, "route", "del");
2565                 default:
2566                         return 0;
2567                 }
2568         }
2569
2570         rc = yaml_lnet_route(network, gateway, -1, -1, -1, LNET_GENL_VERSION,
2571                              0, stdout);
2572         if (rc <= 0) {
2573                 if (rc == -EOPNOTSUPP)
2574                         goto old_api;
2575                 return rc;
2576         }
2577 old_api:
2578         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
2579
2580         if (rc != LUSTRE_CFG_RC_NO_ERR)
2581                 cYAML_print_tree2file(stderr, err_rc);
2582
2583         cYAML_free_tree(err_rc);
2584
2585         return rc;
2586 }
2587
2588 static int jt_del_ni(int argc, char **argv)
2589 {
2590         struct cYAML *err_rc = NULL;
2591         int rc, opt;
2592         struct lnet_dlc_network_descr nw_descr;
2593         const char *const short_options = "n:i:";
2594         static const struct option long_options[] = {
2595         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
2596         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
2597         { .name = "nid",        .has_arg = required_argument,   .val = 'N' },
2598         { .name = NULL } };
2599         bool nid_request = false;
2600         char *net_id = NULL;
2601
2602         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
2603         if (rc)
2604                 return rc;
2605
2606         lustre_lnet_init_nw_descr(&nw_descr);
2607
2608         while ((opt = getopt_long(argc, argv, short_options,
2609                                    long_options, NULL)) != -1) {
2610                 switch (opt) {
2611                 case 'n':
2612                         nw_descr.nw_id = libcfs_str2net(optarg);
2613                         net_id = optarg;
2614                         break;
2615                 case 'N':
2616                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2617                         if (rc != 0) {
2618                                 cYAML_build_error(-1, -1, "ni", "del",
2619                                                   "bad NID list",
2620                                                   &err_rc);
2621                                 goto out;
2622                         }
2623                         nid_request = true;
2624                         break;
2625                 case 'i':
2626                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2627                         if (rc != 0) {
2628                                 cYAML_build_error(-1, -1, "ni", "add",
2629                                                 "bad interface list",
2630                                                 &err_rc);
2631                                 goto out;
2632                         }
2633                         break;
2634                 case '?':
2635                         print_help(net_cmds, "net", "del");
2636                 default:
2637                         return 0;
2638                 }
2639         }
2640
2641         if (nid_request) {
2642                 if (net_id) {
2643                         fprintf(stdout, "--net is invalid with --nid option\n");
2644                         return -EINVAL;
2645                 }
2646                 net_id = libcfs_net2str(nw_descr.nw_id);
2647         }
2648
2649         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, -1, NULL,
2650                                  LNET_GENL_VERSION, 0, stdout);
2651         if (rc <= 0) {
2652                 if (rc != -EOPNOTSUPP)
2653                         return rc;
2654         }
2655
2656         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
2657 out:
2658         if (rc != LUSTRE_CFG_RC_NO_ERR)
2659                 cYAML_print_tree2file(stderr, err_rc);
2660
2661         cYAML_free_tree(err_rc);
2662
2663         return rc;
2664 }
2665
2666 static int jt_show_route(int argc, char **argv)
2667 {
2668         char *network = NULL, *gateway = NULL;
2669         long int hop = -1, prio = -1;
2670         int detail = 0, rc, opt;
2671         struct cYAML *err_rc = NULL, *show_rc = NULL;
2672         const char *const short_options = "c:n:g:p:v";
2673         static const struct option long_options[] = {
2674                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
2675                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
2676                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
2677                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
2678                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
2679                 { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
2680                 { .name = NULL }
2681         };
2682
2683         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
2684         if (rc)
2685                 return rc;
2686
2687         while ((opt = getopt_long(argc, argv, short_options,
2688                                    long_options, NULL)) != -1) {
2689                 switch (opt) {
2690                 case 'n':
2691                         network = optarg;
2692                         break;
2693                 case 'g':
2694                         gateway = optarg;
2695                         break;
2696                 case 'c':
2697                         rc = parse_long(optarg, &hop);
2698                         if (rc != 0) {
2699                                 /* ignore option */
2700                                 hop = -1;
2701                                 continue;
2702                         }
2703                         break;
2704                 case 'p':
2705                         rc = parse_long(optarg, &prio);
2706                         if (rc != 0) {
2707                                 /* ignore option */
2708                                 prio = -1;
2709                                 continue;
2710                         }
2711                         break;
2712                 case 'v':
2713                         detail = 1;
2714                         break;
2715                 case '?':
2716                         print_help(route_cmds, "route", "show");
2717                 default:
2718                         return 0;
2719                 }
2720         }
2721
2722         rc = yaml_lnet_route(network, gateway, hop, prio, -1,
2723                              detail, NLM_F_DUMP, stdout);
2724         if (rc <= 0) {
2725                 if (rc == -EOPNOTSUPP)
2726                         goto old_api;
2727                 return rc;
2728         }
2729 old_api:
2730         rc = lustre_lnet_show_route(network, gateway, hop, prio,
2731                                     detail ? 1 : 0, -1,
2732                                     &show_rc, &err_rc, false);
2733
2734         if (rc != LUSTRE_CFG_RC_NO_ERR)
2735                 cYAML_print_tree2file(stderr, err_rc);
2736         else if (show_rc)
2737                 cYAML_print_tree(show_rc);
2738
2739         cYAML_free_tree(err_rc);
2740         cYAML_free_tree(show_rc);
2741
2742         return rc;
2743 }
2744
2745 static int set_value_helper(int argc, char **argv, int cmd,
2746                             int (*cb)(int, bool, char*, int, int, struct cYAML**))
2747 {
2748         char *nidstr = NULL;
2749         long int healthv = -1;
2750         bool all = false;
2751         long int state = -1;
2752         long int cpp = -1;
2753         int rc, opt;
2754         struct cYAML *err_rc = NULL;
2755         const char *const short_options = "t:n:m:s:a";
2756         static const struct option long_options[] = {
2757                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2758                 { .name = "health", .has_arg = required_argument, .val = 't' },
2759                 { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2760                 { .name = "state", .has_arg = required_argument, .val = 's' },
2761                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2762                 { .name = NULL }
2763         };
2764
2765         while ((opt = getopt_long(argc, argv, short_options,
2766                                   long_options, NULL)) != -1) {
2767                 switch (opt) {
2768                 case 'n':
2769                         nidstr = optarg;
2770                         break;
2771                 case 't':
2772                         if (parse_long(optarg, &healthv) != 0)
2773                                 healthv = -1;
2774                         break;
2775                 case 's':
2776                         if (cmd != LNET_CMD_PEERS ||
2777                             parse_long(optarg, &state) != 0)
2778                                 state = -1;
2779                         break;
2780                 case 'm':
2781                         if (cmd != LNET_CMD_NETS ||
2782                             parse_long(optarg, &cpp) != 0)
2783                                 cpp = -1;
2784                         break;
2785
2786                 case 'a':
2787                         all = true;
2788                         break;
2789                 default:
2790                         return 0;
2791                 }
2792         }
2793
2794         rc = cb(healthv, all, nidstr, cmd == LNET_CMD_PEERS ? state : cpp, -1,
2795                 &err_rc);
2796         if (rc != LUSTRE_CFG_RC_NO_ERR)
2797                 cYAML_print_tree2file(stderr, err_rc);
2798
2799         cYAML_free_tree(err_rc);
2800
2801         return rc;
2802 }
2803
2804 int yaml_lnet_config_ni_healthv(int healthv, bool all, char *nidstr, int cpp,
2805                                 int seq_no, struct cYAML **err_rc)
2806 {
2807         struct lnet_ioctl_config_lnd_tunables tunables;
2808         struct lnet_dlc_network_descr nw_descr;
2809         char *net_id = "<255:65535>"; /* LNET_NET_ANY */
2810         int rc = 0;
2811
2812         /* For NI you can't have both setting all NIDs and a requested NID */
2813         if (!all && !nidstr)
2814                 return -EINVAL;
2815
2816         if (cpp == -1 && healthv == -1)
2817                 return 0;
2818
2819         if (nidstr) {
2820                 net_id = strchr(nidstr, '@');
2821                 if (!net_id)
2822                         return -EINVAL;
2823                 net_id++;
2824         }
2825
2826         lustre_lnet_init_nw_descr(&nw_descr);
2827         nw_descr.nw_id = libcfs_str2net(net_id);
2828
2829         rc = lustre_lnet_parse_interfaces(nidstr ? nidstr : "<?>", &nw_descr);
2830         if (rc != LUSTRE_CFG_RC_NO_ERR)
2831                 return -EINVAL;
2832
2833         memset(&tunables, 0, sizeof(tunables));
2834         tunables.lt_cmn.lct_peer_timeout = -1;
2835         if (nw_descr.nw_id == LNET_NET_ANY && cpp > -1)
2836                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2837         else if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1))
2838                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2839         else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1))
2840                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
2841
2842         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr,
2843                                  cpp != -1 ? &tunables : NULL, healthv, NULL,
2844                                  LNET_GENL_VERSION, NLM_F_REPLACE, stdout);
2845         if (rc <= 0) {
2846                 if (rc == -EOPNOTSUPP)
2847                         goto old_api;
2848                 return rc;
2849         }
2850 old_api:
2851         if (cpp > -1)
2852                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nidstr,
2853                                                           -1, err_rc);
2854         if (healthv > -1)
2855                 rc = lustre_lnet_config_ni_healthv(healthv, all, nidstr,
2856                                                    -1, err_rc);
2857         return rc;
2858 }
2859
2860 static int jt_set_ni_value(int argc, char **argv)
2861 {
2862         int rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2863
2864         if (rc < 0)
2865                 return rc;
2866
2867         return set_value_helper(argc, argv, LNET_CMD_NETS,
2868                                 yaml_lnet_config_ni_healthv);
2869 }
2870
2871 static int yaml_lnet_peer_display(yaml_parser_t *reply, bool list_only)
2872 {
2873         yaml_emitter_t debug;
2874         int rc;
2875
2876         rc = yaml_emitter_initialize(&debug);
2877         if (rc == 0)
2878                 goto out_err;
2879
2880         yaml_emitter_set_indent(&debug, 6);
2881         yaml_emitter_set_output_file(&debug, stdout);
2882
2883         if (list_only) {
2884                 bool done = false;
2885
2886                 while (!done) {
2887                         yaml_event_t event;
2888                         char *value;
2889
2890                         rc = yaml_parser_parse(reply, &event);
2891                         if (rc == 0)
2892                                 goto report_reply_error;
2893
2894                         if (event.type != YAML_SCALAR_EVENT)
2895                                 goto merge_event;
2896
2897                         value = (char *)event.data.scalar.value;
2898                         if (strcmp(value, "peer") == 0) {
2899                                 yaml_event_delete(&event);
2900
2901                                 yaml_scalar_event_initialize(&event, NULL,
2902                                                              (yaml_char_t *)YAML_STR_TAG,
2903                                                              (yaml_char_t *)"peer list",
2904                                                              strlen("peer list"),
2905                                                              1, 0,
2906                                                              YAML_PLAIN_SCALAR_STYLE);
2907                         } else if (strcmp(value, "primary nid") == 0) {
2908                                 yaml_event_delete(&event);
2909
2910                                 yaml_scalar_event_initialize(&event, NULL,
2911                                                              (yaml_char_t *)YAML_STR_TAG,
2912                                                              (yaml_char_t *)"nid",
2913                                                              strlen("nid"),
2914                                                              1, 0,
2915                                                              YAML_PLAIN_SCALAR_STYLE);
2916                                 rc = yaml_emitter_emit(&debug, &event);
2917                                 if (rc == 0)
2918                                         break;
2919
2920                                 /* Now print NID address */
2921                                 rc = yaml_parser_parse(reply, &event);
2922                                 if (rc == 0)
2923                                         goto report_reply_error;
2924
2925                                 rc = yaml_emitter_emit(&debug, &event);
2926                                 if (rc == 0)
2927                                         break;
2928
2929                                 /* skip reset */
2930                                 while (event.type != YAML_MAPPING_END_EVENT) {
2931                                         rc = yaml_parser_parse(reply, &event);
2932                                         if (rc == 0)
2933                                                 goto report_reply_error;
2934                                 }
2935
2936                                 /* we can have map end, seq end, map end or
2937                                  * just map end event. If we see seq end event
2938                                  * then skip to next mapping end event
2939                                  */
2940                                 rc = yaml_parser_parse(reply, &event);
2941                                 if (rc == 0)
2942                                         goto report_reply_error;
2943
2944                                 if (event.type == YAML_SEQUENCE_END_EVENT) {
2945                                         yaml_event_delete(&event);
2946
2947                                         rc = yaml_parser_parse(reply, &event);
2948                                         if (rc == 0)
2949                                                 goto report_reply_error;
2950                                 }
2951                         }
2952 merge_event:
2953                         rc = yaml_emitter_emit(&debug, &event);
2954                         if (rc == 0)
2955                                 break;
2956
2957                         done = (event.type == YAML_DOCUMENT_END_EVENT);
2958                 }
2959         } else {
2960                 yaml_document_t errmsg;
2961
2962                 rc = yaml_parser_load(reply, &errmsg);
2963                 if (rc == 1)
2964                         rc = yaml_emitter_dump(&debug, &errmsg);
2965                 yaml_document_delete(&errmsg);
2966         }
2967 out_err:
2968         if (rc == 0)
2969                 yaml_emitter_log_error(&debug, stderr);
2970 report_reply_error:
2971         yaml_emitter_delete(&debug);
2972
2973         return rc;
2974 }
2975
2976 static int yaml_lnet_peer(char *prim_nid, char *nidstr, bool disable_mr,
2977                           int health_value, int state, bool list_only,
2978                           int version, int flags, FILE *fp)
2979 {
2980         struct nl_sock *sk = NULL;
2981         const char *msg = NULL;
2982         yaml_emitter_t output;
2983         yaml_parser_t reply;
2984         yaml_event_t event;
2985         int rc;
2986
2987         /* Create Netlink emitter to send request to kernel */
2988         sk = nl_socket_alloc();
2989         if (!sk)
2990                 return -EOPNOTSUPP;
2991
2992         /* Setup parser to receive Netlink packets */
2993         rc = yaml_parser_initialize(&reply);
2994         if (rc == 0) {
2995                 nl_socket_free(sk);
2996                 return -EOPNOTSUPP;
2997         }
2998
2999         rc = yaml_parser_set_input_netlink(&reply, sk, false);
3000         if (rc == 0) {
3001                 msg = yaml_parser_get_reader_error(&reply);
3002                 goto free_reply;
3003         }
3004
3005         /* Create Netlink emitter to send request to kernel */
3006         rc = yaml_emitter_initialize(&output);
3007         if (rc == 0) {
3008                 msg = "failed to initialize emitter";
3009                 goto free_reply;
3010         }
3011
3012         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
3013                                              version, LNET_CMD_PEERS, flags);
3014         if (rc == 0)
3015                 goto emitter_error;
3016
3017         yaml_emitter_open(&output);
3018         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
3019         rc = yaml_emitter_emit(&output, &event);
3020         if (rc == 0)
3021                 goto emitter_error;
3022
3023         yaml_mapping_start_event_initialize(&event, NULL,
3024                                             (yaml_char_t *)YAML_MAP_TAG,
3025                                             1, YAML_ANY_MAPPING_STYLE);
3026         rc = yaml_emitter_emit(&output, &event);
3027         if (rc == 0)
3028                 goto emitter_error;
3029
3030         yaml_scalar_event_initialize(&event, NULL,
3031                                      (yaml_char_t *)YAML_STR_TAG,
3032                                      (yaml_char_t *)"peer",
3033                                      strlen("peer"), 1, 0,
3034                                      YAML_PLAIN_SCALAR_STYLE);
3035         rc = yaml_emitter_emit(&output, &event);
3036         if (rc == 0)
3037                 goto emitter_error;
3038
3039         if (prim_nid) {
3040                 yaml_sequence_start_event_initialize(&event, NULL,
3041                                                      (yaml_char_t *)YAML_SEQ_TAG,
3042                                                      1,
3043                                                      YAML_BLOCK_SEQUENCE_STYLE);
3044                 rc = yaml_emitter_emit(&output, &event);
3045                 if (rc == 0)
3046                         goto emitter_error;
3047
3048                 yaml_mapping_start_event_initialize(&event, NULL,
3049                                                     (yaml_char_t *)YAML_MAP_TAG,
3050                                                     1,
3051                                                     YAML_BLOCK_MAPPING_STYLE);
3052                 rc = yaml_emitter_emit(&output, &event);
3053                 if (rc == 0)
3054                         goto emitter_error;
3055
3056                 yaml_scalar_event_initialize(&event, NULL,
3057                                              (yaml_char_t *)YAML_STR_TAG,
3058                                              (yaml_char_t *)"primary nid",
3059                                              strlen("primary nid"), 1, 0,
3060                                              YAML_PLAIN_SCALAR_STYLE);
3061                 rc = yaml_emitter_emit(&output, &event);
3062                 if (rc == 0)
3063                         goto emitter_error;
3064
3065                 yaml_scalar_event_initialize(&event, NULL,
3066                                              (yaml_char_t *)YAML_STR_TAG,
3067                                              (yaml_char_t *)prim_nid,
3068                                              strlen(prim_nid), 1, 0,
3069                                              YAML_PLAIN_SCALAR_STYLE);
3070                 rc = yaml_emitter_emit(&output, &event);
3071                 if (rc == 0)
3072                         goto emitter_error;
3073
3074                 if (disable_mr) {
3075                         yaml_scalar_event_initialize(&event, NULL,
3076                                                      (yaml_char_t *)YAML_STR_TAG,
3077                                                      (yaml_char_t *)"Multi-Rail",
3078                                                      strlen("Multi-Rail"), 1, 0,
3079                                                      YAML_PLAIN_SCALAR_STYLE);
3080                         rc = yaml_emitter_emit(&output, &event);
3081                         if (rc == 0)
3082                                 goto emitter_error;
3083
3084                         yaml_scalar_event_initialize(&event, NULL,
3085                                                      (yaml_char_t *)YAML_BOOL_TAG,
3086                                                      (yaml_char_t *)"False",
3087                                                      strlen("False"), 1, 0,
3088                                                      YAML_PLAIN_SCALAR_STYLE);
3089                         rc = yaml_emitter_emit(&output, &event);
3090                         if (rc == 0)
3091                                 goto emitter_error;
3092                 }
3093
3094                 if (state != -1) {
3095                         char peer_state[INT_STRING_LEN];
3096
3097                         yaml_scalar_event_initialize(&event, NULL,
3098                                                      (yaml_char_t *)YAML_STR_TAG,
3099                                                      (yaml_char_t *)"peer state",
3100                                                      strlen("peer state"), 1, 0,
3101                                                      YAML_PLAIN_SCALAR_STYLE);
3102                         rc = yaml_emitter_emit(&output, &event);
3103                         if (rc == 0)
3104                                 goto emitter_error;
3105
3106                         snprintf(peer_state, sizeof(peer_state), "%d", state);
3107                         yaml_scalar_event_initialize(&event, NULL,
3108                                                      (yaml_char_t *)YAML_INT_TAG,
3109                                                      (yaml_char_t *)peer_state,
3110                                                      strlen(peer_state), 1, 0,
3111                                                      YAML_PLAIN_SCALAR_STYLE);
3112                         rc = yaml_emitter_emit(&output, &event);
3113                         if (rc == 0)
3114                                 goto emitter_error;
3115                 }
3116
3117                 if (!nidstr && health_value == -1)
3118                         goto skip_peer_nis;
3119
3120                 yaml_scalar_event_initialize(&event, NULL,
3121                                              (yaml_char_t *)YAML_STR_TAG,
3122                                              (yaml_char_t *)"peer ni",
3123                                              strlen("peer ni"), 1, 0,
3124                                              YAML_PLAIN_SCALAR_STYLE);
3125                 rc = yaml_emitter_emit(&output, &event);
3126                 if (rc == 0)
3127                         goto emitter_error;
3128
3129                 yaml_sequence_start_event_initialize(&event, NULL,
3130                                                      (yaml_char_t *)YAML_SEQ_TAG,
3131                                                      1, YAML_BLOCK_SEQUENCE_STYLE);
3132                 rc = yaml_emitter_emit(&output, &event);
3133                 if (rc == 0)
3134                         goto emitter_error;
3135
3136                 if (nidstr) {
3137                         struct nid_node head, *entry;
3138                         int count = 0;
3139
3140                         /* If we have LNET_ANY_NID and its NLM_F_REPLACE we
3141                          * treat it as the all flag case for lnetctl peer set
3142                          */
3143                         if (strcmp(nidstr, "<?>") == 0) {
3144                                 yaml_mapping_start_event_initialize(&event, NULL,
3145                                                                     (yaml_char_t *)YAML_MAP_TAG,
3146                                                                     1, YAML_BLOCK_MAPPING_STYLE);
3147                                 rc = yaml_emitter_emit(&output, &event);
3148                                 if (rc == 0)
3149                                         goto emitter_error;
3150
3151                                 yaml_scalar_event_initialize(&event, NULL,
3152                                                              (yaml_char_t *)YAML_STR_TAG,
3153                                                              (yaml_char_t *)"nid",
3154                                                              strlen("nid"), 1, 0,
3155                                                              YAML_PLAIN_SCALAR_STYLE);
3156                                 rc = yaml_emitter_emit(&output, &event);
3157                                 if (rc == 0)
3158                                         goto emitter_error;
3159
3160                                 yaml_scalar_event_initialize(&event, NULL,
3161                                                              (yaml_char_t *)YAML_STR_TAG,
3162                                                              (yaml_char_t *)nidstr,
3163                                                              strlen(nidstr), 1, 0,
3164                                                      YAML_PLAIN_SCALAR_STYLE);
3165                                 rc = yaml_emitter_emit(&output, &event);
3166                                 if (rc == 0)
3167                                         goto emitter_error;
3168
3169                                 yaml_mapping_end_event_initialize(&event);
3170                                 rc = yaml_emitter_emit(&output, &event);
3171                                 if (rc == 0)
3172                                         goto emitter_error;
3173
3174                                 goto handle_health;
3175                         }
3176
3177                         NL_INIT_LIST_HEAD(&head.children);
3178                         nl_init_list_head(&head.list);
3179                         rc = lustre_lnet_parse_nid_range(&head, nidstr, &msg);
3180                         if (rc < 0) {
3181                                 fprintf(stdout, "can't parse nidrange: \"%s\"\n", nidstr);
3182                                 lustre_lnet_free_list(&head);
3183                                 yaml_emitter_delete(&output);
3184                                 errno = rc;
3185                                 rc = 0;
3186                                 goto free_reply;
3187                         }
3188
3189                         if (nl_list_empty(&head.children)) {
3190                                 lustre_lnet_free_list(&head);
3191                                 yaml_emitter_delete(&output);
3192                                 msg = "Unable to parse nidlist: did not expand to any nids";
3193                                 errno = -ENOENT;
3194                                 rc = 0;
3195                                 goto free_reply;
3196                         }
3197                         rc = 1; /* one means its working */
3198
3199                         nl_list_for_each_entry(entry, &head.children, list) {
3200                                 char *nid = entry->nidstr;
3201
3202                                 if (count++ > LNET_MAX_NIDS_PER_PEER) {
3203                                         lustre_lnet_free_list(&head);
3204                                         yaml_emitter_delete(&output);
3205                                         msg = "Unable to parse nidlist: specifies more NIDs than allowed";
3206                                         errno = -E2BIG;
3207                                         rc = 0;
3208                                         goto free_reply;
3209                                 }
3210
3211                                 yaml_mapping_start_event_initialize(&event, NULL,
3212                                                                     (yaml_char_t *)YAML_MAP_TAG,
3213                                                                     1, YAML_BLOCK_MAPPING_STYLE);
3214                                 rc = yaml_emitter_emit(&output, &event);
3215                                 if (rc == 0)
3216                                         goto emitter_error;
3217
3218                                 yaml_scalar_event_initialize(&event, NULL,
3219                                                              (yaml_char_t *)YAML_STR_TAG,
3220                                                              (yaml_char_t *)"nid",
3221                                                              strlen("nid"), 1, 0,
3222                                                              YAML_PLAIN_SCALAR_STYLE);
3223                                 rc = yaml_emitter_emit(&output, &event);
3224                                 if (rc == 0)
3225                                         goto emitter_error;
3226
3227                                 yaml_scalar_event_initialize(&event, NULL,
3228                                                              (yaml_char_t *)YAML_STR_TAG,
3229                                                              (yaml_char_t *)nid,
3230                                                              strlen(nid), 1, 0,
3231                                                      YAML_PLAIN_SCALAR_STYLE);
3232                                 rc = yaml_emitter_emit(&output, &event);
3233                                 if (rc == 0)
3234                                         goto emitter_error;
3235
3236                                 yaml_mapping_end_event_initialize(&event);
3237                                 rc = yaml_emitter_emit(&output, &event);
3238                                 if (rc == 0)
3239                                         goto emitter_error;
3240                         }
3241                         lustre_lnet_free_list(&head);
3242                 }
3243 handle_health:
3244                 if (health_value >= 0) {
3245                         char health[INT_STRING_LEN];
3246
3247                         /* Create the mapping for 'health stats'. The value field for
3248                          * the mapping is not provided so its treated as a empty string.
3249                          */
3250                         yaml_mapping_start_event_initialize(&event, NULL,
3251                                                             (yaml_char_t *)YAML_MAP_TAG,
3252                                                             1, YAML_BLOCK_MAPPING_STYLE);
3253                         rc = yaml_emitter_emit(&output, &event);
3254                         if (rc == 0)
3255                                 goto emitter_error;
3256
3257                         yaml_scalar_event_initialize(&event, NULL,
3258                                                      (yaml_char_t *)YAML_STR_TAG,
3259                                                      (yaml_char_t *)"health stats",
3260                                                      strlen("health stats"), 1, 0,
3261                                                      YAML_PLAIN_SCALAR_STYLE);
3262                         rc = yaml_emitter_emit(&output, &event);
3263                         if (rc == 0)
3264                                 goto emitter_error;
3265
3266                         /* Setup all mappings for data related to the 'health stats' */
3267                         yaml_mapping_start_event_initialize(&event, NULL,
3268                                                             (yaml_char_t *)YAML_MAP_TAG,
3269                                                             1, YAML_BLOCK_MAPPING_STYLE);
3270                         rc = yaml_emitter_emit(&output, &event);
3271                         if (rc == 0)
3272                                 goto emitter_error;
3273
3274                         yaml_scalar_event_initialize(&event, NULL,
3275                                                      (yaml_char_t *)YAML_STR_TAG,
3276                                                      (yaml_char_t *)"health value",
3277                                                      strlen("health value"), 1, 0,
3278                                                      YAML_PLAIN_SCALAR_STYLE);
3279                         rc = yaml_emitter_emit(&output, &event);
3280                         if (rc == 0)
3281                                 goto emitter_error;
3282
3283                         snprintf(health, sizeof(health), "%d", health_value);
3284                         yaml_scalar_event_initialize(&event, NULL,
3285                                                      (yaml_char_t *)YAML_INT_TAG,
3286                                                      (yaml_char_t *)health,
3287                                                      strlen(health), 1, 0,
3288                                                      YAML_PLAIN_SCALAR_STYLE);
3289                         rc = yaml_emitter_emit(&output, &event);
3290                         if (rc == 0)
3291                                 goto emitter_error;
3292
3293                         yaml_mapping_end_event_initialize(&event);
3294                         rc = yaml_emitter_emit(&output, &event);
3295                         if (rc == 0)
3296                                 goto emitter_error;
3297
3298                         yaml_mapping_end_event_initialize(&event);
3299                         rc = yaml_emitter_emit(&output, &event);
3300                         if (rc == 0)
3301                                 goto emitter_error;
3302                 }
3303
3304                 yaml_sequence_end_event_initialize(&event);
3305                 rc = yaml_emitter_emit(&output, &event);
3306                 if (rc == 0)
3307                         goto emitter_error;
3308 skip_peer_nis:
3309                 yaml_mapping_end_event_initialize(&event);
3310                 rc = yaml_emitter_emit(&output, &event);
3311                 if (rc == 0)
3312                         goto emitter_error;
3313
3314                 yaml_sequence_end_event_initialize(&event);
3315                 rc = yaml_emitter_emit(&output, &event);
3316                 if (rc == 0)
3317                         goto emitter_error;
3318         } else {
3319                 yaml_scalar_event_initialize(&event, NULL,
3320                                              (yaml_char_t *)YAML_STR_TAG,
3321                                              (yaml_char_t *)"",
3322                                              strlen(""), 1, 0,
3323                                              YAML_PLAIN_SCALAR_STYLE);
3324                 rc = yaml_emitter_emit(&output, &event);
3325                 if (rc == 0)
3326                         goto emitter_error;
3327         }
3328
3329         yaml_mapping_end_event_initialize(&event);
3330         rc = yaml_emitter_emit(&output, &event);
3331         if (rc == 0)
3332                 goto emitter_error;
3333
3334         yaml_document_end_event_initialize(&event, 0);
3335         rc = yaml_emitter_emit(&output, &event);
3336         if (rc == 0)
3337                 goto emitter_error;
3338
3339         rc = yaml_emitter_close(&output);
3340 emitter_error:
3341         if (rc == 0) {
3342                 yaml_emitter_log_error(&output, stderr);
3343                 rc = -EINVAL;
3344         } else {
3345                 rc = yaml_lnet_peer_display(&reply, list_only);
3346                 if (rc == 0) {
3347                         msg = yaml_parser_get_reader_error(&reply);
3348                         /* If we didn't find any peers just be silent */
3349                         if (msg && strcmp(msg, "No peers found") == 0)
3350                                 rc = 1;
3351                 }
3352
3353         }
3354         yaml_emitter_delete(&output);
3355 free_reply:
3356         if (rc == 0) {
3357                 yaml_lnet_print_error(flags, "peer", msg);
3358                 rc = -EINVAL;
3359         }
3360         yaml_parser_delete(&reply);
3361         nl_socket_free(sk);
3362
3363         return rc == 1 ? 0 : rc;
3364 }
3365
3366 int yaml_lnet_config_peer_ni_healthv(int healthv, bool all, char *lpni_nid,
3367                                      int state, int seq_no, struct cYAML **err_rc)
3368 {
3369         int rc;
3370
3371         rc = yaml_lnet_peer(lpni_nid ? lpni_nid : "<?>", all ? "<?>" : NULL,
3372                             false, healthv, state, false, LNET_GENL_VERSION,
3373                             NLM_F_REPLACE, stdout);
3374         if (rc <= 0) {
3375                 if (rc == -EOPNOTSUPP)
3376                         goto old_api;
3377                 return rc;
3378         }
3379 old_api:
3380         if (state == -1)
3381                 rc = lustre_lnet_config_peer_ni_healthv(healthv, all, lpni_nid,
3382                                                         seq_no, err_rc);
3383         else
3384                 rc = lustre_lnet_set_peer_state(state, lpni_nid, -1, err_rc);
3385
3386         return rc;
3387 }
3388
3389 static int jt_set_peer_ni_value(int argc, char **argv)
3390 {
3391         int rc = check_cmd(peer_cmds, "peer", "set", 0, argc, argv);
3392
3393         if (rc < 0)
3394                 return rc;
3395
3396         return set_value_helper(argc, argv, LNET_CMD_PEERS,
3397                                 yaml_lnet_config_peer_ni_healthv);
3398 }
3399
3400 static int jt_show_recovery(int argc, char **argv)
3401 {
3402         int rc, opt;
3403         struct cYAML *err_rc = NULL, *show_rc = NULL;
3404         const char *const short_options = "lp";
3405         static const struct option long_options[] = {
3406                 { .name = "local", .has_arg = no_argument, .val = 'l' },
3407                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
3408                 { .name = NULL } };
3409
3410         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
3411         if (rc)
3412                 return rc;
3413
3414         while ((opt = getopt_long(argc, argv, short_options,
3415                                    long_options, NULL)) != -1) {
3416                 switch (opt) {
3417                 case 'l':
3418                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
3419                         break;
3420                 case 'p':
3421                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
3422                         break;
3423                 default:
3424                         return 0;
3425                 }
3426         }
3427
3428         if (rc != LUSTRE_CFG_RC_NO_ERR)
3429                 cYAML_print_tree2file(stderr, err_rc);
3430         else if (show_rc)
3431                 cYAML_print_tree(show_rc);
3432
3433         cYAML_free_tree(err_rc);
3434         cYAML_free_tree(show_rc);
3435
3436         return rc;
3437 }
3438
3439 static int jt_show_peer_debug_info(int argc, char **argv)
3440 {
3441         int rc, opt;
3442         struct cYAML *err_rc = NULL;
3443         char *peer_nid = optarg;
3444         const char *const short_opts = "k";
3445         const struct option long_opts[] = {
3446         { .name = "nid", .has_arg = required_argument, .val = 'k' },
3447         { .name = NULL } };
3448
3449         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
3450
3451         if (rc)
3452                 return rc;
3453
3454         while ((opt = getopt_long(argc, argv, short_opts,
3455                                    long_opts, NULL)) != -1) {
3456                 switch (opt) {
3457                 case 'k':
3458                         peer_nid = optarg;
3459                         break;
3460                 default:
3461                         return 0;
3462                 }
3463         }
3464
3465         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
3466
3467         if (rc != LUSTRE_CFG_RC_NO_ERR)
3468                 cYAML_print_tree2file(stderr, err_rc);
3469
3470         cYAML_free_tree(err_rc);
3471
3472         return rc;
3473 }
3474
3475 static int jt_show_net(int argc, char **argv)
3476 {
3477         char *network = NULL;
3478         int rc, opt;
3479         struct cYAML *err_rc = NULL, *show_rc = NULL;
3480         long int detail = 0;
3481         const char *const short_options = "n:v";
3482         static const struct option long_options[] = {
3483                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
3484                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
3485                 { .name = NULL } };
3486
3487         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
3488         if (rc)
3489                 return rc;
3490
3491         while ((opt = getopt_long(argc, argv, short_options,
3492                                    long_options, NULL)) != -1) {
3493                 switch (opt) {
3494                 case 'n':
3495                         network = optarg;
3496                         break;
3497                 case 'v':
3498                         if ((!optarg) && (argv[optind] != NULL) &&
3499                             (argv[optind][0] != '-')) {
3500                                 if (parse_long(argv[optind++], &detail) != 0)
3501                                         detail = 1;
3502                         } else {
3503                                 detail = 1;
3504                         }
3505                         break;
3506                 case '?':
3507                         print_help(net_cmds, "net", "show");
3508                 default:
3509                         return 0;
3510                 }
3511         }
3512
3513         rc = yaml_lnet_config_ni(network, NULL, NULL, NULL, -1, NULL,
3514                                  detail, NLM_F_DUMP, stdout);
3515         if (rc <= 0) {
3516                 if (rc != -EOPNOTSUPP)
3517                         return rc;
3518         }
3519
3520         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
3521                                   false);
3522
3523         if (rc != LUSTRE_CFG_RC_NO_ERR)
3524                 cYAML_print_tree2file(stderr, err_rc);
3525         else if (show_rc)
3526                 cYAML_print_tree(show_rc);
3527
3528         cYAML_free_tree(err_rc);
3529         cYAML_free_tree(show_rc);
3530
3531         return rc;
3532 }
3533
3534 static int jt_show_routing(int argc, char **argv)
3535 {
3536         struct cYAML *err_rc = NULL, *show_rc = NULL;
3537         int rc;
3538
3539         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
3540         if (rc)
3541                 return rc;
3542
3543         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
3544
3545         if (rc != LUSTRE_CFG_RC_NO_ERR)
3546                 cYAML_print_tree2file(stderr, err_rc);
3547         else if (show_rc)
3548                 cYAML_print_tree(show_rc);
3549
3550         cYAML_free_tree(err_rc);
3551         cYAML_free_tree(show_rc);
3552
3553         return rc;
3554 }
3555
3556 static int jt_show_stats(int argc, char **argv)
3557 {
3558         int rc;
3559         struct cYAML *show_rc = NULL, *err_rc = NULL;
3560
3561         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
3562         if (rc)
3563                 return rc;
3564
3565         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
3566
3567         if (rc != LUSTRE_CFG_RC_NO_ERR)
3568                 cYAML_print_tree2file(stderr, err_rc);
3569         else if (show_rc)
3570                 cYAML_print_tree(show_rc);
3571
3572         cYAML_free_tree(err_rc);
3573         cYAML_free_tree(show_rc);
3574
3575         return rc;
3576 }
3577
3578 static int jt_show_udsp(int argc, char **argv)
3579 {
3580         long int idx = -1;
3581         int rc, opt;
3582         struct cYAML *err_rc = NULL, *show_rc = NULL;
3583
3584         const char *const short_options = "i:";
3585         static const struct option long_options[] = {
3586                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
3587                 { .name = NULL }
3588         };
3589
3590         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
3591         if (rc)
3592                 return rc;
3593
3594         while ((opt = getopt_long(argc, argv, short_options,
3595                                    long_options, NULL)) != -1) {
3596                 switch (opt) {
3597                 case 'i':
3598                         rc = parse_long(optarg, &idx);
3599                         if (rc != 0 || idx < -1) {
3600                                 printf("Invalid index \"%s\"\n", optarg);
3601                                 return -EINVAL;
3602                         }
3603                         break;
3604                 case '?':
3605                         print_help(net_cmds, "net", "show");
3606                 default:
3607                         return 0;
3608                 }
3609         }
3610
3611         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
3612
3613         if (rc != LUSTRE_CFG_RC_NO_ERR)
3614                 cYAML_print_tree2file(stderr, err_rc);
3615         else if (show_rc)
3616                 cYAML_print_tree(show_rc);
3617
3618         cYAML_free_tree(err_rc);
3619         cYAML_free_tree(show_rc);
3620
3621         return rc;
3622 }
3623
3624 static int jt_show_global(int argc, char **argv)
3625 {
3626         int rc;
3627         struct cYAML *show_rc = NULL, *err_rc = NULL;
3628
3629         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
3630         if (rc)
3631                 return rc;
3632
3633         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3634         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3635                 cYAML_print_tree2file(stderr, err_rc);
3636                 goto out;
3637         }
3638
3639         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3640         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3641                 cYAML_print_tree2file(stderr, err_rc);
3642                 goto out;
3643         }
3644
3645         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3646         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3647                 cYAML_print_tree2file(stderr, err_rc);
3648                 goto out;
3649         }
3650
3651         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3652         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3653                 cYAML_print_tree2file(stderr, err_rc);
3654                 goto out;
3655         }
3656
3657         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3658         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3659                 cYAML_print_tree2file(stderr, err_rc);
3660                 goto out;
3661         }
3662
3663         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3664         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3665                 cYAML_print_tree2file(stderr, err_rc);
3666                 goto out;
3667         }
3668
3669         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3670         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3671                 cYAML_print_tree2file(stderr, err_rc);
3672                 goto out;
3673         }
3674
3675         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3676         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3677                 cYAML_print_tree2file(stderr, err_rc);
3678                 goto out;
3679         }
3680
3681         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3682         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3683                 cYAML_print_tree2file(stderr, err_rc);
3684                 goto out;
3685         }
3686
3687         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3688         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3689                 cYAML_print_tree2file(stderr, err_rc);
3690                 goto out;
3691         }
3692
3693         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3694         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3695                 cYAML_print_tree2file(stderr, err_rc);
3696                 goto out;
3697         }
3698
3699         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3700         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3701                 cYAML_print_tree2file(stderr, err_rc);
3702                 goto out;
3703         }
3704
3705         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3706         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3707                 cYAML_print_tree2file(stderr, err_rc);
3708                 goto out;
3709         }
3710
3711         if (show_rc)
3712                 cYAML_print_tree(show_rc);
3713
3714 out:
3715         cYAML_free_tree(err_rc);
3716         cYAML_free_tree(show_rc);
3717
3718         return rc;
3719 }
3720
3721 static int jt_lnet(int argc, char **argv)
3722 {
3723         int rc;
3724
3725         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
3726         if (rc)
3727                 return rc;
3728
3729         return cfs_parser(argc, argv, lnet_cmds);
3730 }
3731
3732 static int jt_route(int argc, char **argv)
3733 {
3734         int rc;
3735
3736         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
3737         if (rc)
3738                 return rc;
3739
3740         return cfs_parser(argc, argv, route_cmds);
3741 }
3742
3743 static int jt_net(int argc, char **argv)
3744 {
3745         int rc;
3746
3747         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
3748         if (rc)
3749                 return rc;
3750
3751         return cfs_parser(argc, argv, net_cmds);
3752 }
3753
3754 static int jt_routing(int argc, char **argv)
3755 {
3756         int rc;
3757
3758         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
3759         if (rc)
3760                 return rc;
3761
3762         return cfs_parser(argc, argv, routing_cmds);
3763 }
3764
3765 static int jt_stats(int argc, char **argv)
3766 {
3767         int rc;
3768
3769         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
3770         if (rc)
3771                 return rc;
3772
3773         return cfs_parser(argc, argv, stats_cmds);
3774 }
3775
3776 static int jt_debug(int argc, char **argv)
3777 {
3778         int rc;
3779
3780         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
3781         if (rc)
3782                 return rc;
3783
3784         return cfs_parser(argc, argv, debug_cmds);
3785 }
3786
3787 static int jt_global(int argc, char **argv)
3788 {
3789         int rc;
3790
3791         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
3792         if (rc)
3793                 return rc;
3794
3795         return cfs_parser(argc, argv, global_cmds);
3796 }
3797
3798 static int jt_peers(int argc, char **argv)
3799 {
3800         int rc;
3801
3802         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
3803         if (rc)
3804                 return rc;
3805
3806         return cfs_parser(argc, argv, peer_cmds);
3807 }
3808
3809 static int jt_set(int argc, char **argv)
3810 {
3811         int rc;
3812
3813         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
3814         if (rc)
3815                 return rc;
3816
3817         return cfs_parser(argc, argv, set_cmds);
3818 }
3819
3820 static int jt_udsp(int argc, char **argv)
3821 {
3822         int rc;
3823
3824         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
3825         if (rc)
3826                 return rc;
3827
3828         return cfs_parser(argc, argv, udsp_cmds);
3829 }
3830
3831 static int yaml_import_global_settings(char *key, unsigned long value,
3832                                        char cmd, struct cYAML *show_rc,
3833                                        struct cYAML *err_rc)
3834 {
3835         int rc;
3836
3837         if (strcmp("numa_range", key) == 0) {
3838                 if (cmd == 'a' || cmd == 'd') {
3839                         if (cmd == 'd')
3840                                 value = 0;
3841                         rc = lustre_lnet_config_numa_range(value, -1,
3842                                                            &err_rc);
3843                 } else if (cmd == 's') {
3844                         rc = lustre_lnet_show_numa_range(-1, &show_rc,
3845                                                          &err_rc);
3846                 }
3847         } else if (strcmp("max_interfaces", key) == 0 ||
3848                    strcmp("max_intf", key) == 0) {
3849                 if (cmd == 'a' || cmd == 'd') {
3850                         if (cmd == 'd')
3851                                 value = LNET_INTERFACES_MAX_DEFAULT;
3852                         rc = lustre_lnet_config_max_intf(value, -1,
3853                                                          &err_rc);
3854                 } else if (cmd == 's') {
3855                         rc = lustre_lnet_show_max_intf(-1, &show_rc,
3856                                                        &err_rc);
3857                 }
3858         } else if (strcmp("discovery", key) == 0) {
3859                 if (cmd == 'a' || cmd == 'd') {
3860                         if (cmd == 'd')
3861                                 value = 1;
3862                         rc = lustre_lnet_config_discovery(value, -1,
3863                                                           &err_rc);
3864                 } else if (cmd == 's') {
3865                         rc = lustre_lnet_show_discovery(-1, &show_rc,
3866                                                         &err_rc);
3867                 }
3868         } else if (strcmp("drop_asym_route", key) == 0) {
3869                 if (cmd == 'a') {
3870                         rc = lustre_lnet_config_drop_asym_route(value,
3871                                                                 -1,
3872                                                                 &err_rc);
3873                 } else if (cmd == 's') {
3874                         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc,
3875                                                               &err_rc);
3876                 }
3877         } else if (strcmp("retry_count", key) == 0) {
3878                 if (cmd == 'a') {
3879                         rc = lustre_lnet_config_retry_count(value, -1,
3880                                                             &err_rc);
3881                 } else if (cmd == 's') {
3882                         rc = lustre_lnet_show_retry_count(-1, &show_rc,
3883                                                           &err_rc);
3884                 }
3885         } else if (strcmp("transaction_timeout", key) == 0) {
3886                 if (cmd == 'a') {
3887                         rc = lustre_lnet_config_transaction_to(value, -1,
3888                                                                &err_rc);
3889                 } else if (cmd == 's') {
3890                         rc = lustre_lnet_show_transaction_to(-1, &show_rc,
3891                                                              &err_rc);
3892                 }
3893         } else if (strcmp("health_sensitivity", key) == 0) {
3894                 if (cmd == 'a') {
3895                         rc = lustre_lnet_config_hsensitivity(value, -1,
3896                                                              &err_rc);
3897                 } else if (cmd == 's') {
3898                         rc = lustre_lnet_show_hsensitivity(-1, &show_rc,
3899                                                            &err_rc);
3900                 }
3901         } else if (strcmp("recovery_interval", key) == 0) {
3902                 if (cmd == 'a') {
3903                         rc = lustre_lnet_config_recov_intrv(value, -1,
3904                                                             &err_rc);
3905                 } else if (cmd == 's') {
3906                         rc = lustre_lnet_show_recov_intrv(-1, &show_rc,
3907                                                           &err_rc);
3908                 }
3909         } else if (strcmp("router_sensitivity", key) == 0) {
3910                 if (cmd == 'a') {
3911                         rc = lustre_lnet_config_rtr_sensitivity(value, -1,
3912                                                                 &err_rc);
3913                 } else if (cmd == 's') {
3914                         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc,
3915                                                               &err_rc);
3916                 }
3917         } else if (strcmp("lnd_timeout", key) == 0) {
3918                 if (cmd == 'a') {
3919                 } else if (cmd == 's') {
3920                         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc,
3921                                                           &err_rc);
3922                 }
3923         } else if (strcmp("response_tracking", key) == 0) {
3924                 if (cmd == 'a') {
3925                         rc = lustre_lnet_config_response_tracking(value, -1,
3926                                                                   &err_rc);
3927                 } else if (cmd == 's') {
3928                         rc = lustre_lnet_show_response_tracking(-1, &show_rc,
3929                                                                 &err_rc);
3930                 }
3931         } else if (strcmp("recovery_limit", key) == 0) {
3932                 if (cmd == 'a') {
3933                         rc = lustre_lnet_config_recovery_limit(value, -1,
3934                                                                &err_rc);
3935                 } else if (cmd == 's') {
3936                         rc = lustre_lnet_show_recovery_limit(-1, &show_rc,
3937                                                              &err_rc);
3938                 }
3939         } else if (strcmp("max_recovery_ping_interval", key) == 0) {
3940                 if (cmd == 'a') {
3941                         rc = lustre_lnet_config_max_recovery_ping_interval(value, -1,
3942                                                                            &err_rc);
3943                 } else if (cmd == 's') {
3944                         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc,
3945                                                                          &err_rc);
3946                 }
3947         }
3948
3949         return rc;
3950 }
3951
3952 static int jt_import(int argc, char **argv)
3953 {
3954         char *file = NULL;
3955         struct cYAML *err_rc = NULL;
3956         struct cYAML *show_rc = NULL;
3957         int rc = 0, return_rc = 0, opt, opt_found = 0;
3958         char *yaml_blk = NULL, *buf, cmd = 'a';
3959         int flags = NLM_F_CREATE;
3960         bool release = true;
3961         char err_str[256];
3962         struct stat st;
3963         FILE *input;
3964         size_t len;
3965         const char *const short_options = "adseh";
3966         static const struct option long_options[] = {
3967                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
3968                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
3969                 { .name = "show", .has_arg = no_argument, .val = 's' },
3970                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
3971                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3972                 { .name = NULL }
3973         };
3974         bool done = false, unspec = true;
3975         yaml_parser_t setup, reply;
3976         struct nl_sock *sk = NULL;
3977         int op = LNET_CMD_UNSPEC;
3978         const char *msg = NULL;
3979         yaml_emitter_t output;
3980         yaml_event_t event;
3981
3982         while ((opt = getopt_long(argc, argv, short_options,
3983                                    long_options, NULL)) != -1) {
3984                 opt_found = 1;
3985                 switch (opt) {
3986                 case 'a':
3987                         /* default is NLM_F_CREATE */
3988                         cmd = opt;
3989                         break;
3990                 case 'd':
3991                         flags = 0; /* Netlink delete cmd */
3992                         cmd = opt;
3993                         break;
3994                 case 's':
3995                         flags = NLM_F_DUMP;
3996                         cmd = opt;
3997                         break;
3998                 case 'e':
3999                         /* use NLM_F_CREATE for discover */
4000                         cmd = opt;
4001                         break;
4002                 case 'h':
4003                         printf("import FILE\n"
4004                                "import < FILE : import a file\n"
4005                                "\t--add: add configuration\n"
4006                                "\t--del: delete configuration\n"
4007                                "\t--show: show configuration\n"
4008                                "\t--exec: execute command\n"
4009                                "\t--help: display this help\n"
4010                                "If no command option is given then --add"
4011                                " is assumed by default\n");
4012                         return 0;
4013                 default:
4014                         return 0;
4015                 }
4016         }
4017
4018         /* grab the file name if one exists */
4019         if (opt_found && argc == 3)
4020                 file = argv[2];
4021         else if (!opt_found && argc == 2)
4022                 file = argv[1];
4023
4024         /* file always takes precedence */
4025         if (file != NULL) {
4026                 /* Set a file input. */
4027                 input = fopen(file, "rb");
4028                 if (!input) {
4029                         rc = -errno;
4030                         snprintf(err_str, sizeof(err_str),
4031                                  "cannot open '%s': %s", file,
4032                                  strerror(errno));
4033                         cYAML_build_error(-1, -1, "yaml", "builder",
4034                                           err_str,
4035                                           &err_rc);
4036                         goto err;
4037                 }
4038         } else {
4039                 input = stdin;
4040         }
4041
4042         /* Create Netlink emitter to send request to kernel */
4043         sk = nl_socket_alloc();
4044         if (!sk)
4045                 goto old_api;
4046
4047         /* Setup parser to receive Netlink packets */
4048         rc = yaml_parser_initialize(&reply);
4049         if (rc == 0) {
4050                 nl_socket_free(sk);
4051                 goto old_api;
4052         }
4053
4054         rc = yaml_parser_set_input_netlink(&reply, sk, false);
4055         if (rc == 0) {
4056                 msg = yaml_parser_get_reader_error(&reply);
4057                 goto free_reply;
4058         }
4059
4060         /* Initialize configuration parser */
4061         rc = yaml_parser_initialize(&setup);
4062         if (rc == 0) {
4063                 yaml_parser_log_error(&setup, stderr, "import: ");
4064                 yaml_parser_delete(&setup);
4065                 return -EINVAL;
4066         }
4067
4068         yaml_parser_set_input_file(&setup, input);
4069
4070         while (!done) {
4071                 if (!yaml_parser_parse(&setup, &event)) {
4072                         yaml_parser_log_error(&setup, stderr, "import: ");
4073                         break;
4074                 }
4075
4076                 if (event.type != YAML_SCALAR_EVENT)
4077                         goto skip_test;
4078
4079                 if (!strcmp((char *)event.data.scalar.value, "net") &&
4080                     op != LNET_CMD_ROUTES && cmd != 'e') {
4081                         if (op != LNET_CMD_UNSPEC) {
4082                                 rc = yaml_netlink_complete_emitter(&output);
4083                                 if (rc == 0)
4084                                         goto emitter_error;
4085                         }
4086                         op = LNET_CMD_NETS;
4087
4088                         rc = yaml_netlink_setup_emitter(&output, sk,
4089                                                         LNET_GENL_NAME,
4090                                                         LNET_GENL_VERSION,
4091                                                         flags, op, true);
4092                         if (rc == 0)
4093                                 goto emitter_error;
4094
4095                         unspec = false;
4096                 } else if (!strcmp((char *)event.data.scalar.value, "peer") &&
4097                            cmd != 'e') {
4098                         if (op != LNET_CMD_UNSPEC) {
4099                                 rc = yaml_netlink_complete_emitter(&output);
4100                                 if (rc == 0)
4101                                         goto emitter_error;
4102                         }
4103                         op = LNET_CMD_PEERS;
4104
4105                         rc = yaml_netlink_setup_emitter(&output, sk,
4106                                                         LNET_GENL_NAME,
4107                                                         LNET_GENL_VERSION,
4108                                                         flags, op, true);
4109                         if (rc == 0)
4110                                 goto emitter_error;
4111
4112                         unspec = false;
4113                 } else if (!strcmp((char *)event.data.scalar.value, "route") &&
4114                            cmd != 'e') {
4115                         if (op != LNET_CMD_UNSPEC) {
4116                                 rc = yaml_netlink_complete_emitter(&output);
4117                                 if (rc == 0)
4118                                         goto emitter_error;
4119                         }
4120                         op = LNET_CMD_ROUTES;
4121
4122                         rc = yaml_netlink_setup_emitter(&output, sk,
4123                                                         LNET_GENL_NAME,
4124                                                         LNET_GENL_VERSION,
4125                                                         flags, op, true);
4126                         if (rc == 0)
4127                                 goto emitter_error;
4128
4129                         unspec = false;
4130                 } else if ((!strcmp((char *)event.data.scalar.value, "discover") ||
4131                             !strcmp((char *)event.data.scalar.value, "ping")) &&
4132                            cmd == 'e') {
4133                         if (op != LNET_CMD_UNSPEC) {
4134                                 rc = yaml_netlink_complete_emitter(&output);
4135                                 if (rc == 0)
4136                                         goto emitter_error;
4137                         }
4138                         op = LNET_CMD_PING;
4139
4140                         if (!strcmp((char *)event.data.scalar.value, "ping"))
4141                                 flags = NLM_F_DUMP;
4142
4143                         rc = yaml_netlink_setup_emitter(&output, sk,
4144                                                         LNET_GENL_NAME,
4145                                                         LNET_GENL_VERSION,
4146                                                         flags, op, true);
4147                         if (rc == 0)
4148                                 goto emitter_error;
4149
4150                         unspec = false;
4151                 } else if (!strcmp((char *)event.data.scalar.value, "global")) {
4152                         if (op != LNET_CMD_UNSPEC) {
4153                                 rc = yaml_netlink_complete_emitter(&output);
4154                                 if (rc == 0)
4155                                         goto emitter_error;
4156                         }
4157                         op = LNET_CMD_UNSPEC;
4158                 } else if (op == LNET_CMD_UNSPEC) {
4159                         struct cYAML *err_rc = NULL;
4160                         long int value;
4161                         char *key;
4162
4163                         key = strdup((char *)event.data.scalar.value);
4164                         rc = yaml_parser_parse(&setup, &event);
4165                         if (rc == 0)
4166                                 goto free_reply;
4167
4168                         rc = parse_long((char *)event.data.scalar.value,
4169                                         &value);
4170                         if (rc != 0)
4171                                 goto free_reply;
4172
4173                         rc = yaml_import_global_settings(key, value, cmd,
4174                                                          show_rc, err_rc);
4175                         if (rc != LUSTRE_CFG_RC_NO_ERR)
4176                                 cYAML_print_tree2file(stderr, err_rc);
4177                         else
4178                                 rc = 1;
4179                 }
4180 skip_test:
4181                 if (op != LNET_CMD_UNSPEC) {
4182                         rc = yaml_emitter_emit(&output, &event);
4183                         if (rc == 0)
4184                                 break;
4185                 }
4186
4187                 done = (event.type == YAML_STREAM_END_EVENT);
4188         }
4189 emitter_error:
4190         if (rc == 0) {
4191                 yaml_emitter_log_error(&output, stderr);
4192                 yaml_emitter_delete(&output);
4193                 rc = -EINVAL;
4194         } else if (!unspec) {
4195                 yaml_document_t errmsg;
4196
4197                 rc = yaml_parser_load(&reply, &errmsg);
4198                 if (rc == 1 && (flags & NLM_F_DUMP)) {
4199                         yaml_emitter_t debug;
4200
4201                         rc = yaml_emitter_initialize(&debug);
4202                         if (rc == 1) {
4203                                 yaml_emitter_set_indent(&debug,
4204                                                         LNET_DEFAULT_INDENT);
4205                                 yaml_emitter_set_output_file(&debug,
4206                                                              stdout);
4207                                 rc = yaml_emitter_dump(&debug, &errmsg);
4208                         }
4209                         yaml_emitter_delete(&debug);
4210                 } else {
4211                         msg = yaml_parser_get_reader_error(&reply);
4212                 }
4213                 yaml_emitter_delete(&output);
4214                 yaml_document_delete(&errmsg);
4215         }
4216 free_reply:
4217         if (rc == 0) {
4218                 yaml_lnet_print_error(flags, "import", msg);
4219                 rc = -EINVAL;
4220         }
4221         yaml_parser_delete(&reply);
4222         yaml_parser_delete(&setup);
4223         nl_socket_free(sk);
4224         if (input)
4225                 fclose(input);
4226
4227         return rc == 1 ? 0 : rc;
4228 old_api:
4229         /* assume that we're getting our input from stdin */
4230         rc = fstat(fileno(input), &st);
4231         if (rc < 0) {
4232                 snprintf(err_str, sizeof(err_str),
4233                          "cannot get file stats '%s': %s", file,
4234                          strerror(-rc));
4235                 cYAML_build_error(-1, -1, "yaml", "builder",
4236                                   err_str,
4237                                   &err_rc);
4238                 goto err;
4239         }
4240
4241         yaml_blk = buf = malloc(st.st_size);
4242         if (!yaml_blk) {
4243                 rc = -ENOMEM;
4244                 snprintf(err_str, sizeof(err_str),
4245                          "failed to allocate buffer: %s",
4246                          strerror(-rc));
4247                 cYAML_build_error(-1, -1, "yaml", "builder",
4248                                   err_str,
4249                                   &err_rc);
4250                 goto err;
4251         }
4252         len = st.st_size;
4253
4254         while (fgets(buf, len, input) != NULL) {
4255                 char *seq = strstr(buf, "-     ");
4256
4257                 if (seq) {
4258                         int skip;
4259
4260                         seq[0] = ' ';
4261                         skip = strspn(seq, " ");
4262                         if (skip) {
4263                                 seq += skip - 2;
4264                                 seq[0] = '-';
4265                         }
4266                         /* PyYAML format has libyaml free the
4267                          * buffer for us.
4268                          */
4269                         release = false;
4270                 }
4271                 buf += strlen(buf);
4272                 len -= strlen(buf);
4273         }
4274
4275         switch (cmd) {
4276         case 'a':
4277                 rc = lustre_yaml_config(yaml_blk, st.st_size, &err_rc);
4278                 return_rc = lustre_yaml_exec(yaml_blk, st.st_size, &show_rc,
4279                                              &err_rc);
4280                 cYAML_print_tree(show_rc);
4281                 cYAML_free_tree(show_rc);
4282                 break;
4283         case 'd':
4284                 rc = lustre_yaml_del(yaml_blk, st.st_size, &err_rc);
4285                 break;
4286         case 's':
4287                 rc = lustre_yaml_show(yaml_blk, st.st_size, &show_rc,
4288                                       &err_rc);
4289                 cYAML_print_tree(show_rc);
4290                 cYAML_free_tree(show_rc);
4291                 break;
4292         case 'e':
4293                 rc = lustre_yaml_exec(yaml_blk, st.st_size, &show_rc,
4294                                       &err_rc);
4295                 cYAML_print_tree(show_rc);
4296                 cYAML_free_tree(show_rc);
4297                 break;
4298         }
4299 err:
4300         if (yaml_blk && release)
4301                 free(yaml_blk);
4302         if (rc || return_rc) {
4303                 cYAML_print_tree2file(stderr, err_rc);
4304                 cYAML_free_tree(err_rc);
4305         }
4306
4307         return rc;
4308 }
4309
4310 static int jt_export(int argc, char **argv)
4311 {
4312         struct cYAML *show_rc = NULL;
4313         struct cYAML *err_rc = NULL;
4314         int flags = NLM_F_DUMP;
4315         int rc;
4316         FILE *f = NULL;
4317         int opt;
4318         bool backup = false;
4319         char *file = NULL;
4320         const char *const short_options = "bh";
4321         static const struct option long_options[] = {
4322                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
4323                 { .name = "help", .has_arg = no_argument, .val = 'h' },
4324                 { .name = NULL }
4325         };
4326
4327         while ((opt = getopt_long(argc, argv, short_options,
4328                                    long_options, NULL)) != -1) {
4329                 switch (opt) {
4330                 case 'b':
4331                         flags |= NLM_F_DUMP_FILTERED;
4332                         backup = true;
4333                         break;
4334                 case 'h':
4335                 default:
4336                         printf("export > FILE.yaml : export configuration\n"
4337                                "\t--backup: export only what's necessary for reconfig\n"
4338                                "\t--help: display this help\n");
4339                         return 0;
4340                 }
4341         }
4342
4343         if (backup && argc >= 3)
4344                 file = argv[2];
4345         else if (!backup && argc >= 2)
4346                 file = argv[1];
4347         else
4348                 f = stdout;
4349
4350         if (file) {
4351                 f = fopen(file, "w");
4352                 if (f == NULL)
4353                         return -1;
4354         }
4355
4356         rc = yaml_lnet_config_ni(NULL, NULL, NULL, NULL, -1, NULL,
4357                                  flags & NLM_F_DUMP_FILTERED ? 1 : 2,
4358                                  flags, f);
4359         if (rc < 0) {
4360                 if (rc == -EOPNOTSUPP)
4361                         goto old_api;
4362         }
4363
4364         rc = yaml_lnet_route(NULL, NULL, -1, -1, -1, LNET_GENL_VERSION,
4365                              flags, f);
4366         if (rc < 0) {
4367                 if (rc == -EOPNOTSUPP)
4368                         goto old_route;
4369         }
4370
4371         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
4372         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4373                 cYAML_print_tree2file(f, err_rc);
4374                 cYAML_free_tree(err_rc);
4375                 err_rc = NULL;
4376         }
4377
4378         rc = yaml_lnet_peer(NULL, NULL, false, -1, false, false,
4379                             flags & NLM_F_DUMP_FILTERED ? 0 : 3,
4380                            flags, f);
4381         if (rc < 0) {
4382                 if (rc == -EOPNOTSUPP)
4383                         goto old_peer;
4384         }
4385         goto show_others;
4386
4387 old_api:
4388         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
4389         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4390                 cYAML_print_tree2file(f, err_rc);
4391                 cYAML_free_tree(err_rc);
4392                 err_rc = NULL;
4393         }
4394 old_route:
4395         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
4396                                     &err_rc, backup);
4397         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4398                 cYAML_print_tree2file(f, err_rc);
4399                 cYAML_free_tree(err_rc);
4400                 err_rc = NULL;
4401         }
4402
4403         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
4404         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4405                 cYAML_print_tree2file(f, err_rc);
4406                 cYAML_free_tree(err_rc);
4407                 err_rc = NULL;
4408         }
4409 old_peer:
4410         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
4411         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4412                 cYAML_print_tree2file(f, err_rc);
4413                 cYAML_free_tree(err_rc);
4414                 err_rc = NULL;
4415         }
4416 show_others:
4417         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
4418         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4419                 cYAML_print_tree2file(f, err_rc);
4420                 cYAML_free_tree(err_rc);
4421                 err_rc = NULL;
4422         }
4423
4424         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
4425         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4426                 cYAML_print_tree2file(f, err_rc);
4427                 cYAML_free_tree(err_rc);
4428                 err_rc = NULL;
4429         }
4430
4431         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
4432         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4433                 cYAML_print_tree2file(f, err_rc);
4434                 cYAML_free_tree(err_rc);
4435                 err_rc = NULL;
4436         }
4437
4438         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
4439         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4440                 cYAML_print_tree2file(f, err_rc);
4441                 cYAML_free_tree(err_rc);
4442                 err_rc = NULL;
4443         }
4444
4445         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
4446         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4447                 cYAML_print_tree2file(f, err_rc);
4448                 err_rc = NULL;
4449         }
4450
4451         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
4452         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4453                 cYAML_print_tree2file(f, err_rc);
4454                 err_rc = NULL;
4455         }
4456
4457         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
4458         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4459                 cYAML_print_tree2file(f, err_rc);
4460                 err_rc = NULL;
4461         }
4462
4463         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
4464         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4465                 cYAML_print_tree2file(f, err_rc);
4466                 err_rc = NULL;
4467         }
4468
4469         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
4470         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4471                 cYAML_print_tree2file(f, err_rc);
4472                 err_rc = NULL;
4473         }
4474
4475         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
4476         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4477                 cYAML_print_tree2file(f, err_rc);
4478                 err_rc = NULL;
4479         }
4480
4481         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
4482         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4483                 cYAML_print_tree2file(f, err_rc);
4484                 cYAML_free_tree(err_rc);
4485                 err_rc = NULL;
4486         }
4487
4488         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
4489         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4490                 cYAML_print_tree2file(f, err_rc);
4491                 cYAML_free_tree(err_rc);
4492                 err_rc = NULL;
4493         }
4494
4495         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
4496         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4497                 cYAML_print_tree2file(f, err_rc);
4498                 cYAML_free_tree(err_rc);
4499                 err_rc = NULL;
4500         }
4501
4502         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
4503         if (rc != LUSTRE_CFG_RC_NO_ERR) {
4504                 cYAML_print_tree2file(f, err_rc);
4505                 cYAML_free_tree(err_rc);
4506                 err_rc = NULL;
4507         }
4508
4509         if (show_rc != NULL) {
4510                 cYAML_print_tree2file(f, show_rc);
4511                 cYAML_free_tree(show_rc);
4512         }
4513
4514         if (argc >= 2)
4515                 fclose(f);
4516
4517         return 0;
4518 }
4519
4520 static int jt_peer_nid_common(int argc, char **argv, int cmd)
4521 {
4522         int flags = cmd == LNETCTL_ADD_CMD ? NLM_F_CREATE : 0;
4523         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
4524         bool is_mr = true;
4525         char *prim_nid = NULL, *nidstr = NULL;
4526         char err_str[LNET_MAX_STR_LEN] = "Error";
4527         struct cYAML *err_rc = NULL;
4528         int force_lock = 0;
4529         const char *const short_opts = "k:m:n:f:l";
4530         const struct option long_opts[] = {
4531         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
4532         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
4533         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
4534         { .name = "force",      .has_arg = no_argument,         .val = 'f' },
4535         { .name = "lock_prim",  .has_arg = no_argument,         .val = 'l' },
4536         { .name = NULL } };
4537
4538         rc = check_cmd(peer_cmds, "peer",
4539                        cmd == LNETCTL_ADD_CMD ? "add" : "del", 2, argc, argv);
4540         if (rc)
4541                 return rc;
4542
4543         while ((opt = getopt_long(argc, argv, short_opts,
4544                                   long_opts, NULL)) != -1) {
4545                 switch (opt) {
4546                 case 'k':
4547                         prim_nid = optarg;
4548                         break;
4549                 case 'n':
4550                         nidstr = optarg;
4551                         break;
4552                 case 'm':
4553                         if (cmd == LNETCTL_DEL_CMD) {
4554                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4555                                 snprintf(err_str, LNET_MAX_STR_LEN,
4556                                          "Unrecognized option '-%c'", opt);
4557                                 goto build_error;
4558                         }
4559                         is_mr = false;
4560                         break;
4561                 case 'f':
4562                         if (cmd == LNETCTL_ADD_CMD) {
4563                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4564                                 snprintf(err_str, LNET_MAX_STR_LEN,
4565                                          "Unrecognized option '-%c'", opt);
4566                         }
4567                         force_lock = 1;
4568                         flags |= NLM_F_EXCL;
4569                         break;
4570                 case 'l':
4571                         if (cmd == LNETCTL_DEL_CMD) {
4572                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
4573                                 snprintf(err_str, LNET_MAX_STR_LEN,
4574                                          "Unrecognized option '-%c'", opt);
4575                         }
4576                         force_lock = 1;
4577                         flags |= NLM_F_EXCL;
4578                         break;
4579                 case '?':
4580                         print_help(peer_cmds, "peer",
4581                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
4582                 default:
4583                         return 0;
4584                 }
4585         }
4586
4587         rc = yaml_lnet_peer(prim_nid, nidstr, !is_mr, -1, -1, false,
4588                             LNET_GENL_VERSION, flags, stdout);
4589         if (rc <= 0) {
4590                 if (rc == -EOPNOTSUPP)
4591                         goto old_api;
4592                 return rc;
4593         }
4594 old_api:
4595         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
4596                                      force_lock, -1, &err_rc);
4597         if (rc != LUSTRE_CFG_RC_NO_ERR)
4598                 goto out;
4599
4600 build_error:
4601         cYAML_build_error(rc, -1, "peer",
4602                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
4603                           err_str, &err_rc);
4604
4605 out:
4606         if (rc != LUSTRE_CFG_RC_NO_ERR)
4607                 cYAML_print_tree2file(stderr, err_rc);
4608
4609         cYAML_free_tree(err_rc);
4610
4611         return rc;
4612 }
4613
4614 static int jt_add_peer_nid(int argc, char **argv)
4615 {
4616         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
4617 }
4618
4619 static int jt_del_peer_nid(int argc, char **argv)
4620 {
4621         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
4622 }
4623
4624 static int jt_show_peer(int argc, char **argv)
4625 {
4626         char *nid = NULL;
4627         int rc, opt;
4628         struct cYAML *err_rc = NULL, *show_rc = NULL;
4629         long int detail = 0;
4630         const char *const short_opts = "hn:v::";
4631         const struct option long_opts[] = {
4632                 { .name = "help",       .has_arg = no_argument,         .val = 'h' },
4633                 { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
4634                 { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
4635                 { .name = NULL }
4636         };
4637
4638         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
4639         if (rc)
4640                 return rc;
4641
4642         while ((opt = getopt_long(argc, argv, short_opts,
4643                                   long_opts, NULL)) != -1) {
4644                 switch (opt) {
4645                 case 'n':
4646                         nid = optarg;
4647                         break;
4648                 case 'v':
4649                         if ((!optarg) && (argv[optind] != NULL) &&
4650                             (argv[optind][0] != '-')) {
4651                                 if (parse_long(argv[optind++], &detail) != 0)
4652                                         detail = 1;
4653                         } else {
4654                                 detail = 1;
4655                         }
4656                         break;
4657                 case '?':
4658                         print_help(peer_cmds, "peer", "show");
4659                 default:
4660                         return 0;
4661                 }
4662         }
4663
4664         rc = yaml_lnet_peer(nid, NULL, false, -1, -1, false, detail,
4665                             NLM_F_DUMP, stdout);
4666         if (rc <= 0) {
4667                 if (rc == -EOPNOTSUPP)
4668                         goto old_api;
4669                 return rc;
4670         }
4671 old_api:
4672         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
4673                                    false);
4674
4675         if (rc != LUSTRE_CFG_RC_NO_ERR)
4676                 cYAML_print_tree2file(stderr, err_rc);
4677         else if (show_rc)
4678                 cYAML_print_tree(show_rc);
4679
4680         cYAML_free_tree(err_rc);
4681         cYAML_free_tree(show_rc);
4682
4683         return rc;
4684 }
4685
4686 static int jt_list_peer(int argc, char **argv)
4687 {
4688         struct cYAML *err_rc = NULL, *list_rc = NULL;
4689         int rc;
4690
4691         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
4692         if (rc)
4693                 return rc;
4694
4695         rc = yaml_lnet_peer(NULL, NULL, false, -1, -1, true, 0, NLM_F_DUMP,
4696                             stdout);
4697         if (rc <= 0) {
4698                 if (rc == -EOPNOTSUPP)
4699                         goto old_api;
4700                 return rc;
4701         }
4702
4703 old_api:
4704         rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
4705         if (rc != LUSTRE_CFG_RC_NO_ERR)
4706                 cYAML_print_tree2file(stderr, err_rc);
4707         else if (list_rc)
4708                 cYAML_print_tree(list_rc);
4709
4710         cYAML_free_tree(err_rc);
4711         cYAML_free_tree(list_rc);
4712
4713         return rc;
4714 }
4715
4716 static int yaml_lnet_ping_display(yaml_parser_t *reply)
4717 {
4718         yaml_emitter_t debug;
4719         bool done = false;
4720         int rc, rc2 = 0;
4721         long error = 0;
4722
4723         rc = yaml_emitter_initialize(&debug);
4724         if (rc == 1)
4725                 yaml_emitter_set_output_file(&debug, stdout);
4726         if (rc == 0)
4727                 goto emitter_error;
4728
4729         while (!done) {
4730                 yaml_event_t event;
4731
4732                 rc = yaml_parser_parse(reply, &event);
4733                 if (rc == 0)
4734                         goto report_reply_error;
4735
4736                 if (event.type != YAML_SCALAR_EVENT) {
4737                         rc = yaml_emitter_emit(&debug, &event);
4738                         if (rc == 0)
4739                                 goto emitter_error;
4740
4741                         done = (event.type == YAML_DOCUMENT_END_EVENT);
4742                         continue;
4743                 }
4744
4745                 if (strcmp((char *)event.data.scalar.value, "errno") == 0) {
4746                         rc = yaml_emitter_emit(&debug, &event);
4747                         if (rc == 0)
4748                                 goto emitter_error;
4749
4750                         rc = yaml_parser_parse(reply, &event);
4751                         if (rc == 0)
4752                                 goto report_reply_error;
4753
4754                         rc = parse_long((char *)event.data.scalar.value,
4755                                         &error);
4756                         if (rc != 0)
4757                                 goto report_reply_error;
4758
4759                         rc = yaml_emitter_emit(&debug, &event);
4760                         if (rc == 0)
4761                                 goto emitter_error;
4762
4763                         rc2 = -1;
4764                 } else if (error != 0 &&
4765                            strcmp((char *)event.data.scalar.value,
4766                                   "descr") == 0) {
4767                         rc = yaml_emitter_emit(&debug, &event);
4768                         if (rc == 0)
4769                                 goto emitter_error;
4770
4771                         rc = yaml_parser_parse(reply, &event);
4772                         if (rc == 0)
4773                                 goto report_reply_error;
4774
4775                         if (strncmp((char *)event.data.scalar.value,
4776                                     "failed to ", strlen("failed to ")) == 0) {
4777                                 char err[256];
4778
4779                                 snprintf(err, sizeof(err), "%s: %s",
4780                                         (char *)event.data.scalar.value,
4781                                         strerror(-error));
4782                                 yaml_scalar_event_initialize(&event, NULL,
4783                                                              (yaml_char_t *)YAML_STR_TAG,
4784                                                              (yaml_char_t *)err,
4785                                                              strlen(err), 1, 0,
4786                                                              YAML_PLAIN_SCALAR_STYLE);
4787                         }
4788                         rc = yaml_emitter_emit(&debug, &event);
4789                         if (rc == 0)
4790                                 goto emitter_error;
4791
4792                         errno = 0;
4793                 } else {
4794                         rc = yaml_emitter_emit(&debug, &event);
4795                         if (rc == 0)
4796                                 goto emitter_error;
4797                 }
4798         }
4799 emitter_error:
4800         if (rc == 0)
4801                 yaml_emitter_log_error(&debug, stderr);
4802 report_reply_error:
4803         yaml_emitter_delete(&debug);
4804
4805         return rc2 ? rc2 : rc;
4806 }
4807
4808 static int yaml_lnet_ping(char *group, int timeout, char *src_nidstr,
4809                           int start, int end, char **nids, int flags)
4810 {
4811         struct nl_sock *sk = NULL;
4812         const char *msg = NULL;
4813         yaml_emitter_t output;
4814         yaml_parser_t reply;
4815         yaml_event_t event;
4816         int rc, i;
4817
4818         /* Create Netlink emitter to send request to kernel */
4819         sk = nl_socket_alloc();
4820         if (!sk)
4821                 return -EOPNOTSUPP;
4822
4823         /* Setup parser to receive Netlink packets */
4824         rc = yaml_parser_initialize(&reply);
4825         if (rc == 0) {
4826                 nl_socket_free(sk);
4827                 return -EOPNOTSUPP;
4828         }
4829
4830         rc = yaml_parser_set_input_netlink(&reply, sk, false);
4831         if (rc == 0) {
4832                 msg = yaml_parser_get_reader_error(&reply);
4833                 goto free_reply;
4834         }
4835
4836         /* Create Netlink emitter to send request to kernel */
4837         rc = yaml_emitter_initialize(&output);
4838         if (rc == 0) {
4839                 msg = "failed to initialize emitter";
4840                 goto free_reply;
4841         }
4842
4843         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
4844                                              LNET_GENL_VERSION, LNET_CMD_PING,
4845                                              flags);
4846         if (rc == 0)
4847                 goto emitter_error;
4848
4849         yaml_emitter_open(&output);
4850         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
4851         rc = yaml_emitter_emit(&output, &event);
4852         if (rc == 0)
4853                 goto emitter_error;
4854
4855         yaml_mapping_start_event_initialize(&event, NULL,
4856                                             (yaml_char_t *)YAML_MAP_TAG,
4857                                             1, YAML_ANY_MAPPING_STYLE);
4858         rc = yaml_emitter_emit(&output, &event);
4859         if (rc == 0)
4860                 goto emitter_error;
4861
4862         yaml_scalar_event_initialize(&event, NULL,
4863                                      (yaml_char_t *)YAML_STR_TAG,
4864                                      (yaml_char_t *)group,
4865                                      strlen(group), 1, 0,
4866                                      YAML_PLAIN_SCALAR_STYLE);
4867         rc = yaml_emitter_emit(&output, &event);
4868         if (rc == 0)
4869                 goto emitter_error;
4870
4871         yaml_mapping_start_event_initialize(&event, NULL,
4872                                             (yaml_char_t *)YAML_MAP_TAG,
4873                                             1, YAML_ANY_MAPPING_STYLE);
4874         rc = yaml_emitter_emit(&output, &event);
4875         if (rc == 0)
4876                 goto emitter_error;
4877
4878         if (timeout != 1000 || src_nidstr) {
4879                 if (src_nidstr) {
4880                         yaml_scalar_event_initialize(&event, NULL,
4881                                                      (yaml_char_t *)YAML_STR_TAG,
4882                                                      (yaml_char_t *)"source",
4883                                                      strlen("source"), 1, 0,
4884                                                      YAML_PLAIN_SCALAR_STYLE);
4885                         rc = yaml_emitter_emit(&output, &event);
4886                         if (rc == 0)
4887                                 goto emitter_error;
4888
4889                         yaml_scalar_event_initialize(&event, NULL,
4890                                                      (yaml_char_t *)YAML_STR_TAG,
4891                                                      (yaml_char_t *)src_nidstr,
4892                                                      strlen(src_nidstr), 1, 0,
4893                                                      YAML_PLAIN_SCALAR_STYLE);
4894                         rc = yaml_emitter_emit(&output, &event);
4895                         if (rc == 0)
4896                                 goto emitter_error;
4897                 }
4898
4899                 if (timeout != 1000) {
4900                         char time[23];
4901
4902                         yaml_scalar_event_initialize(&event, NULL,
4903                                                      (yaml_char_t *)YAML_STR_TAG,
4904                                                      (yaml_char_t *)"timeout",
4905                                                      strlen("timeout"), 1, 0,
4906                                                      YAML_PLAIN_SCALAR_STYLE);
4907                         rc = yaml_emitter_emit(&output, &event);
4908                         if (rc == 0)
4909                                 goto emitter_error;
4910
4911                         snprintf(time, sizeof(time), "%u", timeout);
4912                         yaml_scalar_event_initialize(&event, NULL,
4913                                                      (yaml_char_t *)YAML_INT_TAG,
4914                                                      (yaml_char_t *)time,
4915                                                      strlen(time), 1, 0,
4916                                                      YAML_PLAIN_SCALAR_STYLE);
4917                         rc = yaml_emitter_emit(&output, &event);
4918                         if (rc == 0)
4919                                 goto emitter_error;
4920                 }
4921         }
4922
4923         yaml_scalar_event_initialize(&event, NULL,
4924                                      (yaml_char_t *)YAML_STR_TAG,
4925                                      (yaml_char_t *)"nids",
4926                                      strlen("nids"), 1, 0,
4927                                      YAML_PLAIN_SCALAR_STYLE);
4928         rc = yaml_emitter_emit(&output, &event);
4929         if (rc == 0)
4930                 goto emitter_error;
4931
4932         yaml_sequence_start_event_initialize(&event, NULL,
4933                                              (yaml_char_t *)YAML_SEQ_TAG,
4934                                              1, YAML_FLOW_SEQUENCE_STYLE);
4935         rc = yaml_emitter_emit(&output, &event);
4936         if (rc == 0)
4937                 goto emitter_error;
4938
4939         for (i = start; i < end; i++) {
4940                 yaml_scalar_event_initialize(&event, NULL,
4941                                              (yaml_char_t *)YAML_STR_TAG,
4942                                              (yaml_char_t *)nids[i],
4943                                              strlen(nids[i]), 1, 0,
4944                                              YAML_PLAIN_SCALAR_STYLE);
4945                 rc = yaml_emitter_emit(&output, &event);
4946                 if (rc == 0)
4947                         goto emitter_error;
4948         }
4949
4950         yaml_sequence_end_event_initialize(&event);
4951         rc = yaml_emitter_emit(&output, &event);
4952         if (rc == 0)
4953                 goto emitter_error;
4954
4955         yaml_mapping_end_event_initialize(&event);
4956         rc = yaml_emitter_emit(&output, &event);
4957         if (rc == 0)
4958                 goto emitter_error;
4959
4960         yaml_mapping_end_event_initialize(&event);
4961         rc = yaml_emitter_emit(&output, &event);
4962         if (rc == 0)
4963                 goto emitter_error;
4964
4965         yaml_document_end_event_initialize(&event, 0);
4966         rc = yaml_emitter_emit(&output, &event);
4967         if (rc == 0)
4968                 goto emitter_error;
4969
4970         rc = yaml_emitter_close(&output);
4971 emitter_error:
4972         if (rc == 0) {
4973                 yaml_emitter_log_error(&output, stderr);
4974                 rc = -EINVAL;
4975         } else {
4976                 rc = yaml_lnet_ping_display(&reply);
4977                 if (rc == 0)
4978                         msg = yaml_parser_get_reader_error(&reply);
4979         }
4980         yaml_emitter_delete(&output);
4981 free_reply:
4982         if (rc == 0) {
4983                 yaml_lnet_print_error(-1, group, msg);
4984                 rc = -EINVAL;
4985         }
4986
4987         yaml_parser_delete(&reply);
4988         nl_socket_free(sk);
4989
4990         return rc == 1 ? 0 : rc;
4991 }
4992
4993 static int jt_ping(int argc, char **argv)
4994 {
4995         struct cYAML *err_rc = NULL;
4996         struct cYAML *show_rc = NULL;
4997         int timeout = 1000;
4998         int rc = 0, opt;
4999         char *src_nidstr = NULL;
5000         const char *const short_options = "hs:t:";
5001         const struct option long_options[] = {
5002                 { .name = "help",       .has_arg = no_argument,         .val = 'h' },
5003                 { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
5004                 { .name = "source",     .has_arg = required_argument,   .val = 's' },
5005                 { .name = NULL }
5006         };
5007
5008         while ((opt = getopt_long(argc, argv, short_options,
5009                                   long_options, NULL)) != -1) {
5010                 switch (opt) {
5011                 case 's':
5012                         src_nidstr = optarg;
5013                         break;
5014                 case 't':
5015                         timeout = 1000 * atol(optarg);
5016                         break;
5017                 case 'h':
5018                         printf("ping nid[,nid,...]\n"
5019                                "\t --source: source nid\n"
5020                                "\t --timeout: ping timeout\n"
5021                                "\t --help: display this help\n");
5022                         return 0;
5023                 default:
5024                         return 0;
5025                 }
5026         }
5027
5028         rc = yaml_lnet_ping("ping", timeout, src_nidstr, optind, argc,
5029                             argv, NLM_F_DUMP);
5030         if (rc <= 0) {
5031                 if (rc != -EOPNOTSUPP)
5032                         return rc;
5033         }
5034
5035         for (; optind < argc; optind++)
5036                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
5037                                           &show_rc, &err_rc);
5038
5039         if (show_rc)
5040                 cYAML_print_tree(show_rc);
5041
5042         if (err_rc)
5043                 cYAML_print_tree2file(stderr, err_rc);
5044
5045         cYAML_free_tree(err_rc);
5046         cYAML_free_tree(show_rc);
5047
5048         return rc;
5049 }
5050
5051 static int jt_discover(int argc, char **argv)
5052 {
5053         struct cYAML *err_rc = NULL;
5054         struct cYAML *show_rc = NULL;
5055         int flags = NLM_F_CREATE;
5056         int force = 0;
5057         int rc = 0, opt;
5058         const char *const short_options = "fh";
5059         const struct option long_options[] = {
5060                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
5061                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
5062                 { .name = NULL }
5063         };
5064
5065         while ((opt = getopt_long(argc, argv, short_options,
5066                                   long_options, NULL)) != -1) {
5067                 switch (opt) {
5068                 case 'f':
5069                         /* BSD treats NLM_F_CREATE | NLM_F_EXCL as an add */
5070                         flags |= NLM_F_EXCL;
5071                         force = 1;
5072                         break;
5073                 case 'h':
5074                         printf("discover nid[,nid,...]\n"
5075                                "\t --force: force discovery\n"
5076                                "\t --help: display this help\n");
5077                         return 0;
5078                 default:
5079                         return 0;
5080                 }
5081         }
5082
5083         if (optind == argc) {
5084                 printf("Missing nid argument\n");
5085                 return -1;
5086         }
5087
5088         rc = yaml_lnet_ping("discover", 1000, NULL, optind, argc, argv,
5089                             flags);
5090         if (rc <= 0) {
5091                 if (rc != -EOPNOTSUPP)
5092                         return rc;
5093         }
5094
5095         for (; optind < argc; optind++)
5096                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
5097                                               &err_rc);
5098
5099         if (show_rc)
5100                 cYAML_print_tree(show_rc);
5101
5102         if (err_rc)
5103                 cYAML_print_tree2file(stderr, err_rc);
5104
5105         cYAML_free_tree(err_rc);
5106         cYAML_free_tree(show_rc);
5107
5108         return rc;
5109 }
5110
5111 static int jt_add_udsp(int argc, char **argv)
5112 {
5113         char *src = NULL, *dst = NULL, *rte = NULL;
5114         struct cYAML *err_rc = NULL;
5115         union lnet_udsp_action udsp_action;
5116         long int idx = -1, priority = -1;
5117         int opt, rc = 0;
5118         char *action_type = "pref";
5119
5120         const char *const short_options = "s:d:r:p:i:";
5121         static const struct option long_options[] = {
5122         { .name = "src",         .has_arg = required_argument, .val = 's' },
5123         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
5124         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
5125         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
5126         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
5127         { .name = NULL } };
5128
5129         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
5130         if (rc)
5131                 return rc;
5132
5133         while ((opt = getopt_long(argc, argv, short_options,
5134                                   long_options, NULL)) != -1) {
5135                 switch (opt) {
5136                 case 's':
5137                         src = optarg;
5138                         break;
5139                 case 'd':
5140                         dst = optarg;
5141                         break;
5142                 case 'r':
5143                         rte = optarg;
5144                         break;
5145                 case 'p':
5146                         rc = parse_long(optarg, &priority);
5147                         if (rc != 0 || priority < 0) {
5148                                 printf("Invalid priority \"%s\"\n", optarg);
5149                                 return -EINVAL;
5150                         }
5151                         action_type = "priority";
5152                         udsp_action.udsp_priority = priority;
5153                         break;
5154                 case 'i':
5155                         rc = parse_long(optarg, &idx);
5156                         if (rc != 0 || idx < 0) {
5157                                 printf("Invalid index \"%s\"\n", optarg);
5158                                 return -EINVAL;
5159                         }
5160                         break;
5161                 case '?':
5162                         print_help(udsp_cmds, "udsp", "add");
5163                 default:
5164                         return 0;
5165                 }
5166         }
5167
5168         if (!(src || dst || rte)) {
5169                 print_help(udsp_cmds, "udsp", "add");
5170                 return 0;
5171         }
5172
5173         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
5174                                   idx, -1, &err_rc);
5175
5176         if (rc != LUSTRE_CFG_RC_NO_ERR)
5177                 cYAML_print_tree2file(stderr, err_rc);
5178
5179         cYAML_free_tree(err_rc);
5180
5181         return rc;
5182 }
5183
5184 static int jt_del_udsp(int argc, char **argv)
5185 {
5186         struct cYAML *err_rc = NULL;
5187         long int idx = -2;
5188         int opt, rc = 0;
5189         bool all = false;
5190
5191         const char *const short_options = "ai:";
5192         static const struct option long_options[] = {
5193         { .name = "all",        .has_arg = no_argument, .val = 'a' },
5194         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
5195         { .name = NULL } };
5196
5197         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
5198         if (rc)
5199                 return rc;
5200
5201         while ((opt = getopt_long(argc, argv, short_options,
5202                                   long_options, NULL)) != -1) {
5203                 switch (opt) {
5204                 case 'a':
5205                         all = true;
5206                         break;
5207                 case 'i':
5208                         rc = parse_long(optarg, &idx);
5209                         if (rc != 0 || idx < -1) {
5210                                 printf("Invalid index \"%s\"\n", optarg);
5211                                 return -EINVAL;
5212                         }
5213                         break;
5214                 case '?':
5215                         print_help(udsp_cmds, "udsp", "del");
5216                 default:
5217                         return 0;
5218                 }
5219         }
5220
5221         if (all && idx != -2) {
5222                 printf("Cannot combine --all with --idx\n");
5223                 return -EINVAL;
5224         } else if (all) {
5225                 idx = -1;
5226         } else if (idx == -2) {
5227                 printf("Must specify --idx or --all\n");
5228                 return -EINVAL;
5229         }
5230
5231         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
5232         if (rc != LUSTRE_CFG_RC_NO_ERR)
5233                 cYAML_print_tree2file(stderr, err_rc);
5234
5235         cYAML_free_tree(err_rc);
5236
5237         return rc;
5238 }
5239
5240 int main(int argc, char **argv)
5241 {
5242         int rc = 0;
5243         struct cYAML *err_rc = NULL;
5244
5245         rc = lustre_lnet_config_lib_init();
5246         if (rc < 0) {
5247                 cYAML_build_error(-1, -1, "lnetctl", "startup",
5248                                   "cannot register LNet device", &err_rc);
5249                 cYAML_print_tree2file(stderr, err_rc);
5250                 return rc;
5251         }
5252
5253         return cfs_parser(argc, argv, cmd_list);
5254 }