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