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