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