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