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