Whamcloud - gitweb
LU-9680 lnet: collect data about peer_ni by using Netlink
[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, "Calculate the CPT associated with NID\n"
121          "\t--nid: NID to calculate the CPT of\n"
122          "\t--ncpt: Number of CPTs to consider in the calculation\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_calc_cpt_of_nid(int argc, char **argv)
440 {
441         int rc, opt;
442         int cpt;
443         long int ncpts = -1;
444         char *nid = NULL;
445         struct cYAML *err_rc = NULL;
446         const char *const short_options = "n:c:h";
447         static const struct option long_options[] = {
448         { .name = "nid",       .has_arg = required_argument, .val = 'n' },
449         { .name = "ncpt",     .has_arg = required_argument, .val = 'c' },
450         { .name = NULL } };
451
452         rc = check_cmd(cmd_list, "", "cpt-of-nid", 0, argc, argv);
453         if (rc)
454                 return rc;
455
456         while ((opt = getopt_long(argc, argv, short_options,
457                                    long_options, NULL)) != -1) {
458                 switch (opt) {
459                 case 'n':
460                         nid = optarg;
461                         break;
462                 case 'c':
463                         rc = parse_long(optarg, &ncpts);
464                         if (rc != 0) {
465                                 cYAML_build_error(-1, -1, "cpt", "get",
466                                                 "cannot parse input", &err_rc);
467                                 cYAML_print_tree2file(stderr, err_rc);
468                                 cYAML_free_tree(err_rc);
469                                 return -1;
470                         }
471                         break;
472                 case '?':
473                         print_help(cmd_list, "", "cpt-of-nid");
474                 default:
475                         return 0;
476                 }
477         }
478
479         cpt = lustre_lnet_calc_cpt_of_nid(nid, ncpts);
480         if (cpt < 0)
481                 return -1;
482
483         printf("cpt:\n    value: %d\n", cpt);
484
485         return 0;
486 }
487
488 static int jt_set_recovery_limit(int argc, char **argv)
489 {
490         long int value;
491         int rc;
492         struct cYAML *err_rc = NULL;
493
494         rc = check_cmd(set_cmds, "set", "recovery_limit", 2, argc, argv);
495         if (rc)
496                 return rc;
497
498         rc = parse_long(argv[1], &value);
499         if (rc != 0) {
500                 cYAML_build_error(-1, -1, "parser", "set",
501                                   "cannot parse recovery_limit value",
502                                   &err_rc);
503                 cYAML_print_tree2file(stderr, err_rc);
504                 cYAML_free_tree(err_rc);
505                 return -1;
506         }
507
508         rc = lustre_lnet_config_recovery_limit(value, -1, &err_rc);
509         if (rc != LUSTRE_CFG_RC_NO_ERR)
510                 cYAML_print_tree2file(stderr, err_rc);
511
512         cYAML_free_tree(err_rc);
513
514         return rc;
515 }
516
517 static int jt_set_max_intf(int argc, char **argv)
518 {
519         long int value;
520         int rc;
521         struct cYAML *err_rc = NULL;
522
523         rc = check_cmd(set_cmds, "set", "max_interfaces", 2, argc, argv);
524         if (rc)
525                 return rc;
526
527         rc = parse_long(argv[1], &value);
528         if (rc != 0) {
529                 cYAML_build_error(-1, -1, "parser", "set",
530                                   "cannot parse max_interfaces value", &err_rc);
531                 cYAML_print_tree2file(stderr, err_rc);
532                 cYAML_free_tree(err_rc);
533                 return -1;
534         }
535
536         rc = lustre_lnet_config_max_intf(value, -1, &err_rc);
537         if (rc != LUSTRE_CFG_RC_NO_ERR)
538                 cYAML_print_tree2file(stderr, err_rc);
539
540         cYAML_free_tree(err_rc);
541
542         return rc;
543 }
544
545 static int jt_set_numa(int argc, char **argv)
546 {
547         long int value;
548         int rc;
549         struct cYAML *err_rc = NULL;
550
551         rc = check_cmd(set_cmds, "set", "numa_range", 2, argc, argv);
552         if (rc)
553                 return rc;
554
555         rc = parse_long(argv[1], &value);
556         if (rc != 0) {
557                 cYAML_build_error(-1, -1, "parser", "set",
558                                   "cannot parse numa_range value", &err_rc);
559                 cYAML_print_tree2file(stderr, err_rc);
560                 cYAML_free_tree(err_rc);
561                 return -1;
562         }
563
564         rc = lustre_lnet_config_numa_range(value, -1, &err_rc);
565         if (rc != LUSTRE_CFG_RC_NO_ERR)
566                 cYAML_print_tree2file(stderr, err_rc);
567
568         cYAML_free_tree(err_rc);
569
570         return rc;
571 }
572
573 static int jt_set_recov_intrv(int argc, char **argv)
574 {
575         long int value;
576         int rc;
577         struct cYAML *err_rc = NULL;
578
579         rc = check_cmd(set_cmds, "set", "recovery_interval", 2, argc, argv);
580         if (rc)
581                 return rc;
582
583         rc = parse_long(argv[1], &value);
584         if (rc != 0) {
585                 cYAML_build_error(-1, -1, "parser", "set",
586                                   "cannot parse recovery interval value", &err_rc);
587                 cYAML_print_tree2file(stderr, err_rc);
588                 cYAML_free_tree(err_rc);
589                 return -1;
590         }
591
592         rc = lustre_lnet_config_recov_intrv(value, -1, &err_rc);
593         if (rc != LUSTRE_CFG_RC_NO_ERR)
594                 cYAML_print_tree2file(stderr, err_rc);
595
596         cYAML_free_tree(err_rc);
597
598         return rc;
599 }
600
601 static int jt_set_rtr_sensitivity(int argc, char **argv)
602 {
603         long int value;
604         int rc;
605         struct cYAML *err_rc = NULL;
606
607         rc = check_cmd(set_cmds, "set", "router_sensitivity", 2, argc, argv);
608         if (rc)
609                 return rc;
610
611         rc = parse_long(argv[1], &value);
612         if (rc != 0) {
613                 cYAML_build_error(-1, -1, "parser", "set",
614                                   "cannot parse router sensitivity value", &err_rc);
615                 cYAML_print_tree2file(stderr, err_rc);
616                 cYAML_free_tree(err_rc);
617                 return -1;
618         }
619
620         rc = lustre_lnet_config_rtr_sensitivity(value, -1, &err_rc);
621         if (rc != LUSTRE_CFG_RC_NO_ERR)
622                 cYAML_print_tree2file(stderr, err_rc);
623
624         cYAML_free_tree(err_rc);
625
626         return rc;
627 }
628
629 static int jt_set_hsensitivity(int argc, char **argv)
630 {
631         long int value;
632         int rc;
633         struct cYAML *err_rc = NULL;
634
635         rc = check_cmd(set_cmds, "set", "health_sensitivity", 2, argc, argv);
636         if (rc)
637                 return rc;
638
639         rc = parse_long(argv[1], &value);
640         if (rc != 0) {
641                 cYAML_build_error(-1, -1, "parser", "set",
642                                   "cannot parse health sensitivity value", &err_rc);
643                 cYAML_print_tree2file(stderr, err_rc);
644                 cYAML_free_tree(err_rc);
645                 return -1;
646         }
647
648         rc = lustre_lnet_config_hsensitivity(value, -1, &err_rc);
649         if (rc != LUSTRE_CFG_RC_NO_ERR)
650                 cYAML_print_tree2file(stderr, err_rc);
651
652         cYAML_free_tree(err_rc);
653
654         return rc;
655 }
656
657 static int jt_reset_stats(int argc, char **argv)
658 {
659         int rc;
660         struct cYAML *err_rc = NULL;
661
662         rc = check_cmd(stats_cmds, "stats", "reset", 0, argc, argv);
663         if (rc)
664                 return rc;
665
666         rc = lustre_lnet_reset_stats(-1, &err_rc);
667         if (rc != LUSTRE_CFG_RC_NO_ERR)
668                 cYAML_print_tree2file(stderr, err_rc);
669
670         cYAML_free_tree(err_rc);
671
672         return rc;
673 }
674
675 static int jt_set_transaction_to(int argc, char **argv)
676 {
677         long int value;
678         int rc;
679         struct cYAML *err_rc = NULL;
680
681         rc = check_cmd(set_cmds, "set", "transaction_timeout", 2, argc, argv);
682         if (rc)
683                 return rc;
684
685         rc = parse_long(argv[1], &value);
686         if (rc != 0) {
687                 cYAML_build_error(-1, -1, "parser", "set",
688                                   "cannot parse transaction timeout value", &err_rc);
689                 cYAML_print_tree2file(stderr, err_rc);
690                 cYAML_free_tree(err_rc);
691                 return -1;
692         }
693
694         rc = lustre_lnet_config_transaction_to(value, -1, &err_rc);
695         if (rc != LUSTRE_CFG_RC_NO_ERR)
696                 cYAML_print_tree2file(stderr, err_rc);
697
698         cYAML_free_tree(err_rc);
699
700         return rc;
701 }
702
703 static int jt_set_retry_count(int argc, char **argv)
704 {
705         long int value;
706         int rc;
707         struct cYAML *err_rc = NULL;
708
709         rc = check_cmd(set_cmds, "set", "retry_count", 2, argc, argv);
710         if (rc)
711                 return rc;
712
713         rc = parse_long(argv[1], &value);
714         if (rc != 0) {
715                 cYAML_build_error(-1, -1, "parser", "set",
716                                   "cannot parse retry_count value", &err_rc);
717                 cYAML_print_tree2file(stderr, err_rc);
718                 cYAML_free_tree(err_rc);
719                 return -1;
720         }
721
722         rc = lustre_lnet_config_retry_count(value, -1, &err_rc);
723         if (rc != LUSTRE_CFG_RC_NO_ERR)
724                 cYAML_print_tree2file(stderr, err_rc);
725
726         cYAML_free_tree(err_rc);
727
728         return rc;
729 }
730
731 static int jt_set_discovery(int argc, char **argv)
732 {
733         long int value;
734         int rc;
735         struct cYAML *err_rc = NULL;
736
737         rc = check_cmd(set_cmds, "set", "discovery", 2, argc, argv);
738         if (rc)
739                 return rc;
740
741         rc = parse_long(argv[1], &value);
742         if (rc != 0) {
743                 cYAML_build_error(-1, -1, "parser", "set",
744                                   "cannot parse discovery value", &err_rc);
745                 cYAML_print_tree2file(stderr, err_rc);
746                 cYAML_free_tree(err_rc);
747                 return -1;
748         }
749
750         rc = lustre_lnet_config_discovery(value, -1, &err_rc);
751         if (rc != LUSTRE_CFG_RC_NO_ERR)
752                 cYAML_print_tree2file(stderr, err_rc);
753
754         cYAML_free_tree(err_rc);
755
756         return rc;
757 }
758
759 static int jt_set_drop_asym_route(int argc, char **argv)
760 {
761         long int value;
762         int rc;
763         struct cYAML *err_rc = NULL;
764
765         rc = check_cmd(set_cmds, "set", "drop_asym_route", 2, argc, argv);
766         if (rc)
767                 return rc;
768
769         rc = parse_long(argv[1], &value);
770         if (rc != 0) {
771                 cYAML_build_error(-1, -1, "parser", "set",
772                                   "cannot parse drop_asym_route value",
773                                   &err_rc);
774                 cYAML_print_tree2file(stderr, err_rc);
775                 cYAML_free_tree(err_rc);
776                 return -1;
777         }
778
779         rc = lustre_lnet_config_drop_asym_route(value, -1, &err_rc);
780         if (rc != LUSTRE_CFG_RC_NO_ERR)
781                 cYAML_print_tree2file(stderr, err_rc);
782
783         cYAML_free_tree(err_rc);
784
785         return rc;
786 }
787
788 static int jt_set_tiny(int argc, char **argv)
789 {
790         long int value;
791         int rc;
792         struct cYAML *err_rc = NULL;
793
794         rc = check_cmd(set_cmds, "set", "tiny_buffers", 2, argc, argv);
795         if (rc)
796                 return rc;
797
798         rc = parse_long(argv[1], &value);
799         if (rc != 0) {
800                 cYAML_build_error(-1, -1, "parser", "set",
801                                   "cannot parse tiny_buffers value", &err_rc);
802                 cYAML_print_tree2file(stderr, err_rc);
803                 cYAML_free_tree(err_rc);
804                 return -1;
805         }
806
807         rc = lustre_lnet_config_buffers(value, -1, -1, -1, &err_rc);
808         if (rc != LUSTRE_CFG_RC_NO_ERR)
809                 cYAML_print_tree2file(stderr, err_rc);
810
811         cYAML_free_tree(err_rc);
812
813         return rc;
814 }
815
816 static int jt_set_small(int argc, char **argv)
817 {
818         long int value;
819         int rc;
820         struct cYAML *err_rc = NULL;
821
822         rc = check_cmd(set_cmds, "set", "small_buffers", 2, argc, argv);
823         if (rc)
824                 return rc;
825
826         rc = parse_long(argv[1], &value);
827         if (rc != 0) {
828                 cYAML_build_error(-1, -1, "parser", "set",
829                                   "cannot parse small_buffers value", &err_rc);
830                 cYAML_print_tree2file(stderr, err_rc);
831                 cYAML_free_tree(err_rc);
832                 return -1;
833         }
834
835         rc = lustre_lnet_config_buffers(-1, value, -1, -1, &err_rc);
836         if (rc != LUSTRE_CFG_RC_NO_ERR)
837                 cYAML_print_tree2file(stderr, err_rc);
838
839         cYAML_free_tree(err_rc);
840
841         return rc;
842 }
843
844 static int jt_set_large(int argc, char **argv)
845 {
846         long int value;
847         int rc;
848         struct cYAML *err_rc = NULL;
849
850         rc = check_cmd(set_cmds, "set", "large_buffers", 2, argc, argv);
851         if (rc)
852                 return rc;
853
854         rc = parse_long(argv[1], &value);
855         if (rc != 0) {
856                 cYAML_build_error(-1, -1, "parser", "set",
857                                   "cannot parse large_buffers value", &err_rc);
858                 cYAML_print_tree2file(stderr, err_rc);
859                 cYAML_free_tree(err_rc);
860                 return -1;
861         }
862
863         rc = lustre_lnet_config_buffers(-1, -1, value, -1, &err_rc);
864         if (rc != LUSTRE_CFG_RC_NO_ERR)
865                 cYAML_print_tree2file(stderr, err_rc);
866
867         cYAML_free_tree(err_rc);
868
869         return rc;
870 }
871
872 static int jt_set_routing(int argc, char **argv)
873 {
874         long int value;
875         struct cYAML *err_rc = NULL;
876         int rc;
877
878         rc = check_cmd(set_cmds, "set", "routing", 2, argc, argv);
879         if (rc)
880                 return rc;
881
882         rc = parse_long(argv[1], &value);
883         if (rc != 0 || (value != 0 && value != 1)) {
884                 cYAML_build_error(-1, -1, "parser", "set",
885                                   "cannot parse routing value.\n"
886                                   "must be 0 for disable or 1 for enable",
887                                   &err_rc);
888                 cYAML_print_tree2file(stderr, err_rc);
889                 cYAML_free_tree(err_rc);
890                 return -1;
891         }
892
893         rc = lustre_lnet_enable_routing(value, -1, &err_rc);
894
895         if (rc != LUSTRE_CFG_RC_NO_ERR)
896                 cYAML_print_tree2file(stderr, err_rc);
897
898         cYAML_free_tree(err_rc);
899
900         return rc;
901 }
902
903 static int jt_set_max_recovery_ping_interval(int argc, char **argv)
904 {
905         long int value;
906         int rc;
907         struct cYAML *err_rc = NULL;
908
909         rc = check_cmd(set_cmds, "set", "maximum recovery_interval", 2, argc, argv);
910         if (rc)
911                 return rc;
912
913         rc = parse_long(argv[1], &value);
914         if (rc != 0) {
915                 cYAML_build_error(-1, -1, "parser", "set",
916                                   "cannot parse maximum recovery interval value",
917                                   &err_rc);
918                 cYAML_print_tree2file(stderr, err_rc);
919                 cYAML_free_tree(err_rc);
920                 return -1;
921         }
922
923         rc = lustre_lnet_config_max_recovery_ping_interval(value, -1, &err_rc);
924         if (rc != LUSTRE_CFG_RC_NO_ERR)
925                 cYAML_print_tree2file(stderr, err_rc);
926
927         cYAML_free_tree(err_rc);
928
929         return rc;
930 }
931
932 static void yaml_lnet_print_error(int op, char *cmd, const char *errstr)
933 {
934         char errcode[INT_STRING_LEN];
935         yaml_emitter_t log;
936         yaml_event_t event;
937         const char *flag;
938         int rc;
939
940         snprintf(errcode, sizeof(errcode), "%d", errno);
941
942         yaml_emitter_initialize(&log);
943         yaml_emitter_set_indent(&log, LNET_DEFAULT_INDENT);
944         yaml_emitter_set_output_file(&log, stderr);
945
946         yaml_emitter_open(&log);
947         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
948         rc = yaml_emitter_emit(&log, &event);
949         if (rc == 0)
950                 goto emitter_error;
951
952         yaml_mapping_start_event_initialize(&event, NULL,
953                                             (yaml_char_t *)YAML_MAP_TAG,
954                                             1, YAML_ANY_MAPPING_STYLE);
955         rc = yaml_emitter_emit(&log, &event);
956         if (rc == 0)
957                 goto emitter_error;
958
959         switch (op) {
960         case NLM_F_CREATE:
961                 flag = "add";
962                 break;
963         case NLM_F_REPLACE:
964                 flag = "set";
965                 break;
966         case 0:
967                 flag = "del";
968                 break;
969         case NLM_F_DUMP:
970         default:
971                 flag = "show";
972                 break;
973         }
974
975         yaml_scalar_event_initialize(&event, NULL,
976                                      (yaml_char_t *)YAML_STR_TAG,
977                                      (yaml_char_t *)flag,
978                                      strlen(flag), 1, 0,
979                                      YAML_PLAIN_SCALAR_STYLE);
980         rc = yaml_emitter_emit(&log, &event);
981         if (rc == 0)
982                 goto emitter_error;
983
984         yaml_sequence_start_event_initialize(&event, NULL,
985                                              (yaml_char_t *)YAML_SEQ_TAG,
986                                              1, YAML_ANY_SEQUENCE_STYLE);
987         rc = yaml_emitter_emit(&log, &event);
988         if (rc == 0)
989                 goto emitter_error;
990
991         yaml_mapping_start_event_initialize(&event, NULL,
992                                             (yaml_char_t *)YAML_MAP_TAG,
993                                             1, YAML_ANY_MAPPING_STYLE);
994         rc = yaml_emitter_emit(&log, &event);
995         if (rc == 0)
996                 goto emitter_error;
997
998         yaml_scalar_event_initialize(&event, NULL,
999                                      (yaml_char_t *)YAML_STR_TAG,
1000                                      (yaml_char_t *)cmd,
1001                                      strlen(cmd),
1002                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
1003         rc = yaml_emitter_emit(&log, &event);
1004         if (rc == 0)
1005                 goto emitter_error;
1006
1007         yaml_scalar_event_initialize(&event, NULL,
1008                                      (yaml_char_t *)YAML_STR_TAG,
1009                                      (yaml_char_t *)"",
1010                                      strlen(""),
1011                                      1, 0, YAML_PLAIN_SCALAR_STYLE);
1012         rc = yaml_emitter_emit(&log, &event);
1013         if (rc == 0)
1014                 goto emitter_error;
1015
1016         yaml_scalar_event_initialize(&event, NULL,
1017                                      (yaml_char_t *)YAML_STR_TAG,
1018                                      (yaml_char_t *)"errno",
1019                                      strlen("errno"), 1, 0,
1020                                      YAML_PLAIN_SCALAR_STYLE);
1021         rc = yaml_emitter_emit(&log, &event);
1022         if (rc == 0)
1023                 goto emitter_error;
1024
1025         yaml_scalar_event_initialize(&event, NULL,
1026                                      (yaml_char_t *)YAML_INT_TAG,
1027                                      (yaml_char_t *)errcode,
1028                                      strlen(errcode), 1, 0,
1029                                      YAML_PLAIN_SCALAR_STYLE);
1030         rc = yaml_emitter_emit(&log, &event);
1031         if (rc == 0)
1032                 goto emitter_error;
1033
1034
1035         yaml_scalar_event_initialize(&event, NULL,
1036                                      (yaml_char_t *)YAML_STR_TAG,
1037                                      (yaml_char_t *)"descr",
1038                                      strlen("descr"), 1, 0,
1039                                      YAML_PLAIN_SCALAR_STYLE);
1040         rc = yaml_emitter_emit(&log, &event);
1041         if (rc == 0)
1042                 goto emitter_error;
1043
1044         yaml_scalar_event_initialize(&event, NULL,
1045                                      (yaml_char_t *)YAML_STR_TAG,
1046                                      (yaml_char_t *)errstr,
1047                                      strlen(errstr), 1, 0,
1048                                      YAML_DOUBLE_QUOTED_SCALAR_STYLE);
1049         rc = yaml_emitter_emit(&log, &event);
1050         if (rc == 0)
1051                 goto emitter_error;
1052
1053         yaml_mapping_end_event_initialize(&event);
1054         rc = yaml_emitter_emit(&log, &event);
1055         if (rc == 0)
1056                 goto emitter_error;
1057
1058         yaml_sequence_end_event_initialize(&event);
1059         rc = yaml_emitter_emit(&log, &event);
1060         if (rc == 0)
1061                 goto emitter_error;
1062
1063         yaml_mapping_end_event_initialize(&event);
1064         rc = yaml_emitter_emit(&log, &event);
1065         if (rc == 0)
1066                 goto emitter_error;
1067
1068         yaml_document_end_event_initialize(&event, 0);
1069         rc = yaml_emitter_emit(&log, &event);
1070         if (rc == 0)
1071                 goto emitter_error;
1072
1073         rc = yaml_emitter_close(&log);
1074 emitter_error:
1075         if (rc == 0)
1076                 yaml_emitter_log_error(&log, stdout);
1077         yaml_emitter_delete(&log);
1078 }
1079
1080 static int jt_config_lnet(int argc, char **argv)
1081 {
1082         struct cYAML *err_rc = NULL;
1083         bool load_mod_params = false;
1084         int rc, opt;
1085
1086         const char *const short_options = "a";
1087         static const struct option long_options[] = {
1088                 { .name = "all",  .has_arg = no_argument, .val = 'a' },
1089                 { .name = NULL }
1090         };
1091
1092         rc = check_cmd(lnet_cmds, "lnet", "configure", 0, argc, argv);
1093         if (rc)
1094                 return rc;
1095
1096         while ((opt = getopt_long(argc, argv, short_options,
1097                                    long_options, NULL)) != -1) {
1098                 switch (opt) {
1099                 case 'a':
1100                         load_mod_params = true;
1101                         break;
1102                 default:
1103                         return 0;
1104                 }
1105         }
1106
1107         rc = lustre_lnet_config_ni_system(LNET_CONFIGURE, load_mod_params,
1108                                           -1, &err_rc);
1109
1110         if (rc != LUSTRE_CFG_RC_NO_ERR)
1111                 cYAML_print_tree2file(stderr, err_rc);
1112
1113         cYAML_free_tree(err_rc);
1114
1115         return rc;
1116 }
1117
1118 static int jt_unconfig_lnet(int argc, char **argv)
1119 {
1120         struct cYAML *err_rc = NULL;
1121         int rc;
1122
1123         rc = check_cmd(lnet_cmds, "lnet", "unconfigure", 0, argc, argv);
1124         if (rc)
1125                 return rc;
1126
1127         rc = lustre_lnet_config_ni_system(LNET_UNCONFIGURE, 0, -1, &err_rc);
1128
1129         if (rc != LUSTRE_CFG_RC_NO_ERR)
1130                 cYAML_print_tree2file(stderr, err_rc);
1131
1132         cYAML_free_tree(err_rc);
1133
1134         return rc;
1135 }
1136
1137 static int yaml_lnet_route(char *nw, char *gw, int hops, int prio, int sen,
1138                            int version, int flags)
1139 {
1140         struct nl_sock *sk = NULL;
1141         const char *msg = NULL;
1142         yaml_emitter_t output;
1143         yaml_parser_t reply;
1144         yaml_event_t event;
1145         int rc;
1146
1147         /* Create Netlink emitter to send request to kernel */
1148         sk = nl_socket_alloc();
1149         if (!sk)
1150                 return -EOPNOTSUPP;
1151
1152         /* Setup parser to receive Netlink packets */
1153         rc = yaml_parser_initialize(&reply);
1154         if (rc == 0) {
1155                 nl_socket_free(sk);
1156                 return -EOPNOTSUPP;
1157         }
1158
1159         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1160         if (rc == 0) {
1161                 msg = yaml_parser_get_reader_error(&reply);
1162                 goto free_reply;
1163         }
1164
1165         /* Create Netlink emitter to send request to kernel */
1166         rc = yaml_emitter_initialize(&output);
1167         if (rc == 0) {
1168                 msg = "failed to initialize emitter";
1169                 goto free_reply;
1170         }
1171
1172         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1173                                              version, LNET_CMD_ROUTES, flags);
1174         if (rc == 0)
1175                 goto emitter_error;
1176
1177         yaml_emitter_open(&output);
1178         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1179         rc = yaml_emitter_emit(&output, &event);
1180         if (rc == 0)
1181                 goto emitter_error;
1182
1183         yaml_mapping_start_event_initialize(&event, NULL,
1184                                             (yaml_char_t *)YAML_MAP_TAG,
1185                                             1, YAML_ANY_MAPPING_STYLE);
1186         rc = yaml_emitter_emit(&output, &event);
1187         if (rc == 0)
1188                 goto emitter_error;
1189
1190         yaml_scalar_event_initialize(&event, NULL,
1191                                      (yaml_char_t *)YAML_STR_TAG,
1192                                      (yaml_char_t *)"route",
1193                                      strlen("route"), 1, 0,
1194                                      YAML_PLAIN_SCALAR_STYLE);
1195         rc = yaml_emitter_emit(&output, &event);
1196         if (rc == 0)
1197                 goto emitter_error;
1198
1199         if (nw || gw || hops != -1 || prio != -1) {
1200                 char num[INT_STRING_LEN];
1201
1202                 yaml_sequence_start_event_initialize(&event, NULL,
1203                                                      (yaml_char_t *)YAML_SEQ_TAG,
1204                                                      1,
1205                                                      YAML_BLOCK_SEQUENCE_STYLE);
1206                 rc = yaml_emitter_emit(&output, &event);
1207                 if (rc == 0)
1208                         goto emitter_error;
1209
1210                 if (nw) {
1211                         yaml_mapping_start_event_initialize(&event, NULL,
1212                                                             (yaml_char_t *)YAML_MAP_TAG,
1213                                                             1,
1214                                                             YAML_BLOCK_MAPPING_STYLE);
1215                         rc = yaml_emitter_emit(&output, &event);
1216                         if (rc == 0)
1217                                 goto emitter_error;
1218
1219                         yaml_scalar_event_initialize(&event, NULL,
1220                                                      (yaml_char_t *)YAML_STR_TAG,
1221                                                      (yaml_char_t *)"net",
1222                                                      strlen("net"), 1, 0,
1223                                                      YAML_PLAIN_SCALAR_STYLE);
1224                         rc = yaml_emitter_emit(&output, &event);
1225                         if (rc == 0)
1226                                 goto emitter_error;
1227
1228                         yaml_scalar_event_initialize(&event, NULL,
1229                                                      (yaml_char_t *)YAML_STR_TAG,
1230                                                      (yaml_char_t *)nw,
1231                                                      strlen(nw), 1, 0,
1232                                                      YAML_PLAIN_SCALAR_STYLE);
1233                         rc = yaml_emitter_emit(&output, &event);
1234                         if (rc == 0)
1235                                 goto emitter_error;
1236
1237                         yaml_mapping_end_event_initialize(&event);
1238                         rc = yaml_emitter_emit(&output, &event);
1239                         if (rc == 0)
1240                                 goto emitter_error;
1241                 }
1242
1243                 if (gw) {
1244                         yaml_mapping_start_event_initialize(&event, NULL,
1245                                                             (yaml_char_t *)YAML_MAP_TAG,
1246                                                             1,
1247                                                             YAML_BLOCK_MAPPING_STYLE);
1248                         rc = yaml_emitter_emit(&output, &event);
1249                         if (rc == 0)
1250                                 goto emitter_error;
1251
1252                         yaml_scalar_event_initialize(&event, NULL,
1253                                                      (yaml_char_t *)YAML_STR_TAG,
1254                                                      (yaml_char_t *)"gateway",
1255                                                      strlen("gateway"), 1, 0,
1256                                                      YAML_PLAIN_SCALAR_STYLE);
1257                         rc = yaml_emitter_emit(&output, &event);
1258                         if (rc == 0)
1259                                 goto emitter_error;
1260
1261                         yaml_scalar_event_initialize(&event, NULL,
1262                                                      (yaml_char_t *)YAML_STR_TAG,
1263                                                      (yaml_char_t *)gw,
1264                                                      strlen(gw), 1, 0,
1265                                                      YAML_PLAIN_SCALAR_STYLE);
1266                         rc = yaml_emitter_emit(&output, &event);
1267                         if (rc == 0)
1268                                 goto emitter_error;
1269
1270                         yaml_mapping_end_event_initialize(&event);
1271                         rc = yaml_emitter_emit(&output, &event);
1272                         if (rc == 0)
1273                                 goto emitter_error;
1274                 }
1275
1276                 if (hops != -1) {
1277                         yaml_mapping_start_event_initialize(&event, NULL,
1278                                                             (yaml_char_t *)YAML_MAP_TAG,
1279                                                             1,
1280                                                             YAML_BLOCK_MAPPING_STYLE);
1281                         rc = yaml_emitter_emit(&output, &event);
1282                         if (rc == 0)
1283                                 goto emitter_error;
1284
1285                         yaml_scalar_event_initialize(&event, NULL,
1286                                                      (yaml_char_t *)YAML_STR_TAG,
1287                                                      (yaml_char_t *)"hop",
1288                                                      strlen("hop"), 1, 0,
1289                                                      YAML_PLAIN_SCALAR_STYLE);
1290                         rc = yaml_emitter_emit(&output, &event);
1291                         if (rc == 0)
1292                                 goto emitter_error;
1293
1294                         snprintf(num, sizeof(num), "%d", hops);
1295                         yaml_scalar_event_initialize(&event, NULL,
1296                                                      (yaml_char_t *)YAML_INT_TAG,
1297                                                      (yaml_char_t *)num,
1298                                                      strlen(num), 1, 0,
1299                                                      YAML_PLAIN_SCALAR_STYLE);
1300                         rc = yaml_emitter_emit(&output, &event);
1301                         if (rc == 0)
1302                                 goto emitter_error;
1303
1304                         yaml_mapping_end_event_initialize(&event);
1305                         rc = yaml_emitter_emit(&output, &event);
1306                         if (rc == 0)
1307                                 goto emitter_error;
1308                 }
1309
1310                 if (prio != -1) {
1311                         yaml_mapping_start_event_initialize(&event, NULL,
1312                                                             (yaml_char_t *)YAML_MAP_TAG,
1313                                                             1,
1314                                                             YAML_BLOCK_MAPPING_STYLE);
1315                         rc = yaml_emitter_emit(&output, &event);
1316                         if (rc == 0)
1317                                 goto emitter_error;
1318
1319                         yaml_scalar_event_initialize(&event, NULL,
1320                                                      (yaml_char_t *)YAML_STR_TAG,
1321                                                      (yaml_char_t *)"priority",
1322                                                      strlen("priority"), 1, 0,
1323                                                      YAML_PLAIN_SCALAR_STYLE);
1324                         rc = yaml_emitter_emit(&output, &event);
1325                         if (rc == 0)
1326                                 goto emitter_error;
1327
1328                         snprintf(num, sizeof(num), "%d", prio);
1329                         yaml_scalar_event_initialize(&event, NULL,
1330                                                      (yaml_char_t *)YAML_INT_TAG,
1331                                                      (yaml_char_t *)num,
1332                                                      strlen(num), 1, 0,
1333                                                      YAML_PLAIN_SCALAR_STYLE);
1334                         rc = yaml_emitter_emit(&output, &event);
1335                         if (rc == 0)
1336                                 goto emitter_error;
1337
1338                         yaml_mapping_end_event_initialize(&event);
1339                         rc = yaml_emitter_emit(&output, &event);
1340                         if (rc == 0)
1341                                 goto emitter_error;
1342                 }
1343
1344                 if (sen != -1) {
1345                         yaml_mapping_start_event_initialize(&event, NULL,
1346                                                             (yaml_char_t *)YAML_MAP_TAG,
1347                                                             1,
1348                                                             YAML_BLOCK_MAPPING_STYLE);
1349                         rc = yaml_emitter_emit(&output, &event);
1350                         if (rc == 0)
1351                                 goto emitter_error;
1352
1353                         yaml_scalar_event_initialize(&event, NULL,
1354                                                      (yaml_char_t *)YAML_STR_TAG,
1355                                                      (yaml_char_t *)"health_sensitivity",
1356                                                      strlen("health_sensitivity"),
1357                                                      1, 0,
1358                                                      YAML_PLAIN_SCALAR_STYLE);
1359                         rc = yaml_emitter_emit(&output, &event);
1360                         if (rc == 0)
1361                                 goto emitter_error;
1362
1363                         snprintf(num, sizeof(num), "%d", sen);
1364                         yaml_scalar_event_initialize(&event, NULL,
1365                                                      (yaml_char_t *)YAML_INT_TAG,
1366                                                      (yaml_char_t *)num,
1367                                                      strlen(num), 1, 0,
1368                                                      YAML_PLAIN_SCALAR_STYLE);
1369                         rc = yaml_emitter_emit(&output, &event);
1370                         if (rc == 0)
1371                                 goto emitter_error;
1372
1373                         yaml_mapping_end_event_initialize(&event);
1374                         rc = yaml_emitter_emit(&output, &event);
1375                         if (rc == 0)
1376                                 goto emitter_error;
1377                 }
1378
1379                 yaml_sequence_end_event_initialize(&event);
1380                 rc = yaml_emitter_emit(&output, &event);
1381                 if (rc == 0)
1382                         goto emitter_error;
1383         } else {
1384                 yaml_scalar_event_initialize(&event, NULL,
1385                                              (yaml_char_t *)YAML_STR_TAG,
1386                                              (yaml_char_t *)"",
1387                                              strlen(""), 1, 0,
1388                                              YAML_PLAIN_SCALAR_STYLE);
1389                 rc = yaml_emitter_emit(&output, &event);
1390                 if (rc == 0)
1391                         goto emitter_error;
1392         }
1393
1394         yaml_mapping_end_event_initialize(&event);
1395         rc = yaml_emitter_emit(&output, &event);
1396         if (rc == 0)
1397                 goto emitter_error;
1398
1399         yaml_document_end_event_initialize(&event, 0);
1400         rc = yaml_emitter_emit(&output, &event);
1401         if (rc == 0)
1402                 goto emitter_error;
1403
1404         rc = yaml_emitter_close(&output);
1405 emitter_error:
1406         if (rc == 0) {
1407                 yaml_emitter_log_error(&output, stderr);
1408                 rc = -EINVAL;
1409         } else {
1410                 yaml_document_t errmsg;
1411
1412                 rc = yaml_parser_load(&reply, &errmsg);
1413                 if (rc == 1 && flags == NLM_F_DUMP) {
1414                         yaml_emitter_t debug;
1415
1416                         rc = yaml_emitter_initialize(&debug);
1417                         if (rc == 1) {
1418                                 yaml_emitter_set_indent(&debug, 6);
1419                                 yaml_emitter_set_output_file(&debug,
1420                                                              stdout);
1421                                 rc = yaml_emitter_dump(&debug, &errmsg);
1422                         }
1423                         yaml_emitter_delete(&debug);
1424                 } else {
1425                         msg = yaml_parser_get_reader_error(&reply);
1426                         /* If we didn't find any routes just be silent */
1427                         if (msg && strcmp(msg, "No routes found") == 0)
1428                                 rc = 1;
1429                 }
1430                 yaml_document_delete(&errmsg);
1431         }
1432         yaml_emitter_delete(&output);
1433 free_reply:
1434         if (rc == 0) {
1435                 yaml_lnet_print_error(flags, "route", msg);
1436                 rc = -EINVAL;
1437         }
1438         yaml_parser_delete(&reply);
1439         nl_socket_free(sk);
1440
1441         return rc == 1 ? 0 : rc;
1442 }
1443
1444 static int jt_add_route(int argc, char **argv)
1445 {
1446         char *network = NULL, *gateway = NULL;
1447         long int hop = -1, prio = -1, sen = -1;
1448         struct cYAML *err_rc = NULL;
1449         int rc, opt;
1450
1451         const char *const short_options = "n:g:c:p:";
1452         static const struct option long_options[] = {
1453         { .name = "net",       .has_arg = required_argument, .val = 'n' },
1454         { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
1455         { .name = "hop",       .has_arg = required_argument, .val = 'c' },
1456         { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
1457         { .name = "priority",  .has_arg = required_argument, .val = 'p' },
1458         { .name = "health_sensitivity",  .has_arg = required_argument, .val = 's' },
1459         { .name = NULL } };
1460
1461         rc = check_cmd(route_cmds, "route", "add", 0, argc, argv);
1462         if (rc)
1463                 return rc;
1464
1465         while ((opt = getopt_long(argc, argv, short_options,
1466                                    long_options, NULL)) != -1) {
1467                 switch (opt) {
1468                 case 'n':
1469                         network = optarg;
1470                         break;
1471                 case 'g':
1472                         gateway = optarg;
1473                         break;
1474                 case 'c':
1475                         rc = parse_long(optarg, &hop);
1476                         if (rc != 0) {
1477                                 /* ignore option */
1478                                 hop = -1;
1479                                 continue;
1480                         }
1481                         break;
1482                 case 'p':
1483                         rc = parse_long(optarg, &prio);
1484                         if (rc != 0) {
1485                                 /* ingore option */
1486                                 prio = -1;
1487                                 continue;
1488                         }
1489                         break;
1490                 case 's':
1491                         rc = parse_long(optarg, &sen);
1492                         if (rc != 0) {
1493                                 /* ingore option */
1494                                 sen = -1;
1495                                 continue;
1496                         }
1497                         break;
1498
1499                 case '?':
1500                         print_help(route_cmds, "route", "add");
1501                 default:
1502                         return 0;
1503                 }
1504         }
1505
1506         rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
1507                                       &err_rc);
1508
1509         if (rc != LUSTRE_CFG_RC_NO_ERR)
1510                 cYAML_print_tree2file(stderr, err_rc);
1511
1512         cYAML_free_tree(err_rc);
1513
1514         return rc;
1515 }
1516
1517 static int yaml_add_ni_tunables(yaml_emitter_t *output,
1518                                 struct lnet_ioctl_config_lnd_tunables *tunables,
1519                                 struct lnet_dlc_network_descr *nw_descr)
1520 {
1521         char num[INT_STRING_LEN];
1522         yaml_event_t event;
1523         int rc;
1524
1525         if (tunables->lt_cmn.lct_peer_timeout < 0 &&
1526             tunables->lt_cmn.lct_peer_tx_credits <= 0 &&
1527             tunables->lt_cmn.lct_peer_rtr_credits <= 0 &&
1528             tunables->lt_cmn.lct_max_tx_credits <= 0)
1529                 goto skip_general_settings;
1530
1531         yaml_scalar_event_initialize(&event, NULL,
1532                                      (yaml_char_t *)YAML_STR_TAG,
1533                                      (yaml_char_t *)"tunables",
1534                                      strlen("tunables"), 1, 0,
1535                                      YAML_PLAIN_SCALAR_STYLE);
1536         rc = yaml_emitter_emit(output, &event);
1537         if (rc == 0)
1538                 goto error;
1539
1540         yaml_mapping_start_event_initialize(&event, NULL,
1541                                             (yaml_char_t *)YAML_MAP_TAG,
1542                                             1, YAML_ANY_MAPPING_STYLE);
1543         rc = yaml_emitter_emit(output, &event);
1544         if (rc == 0)
1545                 goto error;
1546
1547         if (tunables->lt_cmn.lct_peer_timeout >= 0) {
1548                 yaml_scalar_event_initialize(&event, NULL,
1549                                              (yaml_char_t *)YAML_STR_TAG,
1550                                              (yaml_char_t *)"peer_timeout",
1551                                              strlen("peer_timeout"), 1, 0,
1552                                              YAML_PLAIN_SCALAR_STYLE);
1553                 rc = yaml_emitter_emit(output, &event);
1554                 if (rc == 0)
1555                         goto error;
1556
1557                 snprintf(num, sizeof(num), "%u",
1558                          tunables->lt_cmn.lct_peer_timeout);
1559                 yaml_scalar_event_initialize(&event, NULL,
1560                                              (yaml_char_t *)YAML_INT_TAG,
1561                                              (yaml_char_t *)num,
1562                                              strlen(num), 1, 0,
1563                                              YAML_PLAIN_SCALAR_STYLE);
1564                 rc = yaml_emitter_emit(output, &event);
1565                 if (rc == 0)
1566                         goto error;
1567         }
1568
1569         if (tunables->lt_cmn.lct_peer_tx_credits > 0) {
1570                 yaml_scalar_event_initialize(&event, NULL,
1571                                              (yaml_char_t *)YAML_STR_TAG,
1572                                              (yaml_char_t *)"peer_credits",
1573                                              strlen("peer_credits"), 1, 0,
1574                                              YAML_PLAIN_SCALAR_STYLE);
1575                 rc = yaml_emitter_emit(output, &event);
1576                 if (rc == 0)
1577                         goto error;
1578
1579                 snprintf(num, sizeof(num), "%u",
1580                          tunables->lt_cmn.lct_peer_tx_credits);
1581                 yaml_scalar_event_initialize(&event, NULL,
1582                                              (yaml_char_t *)YAML_INT_TAG,
1583                                              (yaml_char_t *)num,
1584                                              strlen(num), 1, 0,
1585                                              YAML_PLAIN_SCALAR_STYLE);
1586                 rc = yaml_emitter_emit(output, &event);
1587                 if (rc == 0)
1588                         goto error;
1589         }
1590
1591         if (tunables->lt_cmn.lct_peer_rtr_credits > 0) {
1592                 yaml_scalar_event_initialize(&event, NULL,
1593                                              (yaml_char_t *)YAML_STR_TAG,
1594                                              (yaml_char_t *)"peer_buffer_credits",
1595                                              strlen("peer_buffer_credits"), 1, 0,
1596                                              YAML_PLAIN_SCALAR_STYLE);
1597                 rc = yaml_emitter_emit(output, &event);
1598                 if (rc == 0)
1599                         goto error;
1600
1601                 snprintf(num, sizeof(num), "%u",
1602                          tunables->lt_cmn.lct_peer_rtr_credits);
1603                 yaml_scalar_event_initialize(&event, NULL,
1604                                              (yaml_char_t *)YAML_INT_TAG,
1605                                              (yaml_char_t *)num,
1606                                              strlen(num), 1, 0,
1607                                              YAML_PLAIN_SCALAR_STYLE);
1608                 rc = yaml_emitter_emit(output, &event);
1609                 if (rc == 0)
1610                         goto error;
1611         }
1612
1613         if (tunables->lt_cmn.lct_max_tx_credits > 0) {
1614                 yaml_scalar_event_initialize(&event, NULL,
1615                                              (yaml_char_t *)YAML_STR_TAG,
1616                                              (yaml_char_t *)"credits",
1617                                              strlen("credits"), 1, 0,
1618                                              YAML_PLAIN_SCALAR_STYLE);
1619                 rc = yaml_emitter_emit(output, &event);
1620                 if (rc == 0)
1621                         goto error;
1622
1623                 snprintf(num, sizeof(num), "%u",
1624                          tunables->lt_cmn.lct_max_tx_credits);
1625                 yaml_scalar_event_initialize(&event, NULL,
1626                                              (yaml_char_t *)YAML_INT_TAG,
1627                                              (yaml_char_t *)num,
1628                                              strlen(num), 1, 0,
1629                                              YAML_PLAIN_SCALAR_STYLE);
1630                 rc = yaml_emitter_emit(output, &event);
1631                 if (rc == 0)
1632                         goto error;
1633         }
1634
1635         yaml_mapping_end_event_initialize(&event);
1636         rc = yaml_emitter_emit(output, &event);
1637         if (rc == 0)
1638                 goto error;
1639
1640 skip_general_settings:
1641         if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1642 #ifdef HAVE_KFILND
1643             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0 ||
1644             tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0] ||
1645 #endif
1646             tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1647                 yaml_scalar_event_initialize(&event, NULL,
1648                                              (yaml_char_t *)YAML_STR_TAG,
1649                                              (yaml_char_t *)"lnd tunables",
1650                                              strlen("lnd tunables"), 1, 0,
1651                                              YAML_PLAIN_SCALAR_STYLE);
1652                 rc = yaml_emitter_emit(output, &event);
1653                 if (rc == 0)
1654                         goto error;
1655
1656                 yaml_mapping_start_event_initialize(&event, NULL,
1657                                                     (yaml_char_t *)YAML_MAP_TAG,
1658                                                     1, YAML_ANY_MAPPING_STYLE);
1659                 rc = yaml_emitter_emit(output, &event);
1660                 if (rc == 0)
1661                         goto error;
1662 #ifdef HAVE_KFILND
1663                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key > 0) {
1664                         yaml_scalar_event_initialize(&event, NULL,
1665                                                      (yaml_char_t *)YAML_STR_TAG,
1666                                                      (yaml_char_t *)"auth_key",
1667                                                      strlen("auth_key"), 1, 0,
1668                                                      YAML_PLAIN_SCALAR_STYLE);
1669                         rc = yaml_emitter_emit(output, &event);
1670                         if (rc == 0)
1671                                 goto error;
1672
1673                         snprintf(num, sizeof(num), "%u",
1674                                  tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key);
1675
1676                         yaml_scalar_event_initialize(&event, NULL,
1677                                                      (yaml_char_t *)YAML_INT_TAG,
1678                                                      (yaml_char_t *)num,
1679                                                      strlen(num), 1, 0,
1680                                                      YAML_PLAIN_SCALAR_STYLE);
1681                         rc = yaml_emitter_emit(output, &event);
1682                         if (rc == 0)
1683                                 goto error;
1684                 }
1685
1686                 if (tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0]) {
1687                         char *tc = &tunables->lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0];
1688
1689                         yaml_scalar_event_initialize(&event, NULL,
1690                                                      (yaml_char_t *)YAML_STR_TAG,
1691                                                      (yaml_char_t *)"traffic_class",
1692                                                      strlen("traffic_class"), 1, 0,
1693                                                      YAML_PLAIN_SCALAR_STYLE);
1694                         rc = yaml_emitter_emit(output, &event);
1695                         if (rc == 0)
1696                                 goto error;
1697
1698                         yaml_scalar_event_initialize(&event, NULL,
1699                                                      (yaml_char_t *)YAML_INT_TAG,
1700                                                      (yaml_char_t *)tc,
1701                                                      strlen(tc), 1, 0,
1702                                                      YAML_PLAIN_SCALAR_STYLE);
1703
1704                         rc = yaml_emitter_emit(output, &event);
1705                         if (rc == 0)
1706                                 goto error;
1707                 }
1708 #endif
1709                 if (tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer > 0 ||
1710                     tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer > 0) {
1711                         int cpp = 0;
1712
1713                         yaml_scalar_event_initialize(&event, NULL,
1714                                                      (yaml_char_t *)YAML_STR_TAG,
1715                                                      (yaml_char_t *)"conns_per_peer",
1716                                                      strlen("conns_per_peer"), 1, 0,
1717                                                      YAML_PLAIN_SCALAR_STYLE);
1718                         rc = yaml_emitter_emit(output, &event);
1719                         if (rc == 0)
1720                                 goto error;
1721
1722                         if (LNET_NETTYP(nw_descr->nw_id) == SOCKLND)
1723                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer;
1724                         else if (LNET_NETTYP(nw_descr->nw_id) == O2IBLND)
1725                                 cpp = tunables->lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer;
1726                         snprintf(num, sizeof(num), "%u", cpp);
1727
1728                         yaml_scalar_event_initialize(&event, NULL,
1729                                                      (yaml_char_t *)YAML_INT_TAG,
1730                                                      (yaml_char_t *)num,
1731                                                      strlen(num), 1, 0,
1732                                                      YAML_PLAIN_SCALAR_STYLE);
1733                         rc = yaml_emitter_emit(output, &event);
1734                         if (rc == 0)
1735                                 goto error;
1736                 }
1737
1738                 yaml_mapping_end_event_initialize(&event);
1739                 rc = yaml_emitter_emit(output, &event);
1740         }
1741 error:
1742         return rc;
1743 }
1744
1745 static int yaml_lnet_config_ni(char *net_id, char *ip2net,
1746                                struct lnet_dlc_network_descr *nw_descr,
1747                                struct lnet_ioctl_config_lnd_tunables *tunables,
1748                                struct cfs_expr_list *global_cpts,
1749                                int version, int flags)
1750 {
1751         struct lnet_dlc_intf_descr *intf;
1752         struct nl_sock *sk = NULL;
1753         const char *msg = NULL;
1754         yaml_emitter_t output;
1755         yaml_parser_t reply;
1756         yaml_event_t event;
1757         int rc;
1758
1759         if (!(flags & NLM_F_DUMP) && !ip2net && (!nw_descr || nw_descr->nw_id == 0)) {
1760                 fprintf(stdout, "missing mandatory parameters in NI config: '%s'",
1761                         (!nw_descr) ? "network , interface" :
1762                         (nw_descr->nw_id == 0) ? "network" : "interface");
1763                 return -EINVAL;
1764         }
1765
1766         if ((flags == NLM_F_CREATE) && !ip2net && list_empty(&nw_descr->nw_intflist)) {
1767                 fprintf(stdout, "creating a local NI needs at least one interface");
1768                 return -EINVAL;
1769         }
1770
1771         /* Create Netlink emitter to send request to kernel */
1772         sk = nl_socket_alloc();
1773         if (!sk)
1774                 return -EOPNOTSUPP;
1775
1776         /* Setup parser to receive Netlink packets */
1777         rc = yaml_parser_initialize(&reply);
1778         if (rc == 0) {
1779                 nl_socket_free(sk);
1780                 return -EOPNOTSUPP;
1781         }
1782
1783         rc = yaml_parser_set_input_netlink(&reply, sk, false);
1784         if (rc == 0) {
1785                 msg = yaml_parser_get_reader_error(&reply);
1786                 goto free_reply;
1787         }
1788
1789         /* Create Netlink emitter to send request to kernel */
1790         rc = yaml_emitter_initialize(&output);
1791         if (rc == 0) {
1792                 msg = "failed to initialize emitter";
1793                 goto free_reply;
1794         }
1795
1796         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
1797                                              version, LNET_CMD_NETS, flags);
1798         if (rc == 0)
1799                 goto emitter_error;
1800
1801         yaml_emitter_open(&output);
1802         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
1803         rc = yaml_emitter_emit(&output, &event);
1804         if (rc == 0)
1805                 goto emitter_error;
1806
1807         yaml_mapping_start_event_initialize(&event, NULL,
1808                                             (yaml_char_t *)YAML_MAP_TAG,
1809                                             1, YAML_ANY_MAPPING_STYLE);
1810         rc = yaml_emitter_emit(&output, &event);
1811         if (rc == 0)
1812                 goto emitter_error;
1813
1814         yaml_scalar_event_initialize(&event, NULL,
1815                                      (yaml_char_t *)YAML_STR_TAG,
1816                                      (yaml_char_t *)"net",
1817                                      strlen("net"), 1, 0,
1818                                      YAML_PLAIN_SCALAR_STYLE);
1819         rc = yaml_emitter_emit(&output, &event);
1820         if (rc == 0)
1821                 goto emitter_error;
1822
1823         if (net_id || ip2net) {
1824                 char *key = net_id ? "net type" : "ip2net";
1825                 char *value = net_id ? net_id : ip2net;
1826
1827                 yaml_sequence_start_event_initialize(&event, NULL,
1828                                                      (yaml_char_t *)YAML_SEQ_TAG,
1829                                                      1, YAML_ANY_SEQUENCE_STYLE);
1830                 rc = yaml_emitter_emit(&output, &event);
1831                 if (rc == 0)
1832                         goto emitter_error;
1833
1834                 yaml_mapping_start_event_initialize(&event, NULL,
1835                                                     (yaml_char_t *)YAML_MAP_TAG,
1836                                                     1, YAML_ANY_MAPPING_STYLE);
1837                 rc = yaml_emitter_emit(&output, &event);
1838                 if (rc == 0)
1839                         goto emitter_error;
1840
1841                 yaml_scalar_event_initialize(&event, NULL,
1842                                              (yaml_char_t *)YAML_STR_TAG,
1843                                              (yaml_char_t *)key,
1844                                              strlen(key),
1845                                              1, 0, YAML_PLAIN_SCALAR_STYLE);
1846                 rc = yaml_emitter_emit(&output, &event);
1847                 if (rc == 0)
1848                         goto emitter_error;
1849
1850                 yaml_scalar_event_initialize(&event, NULL,
1851                                              (yaml_char_t *)YAML_STR_TAG,
1852                                              (yaml_char_t *)value,
1853                                              strlen(value), 1, 0,
1854                                              YAML_PLAIN_SCALAR_STYLE);
1855                 rc = yaml_emitter_emit(&output, &event);
1856                 if (rc == 0)
1857                         goto emitter_error;
1858         } else {
1859                 yaml_scalar_event_initialize(&event, NULL,
1860                                              (yaml_char_t *)YAML_STR_TAG,
1861                                              (yaml_char_t *)"",
1862                                              strlen(""), 1, 0,
1863                                              YAML_PLAIN_SCALAR_STYLE);
1864                 rc = yaml_emitter_emit(&output, &event);
1865                 if (rc == 0)
1866                         goto emitter_error;
1867
1868                 goto no_net_id;
1869         }
1870
1871         if (!nw_descr || list_empty(&nw_descr->nw_intflist))
1872                 goto skip_intf;
1873
1874         yaml_scalar_event_initialize(&event, NULL,
1875                                      (yaml_char_t *)YAML_STR_TAG,
1876                                      (yaml_char_t *)"local NI(s)",
1877                                      strlen("local NI(s)"), 1, 0,
1878                                      YAML_PLAIN_SCALAR_STYLE);
1879         rc = yaml_emitter_emit(&output, &event);
1880         if (rc == 0)
1881                 goto emitter_error;
1882
1883         yaml_sequence_start_event_initialize(&event, NULL,
1884                                              (yaml_char_t *)YAML_SEQ_TAG,
1885                                              1, YAML_ANY_SEQUENCE_STYLE);
1886         rc = yaml_emitter_emit(&output, &event);
1887         if (rc == 0)
1888                 goto emitter_error;
1889
1890         list_for_each_entry(intf, &nw_descr->nw_intflist,
1891                             intf_on_network) {
1892                 yaml_mapping_start_event_initialize(&event, NULL,
1893                                                     (yaml_char_t *)YAML_MAP_TAG,
1894                                                     1, YAML_ANY_MAPPING_STYLE);
1895                 rc = yaml_emitter_emit(&output, &event);
1896                 if (rc == 0)
1897                         goto emitter_error;
1898
1899                 yaml_scalar_event_initialize(&event, NULL,
1900                                              (yaml_char_t *)YAML_STR_TAG,
1901                                              (yaml_char_t *)"interfaces",
1902                                              strlen("interfaces"), 1, 0,
1903                                              YAML_PLAIN_SCALAR_STYLE);
1904                 rc = yaml_emitter_emit(&output, &event);
1905                 if (rc == 0)
1906                         goto emitter_error;
1907
1908                 yaml_mapping_start_event_initialize(&event, NULL,
1909                                                     (yaml_char_t *)YAML_MAP_TAG,
1910                                                     1, YAML_ANY_MAPPING_STYLE);
1911                 rc = yaml_emitter_emit(&output, &event);
1912                 if (rc == 0)
1913                         goto emitter_error;
1914
1915                 yaml_scalar_event_initialize(&event, NULL,
1916                                              (yaml_char_t *)YAML_STR_TAG,
1917                                              (yaml_char_t *)"0",
1918                                              strlen("0"), 1, 0,
1919                                              YAML_PLAIN_SCALAR_STYLE);
1920                 rc = yaml_emitter_emit(&output, &event);
1921                 if (rc == 0)
1922                         goto emitter_error;
1923
1924                 yaml_scalar_event_initialize(&event, NULL,
1925                                              (yaml_char_t *)YAML_STR_TAG,
1926                                              (yaml_char_t *)intf->intf_name,
1927                                              strlen(intf->intf_name), 1, 0,
1928                                              YAML_PLAIN_SCALAR_STYLE);
1929                 rc = yaml_emitter_emit(&output, &event);
1930                 if (rc == 0)
1931                         goto emitter_error;
1932
1933                 yaml_mapping_end_event_initialize(&event);
1934                 rc = yaml_emitter_emit(&output, &event);
1935                 if (rc == 0)
1936                         goto emitter_error;
1937
1938                 if (tunables) {
1939                         rc = yaml_add_ni_tunables(&output, tunables, nw_descr);
1940                         if (rc == 0)
1941                                 goto emitter_error;
1942                 }
1943
1944                 if (global_cpts) {
1945                         __u32 *cpt_array;
1946                         int count, i;
1947
1948                         yaml_scalar_event_initialize(&event, NULL,
1949                                                      (yaml_char_t *)YAML_STR_TAG,
1950                                                      (yaml_char_t *)"CPT",
1951                                                      strlen("CPT"), 1, 0,
1952                                                      YAML_PLAIN_SCALAR_STYLE);
1953                         rc = yaml_emitter_emit(&output, &event);
1954                         if (rc == 0)
1955                                 goto emitter_error;
1956
1957                         yaml_sequence_start_event_initialize(&event, NULL,
1958                                                              (yaml_char_t *)YAML_SEQ_TAG,
1959                                                              1,
1960                                                              YAML_FLOW_SEQUENCE_STYLE);
1961                         rc = yaml_emitter_emit(&output, &event);
1962                         if (rc == 0)
1963                                 goto emitter_error;
1964
1965                         count = cfs_expr_list_values(global_cpts,
1966                                                      LNET_MAX_SHOW_NUM_CPT,
1967                                                      &cpt_array);
1968                         for (i = 0; i < count; i++) {
1969                                 char core[INT_STRING_LEN];
1970
1971                                 snprintf(core, sizeof(core), "%u", cpt_array[i]);
1972                                 yaml_scalar_event_initialize(&event, NULL,
1973                                                              (yaml_char_t *)YAML_STR_TAG,
1974                                                              (yaml_char_t *)core,
1975                                                              strlen(core), 1, 0,
1976                                                              YAML_PLAIN_SCALAR_STYLE);
1977                                 rc = yaml_emitter_emit(&output, &event);
1978                                 if (rc == 0)
1979                                         goto emitter_error;
1980                         }
1981
1982                         yaml_sequence_end_event_initialize(&event);
1983                         rc = yaml_emitter_emit(&output, &event);
1984                         if (rc == 0)
1985                                 goto emitter_error;
1986
1987                         cfs_expr_list_free(global_cpts);
1988                         free(cpt_array);
1989                 }
1990
1991                 yaml_mapping_end_event_initialize(&event);
1992                 rc = yaml_emitter_emit(&output, &event);
1993                 if (rc == 0)
1994                         goto emitter_error;
1995         }
1996
1997         yaml_sequence_end_event_initialize(&event);
1998         rc = yaml_emitter_emit(&output, &event);
1999         if (rc == 0)
2000                 goto emitter_error;
2001 skip_intf:
2002         yaml_mapping_end_event_initialize(&event);
2003         rc = yaml_emitter_emit(&output, &event);
2004         if (rc == 0)
2005                 goto emitter_error;
2006
2007         yaml_sequence_end_event_initialize(&event);
2008         rc = yaml_emitter_emit(&output, &event);
2009         if (rc == 0)
2010                 goto emitter_error;
2011 no_net_id:
2012         yaml_mapping_end_event_initialize(&event);
2013         rc = yaml_emitter_emit(&output, &event);
2014         if (rc == 0)
2015                 goto emitter_error;
2016
2017         yaml_document_end_event_initialize(&event, 0);
2018         rc = yaml_emitter_emit(&output, &event);
2019         if (rc == 0)
2020                 goto emitter_error;
2021
2022         rc = yaml_emitter_close(&output);
2023 emitter_error:
2024         if (rc == 0) {
2025                 yaml_emitter_log_error(&output, stderr);
2026                 rc = -EINVAL;
2027         } else {
2028                 yaml_document_t errmsg;
2029
2030                 rc = yaml_parser_load(&reply, &errmsg);
2031                 if (rc == 1 && (flags & NLM_F_DUMP)) {
2032                         yaml_emitter_t debug;
2033
2034                         rc = yaml_emitter_initialize(&debug);
2035                         if (rc == 1) {
2036                                 yaml_emitter_set_indent(&debug,
2037                                                         LNET_DEFAULT_INDENT);
2038                                 yaml_emitter_set_output_file(&debug, stdout);
2039                                 rc = yaml_emitter_dump(&debug, &errmsg);
2040                         }
2041                         yaml_emitter_delete(&debug);
2042                 } else {
2043                         msg = yaml_parser_get_reader_error(&reply);
2044                 }
2045                 yaml_document_delete(&errmsg);
2046         }
2047         yaml_emitter_delete(&output);
2048 free_reply:
2049         if (rc == 0) {
2050                 yaml_lnet_print_error(flags, "net", msg);
2051                 rc = -EINVAL;
2052         }
2053         yaml_parser_delete(&reply);
2054         nl_socket_free(sk);
2055
2056         return rc == 1 ? 0 : rc;
2057 }
2058
2059 static int jt_add_ni(int argc, char **argv)
2060 {
2061         char *ip2net = NULL;
2062         long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1, auth_key = -1;
2063         char *traffic_class = NULL;
2064         struct cYAML *err_rc = NULL;
2065         int rc, opt, cpt_rc = -1;
2066         struct lnet_dlc_network_descr nw_descr;
2067         struct cfs_expr_list *global_cpts = NULL;
2068         struct lnet_ioctl_config_lnd_tunables tunables;
2069         bool found = false;
2070         bool skip_mr_route_setup = false;
2071         const char *const short_options = "a:b:c:i:k:m:n:p:r:s:t:T:";
2072         static const struct option long_options[] = {
2073         { .name = "auth-key",     .has_arg = required_argument, .val = 'a' },
2074         { .name = "peer-buffer-credits",
2075                                   .has_arg = required_argument, .val = 'b' },
2076         { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
2077         { .name = "if",           .has_arg = required_argument, .val = 'i' },
2078         { .name = "skip-mr-route-setup",
2079                                   .has_arg = no_argument, .val = 'k' },
2080         { .name = "conns-per-peer",
2081                                   .has_arg = required_argument, .val = 'm' },
2082         { .name = "net",          .has_arg = required_argument, .val = 'n' },
2083         { .name = "ip2net",       .has_arg = required_argument, .val = 'p' },
2084         { .name = "credits",      .has_arg = required_argument, .val = 'r' },
2085         { .name = "cpt",          .has_arg = required_argument, .val = 's' },
2086         { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
2087         { .name = "traffic-class", .has_arg = required_argument, .val = 'T' },
2088         { .name = NULL } };
2089         char *net_id = NULL;
2090
2091         memset(&tunables, 0, sizeof(tunables));
2092         lustre_lnet_init_nw_descr(&nw_descr);
2093
2094         rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
2095         if (rc)
2096                 return rc;
2097
2098         while ((opt = getopt_long(argc, argv, short_options,
2099                                    long_options, NULL)) != -1) {
2100                 switch (opt) {
2101                 case 'a':
2102                         rc = parse_long(optarg, &auth_key);
2103                         if (rc != 0) {
2104                                 /* ignore option */
2105                                 auth_key = -1;
2106                                 continue;
2107                         }
2108                         break;
2109                 case 'b':
2110                         rc = parse_long(optarg, &pbc);
2111                         if (rc != 0) {
2112                                 /* ignore option */
2113                                 pbc = -1;
2114                                 continue;
2115                         }
2116                         break;
2117                 case 'c':
2118                         rc = parse_long(optarg, &pc);
2119                         if (rc != 0) {
2120                                 /* ignore option */
2121                                 pc = -1;
2122                                 continue;
2123                         }
2124                         break;
2125                 case 'i':
2126                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2127                         if (rc != 0) {
2128                                 cYAML_build_error(-1, -1, "ni", "add",
2129                                                 "bad interface list",
2130                                                 &err_rc);
2131                                 goto failed;
2132                         }
2133                         break;
2134                 case 'k':
2135                         skip_mr_route_setup = true;
2136                         break;
2137                 case 'm':
2138                         rc = parse_long(optarg, &cpp);
2139                         if (rc != 0) {
2140                                 /* ignore option */
2141                                 cpp = -1;
2142                                 continue;
2143                         }
2144                         break;
2145
2146                 case 'n':
2147                         nw_descr.nw_id = libcfs_str2net(optarg);
2148                         net_id = optarg;
2149                         break;
2150                 case 'p':
2151                         ip2net = optarg;
2152                         break;
2153                 case 'r':
2154                         rc = parse_long(optarg, &cre);
2155                         if (rc != 0) {
2156                                 /* ignore option */
2157                                 cre = -1;
2158                                 continue;
2159                         }
2160                         break;
2161                 case 's':
2162                         cpt_rc = cfs_expr_list_parse(optarg,
2163                                                      strlen(optarg), 0,
2164                                                      UINT_MAX, &global_cpts);
2165                         break;
2166                 case 't':
2167                         rc = parse_long(optarg, &pto);
2168                         if (rc != 0) {
2169                                 /* ignore option */
2170                                 pto = -1;
2171                                 continue;
2172                         }
2173                         break;
2174                 case 'T':
2175                         traffic_class = optarg;
2176                         if (strlen(traffic_class) == 0 ||
2177                             strlen(traffic_class) >= LNET_MAX_STR_LEN) {
2178                                 cYAML_build_error(-1, -1, "ni", "add",
2179                                                   "Invalid traffic-class argument",
2180                                                   &err_rc);
2181                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
2182                                 goto failed;
2183                         }
2184                         break;
2185                 case '?':
2186                         print_help(net_cmds, "net", "add");
2187                 default:
2188                         return 0;
2189                 }
2190         }
2191 #ifdef HAVE_KFILND
2192         if (auth_key > 0 && LNET_NETTYP(nw_descr.nw_id) == KFILND) {
2193                 tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_auth_key = auth_key;
2194                 found = true;
2195         }
2196
2197         if (traffic_class && LNET_NETTYP(nw_descr.nw_id) == KFILND &&
2198             strlen(traffic_class) < LNET_MAX_STR_LEN) {
2199                 strcpy(&tunables.lt_tun.lnd_tun_u.lnd_kfi.lnd_traffic_class_str[0],
2200                        traffic_class);
2201                 found = true;
2202         }
2203 #endif
2204
2205         if (LNET_NETTYP(nw_descr.nw_id) == SOCKLND && (cpp > -1)) {
2206                 tunables.lt_tun.lnd_tun_u.lnd_sock.lnd_conns_per_peer = cpp;
2207                 found = true;
2208         } else if (LNET_NETTYP(nw_descr.nw_id) == O2IBLND && (cpp > -1)) {
2209                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_conns_per_peer = cpp;
2210                 found = true;
2211         }
2212
2213         if (pto >= 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
2214                 tunables.lt_cmn.lct_peer_timeout = pto;
2215                 tunables.lt_cmn.lct_peer_tx_credits = pc;
2216                 tunables.lt_cmn.lct_peer_rtr_credits = pbc;
2217                 tunables.lt_cmn.lct_max_tx_credits = cre;
2218                 found = true;
2219         }
2220
2221         if (found && LNET_NETTYP(nw_descr.nw_id) == O2IBLND)
2222                 tunables.lt_tun.lnd_tun_u.lnd_o2ib.lnd_map_on_demand = UINT_MAX;
2223
2224         rc = yaml_lnet_config_ni(net_id, ip2net, &nw_descr,
2225                                  found ? &tunables : NULL,
2226                                  (cpt_rc == 0) ? global_cpts : NULL,
2227                                  LNET_GENL_VERSION, NLM_F_CREATE);
2228         if (rc <= 0) {
2229                 if (rc == -EOPNOTSUPP)
2230                         goto old_api;
2231                 if (global_cpts != NULL)
2232                         cfs_expr_list_free(global_cpts);
2233                 if (rc == 0 && !skip_mr_route_setup)
2234                         rc = lustre_lnet_setup_mrrouting(&err_rc);
2235                 return rc;
2236         }
2237 old_api:
2238         rc = lustre_lnet_config_ni(&nw_descr,
2239                                    (cpt_rc == 0) ? global_cpts: NULL,
2240                                    ip2net, (found) ? &tunables : NULL,
2241                                    cpp, &err_rc);
2242
2243         if (global_cpts != NULL)
2244                 cfs_expr_list_free(global_cpts);
2245
2246 failed:
2247         if (rc != LUSTRE_CFG_RC_NO_ERR)
2248                 cYAML_print_tree2file(stderr, err_rc);
2249
2250         cYAML_free_tree(err_rc);
2251
2252         if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
2253                 err_rc = NULL;
2254                 rc = lustre_lnet_setup_mrrouting(&err_rc);
2255
2256                 if (rc != LUSTRE_CFG_RC_NO_ERR)
2257                         cYAML_print_tree2file(stderr, err_rc);
2258
2259                 cYAML_free_tree(err_rc);
2260         }
2261
2262         return rc;
2263 }
2264
2265 static int jt_del_route(int argc, char **argv)
2266 {
2267         char *network = NULL, *gateway = NULL;
2268         struct cYAML *err_rc = NULL;
2269         int rc, opt;
2270
2271         const char *const short_options = "n:g:";
2272         static const struct option long_options[] = {
2273                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2274                 { .name = "gateway", .has_arg = required_argument, .val = 'g' },
2275                 { .name = NULL } };
2276
2277         rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
2278         if (rc)
2279                 return rc;
2280
2281         while ((opt = getopt_long(argc, argv, short_options,
2282                                    long_options, NULL)) != -1) {
2283                 switch (opt) {
2284                 case 'n':
2285                         network = optarg;
2286                         break;
2287                 case 'g':
2288                         gateway = optarg;
2289                         break;
2290                 case '?':
2291                         print_help(route_cmds, "route", "del");
2292                 default:
2293                         return 0;
2294                 }
2295         }
2296
2297         rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
2298
2299         if (rc != LUSTRE_CFG_RC_NO_ERR)
2300                 cYAML_print_tree2file(stderr, err_rc);
2301
2302         cYAML_free_tree(err_rc);
2303
2304         return rc;
2305 }
2306
2307 static int jt_del_ni(int argc, char **argv)
2308 {
2309         struct cYAML *err_rc = NULL;
2310         int rc, opt;
2311         struct lnet_dlc_network_descr nw_descr;
2312         const char *const short_options = "n:i:";
2313         static const struct option long_options[] = {
2314         { .name = "net",        .has_arg = required_argument,   .val = 'n' },
2315         { .name = "if",         .has_arg = required_argument,   .val = 'i' },
2316         { .name = NULL } };
2317         char *net_id = NULL;
2318
2319         rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
2320         if (rc)
2321                 return rc;
2322
2323         lustre_lnet_init_nw_descr(&nw_descr);
2324
2325         while ((opt = getopt_long(argc, argv, short_options,
2326                                    long_options, NULL)) != -1) {
2327                 switch (opt) {
2328                 case 'n':
2329                         nw_descr.nw_id = libcfs_str2net(optarg);
2330                         net_id = optarg;
2331                         break;
2332                 case 'i':
2333                         rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
2334                         if (rc != 0) {
2335                                 cYAML_build_error(-1, -1, "ni", "add",
2336                                                 "bad interface list",
2337                                                 &err_rc);
2338                                 goto out;
2339                         }
2340                         break;
2341                 case '?':
2342                         print_help(net_cmds, "net", "del");
2343                 default:
2344                         return 0;
2345                 }
2346         }
2347
2348         rc = yaml_lnet_config_ni(net_id, NULL, &nw_descr, NULL, NULL,
2349                                  LNET_GENL_VERSION, 0);
2350         if (rc <= 0) {
2351                 if (rc != -EOPNOTSUPP)
2352                         return rc;
2353         }
2354
2355         rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
2356 out:
2357         if (rc != LUSTRE_CFG_RC_NO_ERR)
2358                 cYAML_print_tree2file(stderr, err_rc);
2359
2360         cYAML_free_tree(err_rc);
2361
2362         return rc;
2363 }
2364
2365 static int jt_show_route(int argc, char **argv)
2366 {
2367         char *network = NULL, *gateway = NULL;
2368         long int hop = -1, prio = -1;
2369         int detail = 0, rc, opt;
2370         struct cYAML *err_rc = NULL, *show_rc = NULL;
2371         const char *const short_options = "c:n:g:p:v";
2372         static const struct option long_options[] = {
2373                 { .name = "net",       .has_arg = required_argument, .val = 'n' },
2374                 { .name = "gateway",   .has_arg = required_argument, .val = 'g' },
2375                 { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
2376                 { .name = "hop",       .has_arg = required_argument, .val = 'c' },
2377                 { .name = "priority",  .has_arg = required_argument, .val = 'p' },
2378                 { .name = "verbose",   .has_arg = no_argument,       .val = 'v' },
2379                 { .name = NULL }
2380         };
2381
2382         rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
2383         if (rc)
2384                 return rc;
2385
2386         while ((opt = getopt_long(argc, argv, short_options,
2387                                    long_options, NULL)) != -1) {
2388                 switch (opt) {
2389                 case 'n':
2390                         network = optarg;
2391                         break;
2392                 case 'g':
2393                         gateway = optarg;
2394                         break;
2395                 case 'c':
2396                         rc = parse_long(optarg, &hop);
2397                         if (rc != 0) {
2398                                 /* ignore option */
2399                                 hop = -1;
2400                                 continue;
2401                         }
2402                         break;
2403                 case 'p':
2404                         rc = parse_long(optarg, &prio);
2405                         if (rc != 0) {
2406                                 /* ignore option */
2407                                 prio = -1;
2408                                 continue;
2409                         }
2410                         break;
2411                 case 'v':
2412                         detail = 1;
2413                         break;
2414                 case '?':
2415                         print_help(route_cmds, "route", "show");
2416                 default:
2417                         return 0;
2418                 }
2419         }
2420
2421         rc = yaml_lnet_route(network, gateway, hop, prio, -1,
2422                              detail, NLM_F_DUMP);
2423         if (rc <= 0) {
2424                 if (rc == -EOPNOTSUPP)
2425                         goto old_api;
2426                 return rc;
2427         }
2428 old_api:
2429         rc = lustre_lnet_show_route(network, gateway, hop, prio,
2430                                     detail ? 1 : 0, -1,
2431                                     &show_rc, &err_rc, false);
2432
2433         if (rc != LUSTRE_CFG_RC_NO_ERR)
2434                 cYAML_print_tree2file(stderr, err_rc);
2435         else if (show_rc)
2436                 cYAML_print_tree(show_rc);
2437
2438         cYAML_free_tree(err_rc);
2439         cYAML_free_tree(show_rc);
2440
2441         return rc;
2442 }
2443
2444 static int set_value_helper(int argc, char **argv,
2445                             int (*cb)(int, bool, char*, int, struct cYAML**))
2446 {
2447         char *nid = NULL;
2448         long int healthv = -1;
2449         bool all = false;
2450         long int state = -1;
2451         int rc, opt;
2452         struct cYAML *err_rc = NULL;
2453
2454         const char *const short_options = "t:n:s:a";
2455         static const struct option long_options[] = {
2456                 { .name = "nid", .has_arg = required_argument, .val = 'n' },
2457                 { .name = "health", .has_arg = required_argument, .val = 't' },
2458                 { .name = "state", .has_arg = required_argument, .val = 's' },
2459                 { .name = "all", .has_arg = no_argument, .val = 'a' },
2460                 { .name = NULL } };
2461
2462         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2463         if (rc)
2464                 return rc;
2465
2466         while ((opt = getopt_long(argc, argv, short_options,
2467                                    long_options, NULL)) != -1) {
2468                 switch (opt) {
2469                 case 'n':
2470                         nid = optarg;
2471                         break;
2472                 case 't':
2473                         if (parse_long(optarg, &healthv) != 0)
2474                                 healthv = -1;
2475                         break;
2476                 case 's':
2477                         if (parse_long(optarg, &state) != 0)
2478                                 state = -1;
2479                         break;
2480                 case 'a':
2481                         all = true;
2482                         break;
2483                 default:
2484                         return 0;
2485                 }
2486         }
2487
2488         if (state > -1)
2489                 rc = lustre_lnet_set_peer_state(state, nid, -1, &err_rc);
2490         else
2491                 rc = cb(healthv, all, nid, -1, &err_rc);
2492
2493         if (rc != LUSTRE_CFG_RC_NO_ERR)
2494                 cYAML_print_tree2file(stderr, err_rc);
2495
2496         cYAML_free_tree(err_rc);
2497
2498         return rc;
2499 }
2500
2501 static int jt_set_ni_value(int argc, char **argv)
2502 {
2503         char *nid = NULL;
2504         long int healthv = -1, cpp = -1;
2505         bool all = false;
2506         int rc, opt;
2507         struct cYAML *err_rc = NULL;
2508
2509         const char *const short_options = "a:m:n:t:";
2510         static const struct option long_options[] = {
2511         { .name = "all",            .has_arg = no_argument,       .val = 'a' },
2512         { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
2513         { .name = "nid",            .has_arg = required_argument, .val = 'n' },
2514         { .name = "health",         .has_arg = required_argument, .val = 't' },
2515         { .name = NULL } };
2516
2517         rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
2518         if (rc)
2519                 return rc;
2520
2521         while ((opt = getopt_long(argc, argv, short_options,
2522                                    long_options, NULL)) != -1) {
2523                 switch (opt) {
2524                 case 'a':
2525                         all = true;
2526                         break;
2527                 case 'm':
2528                         rc = parse_long(optarg, &cpp);
2529                         if (rc != 0) {
2530                                 /* ignore option */
2531                                 cpp = -1;
2532                                 continue;
2533                         }
2534                         break;
2535                 case 'n':
2536                         nid = optarg;
2537                         break;
2538                 case 't':
2539                         if (parse_long(optarg, &healthv) != 0) {
2540                                 /* ignore option */
2541                                 healthv = -1;
2542                                 continue;
2543                         }
2544                         break;
2545                 default:
2546                         return 0;
2547                 }
2548         }
2549
2550         if (cpp > -1)
2551                 rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
2552                                                           -1, &err_rc);
2553         if (healthv > -1)
2554                 rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
2555                                                    -1, &err_rc);
2556
2557         if (rc != LUSTRE_CFG_RC_NO_ERR)
2558                 cYAML_print_tree2file(stderr, err_rc);
2559
2560         cYAML_free_tree(err_rc);
2561
2562         return rc;
2563 }
2564
2565 static int yaml_lnet_peer_display(yaml_parser_t *reply, bool list_only)
2566 {
2567         yaml_emitter_t debug;
2568         int rc;
2569
2570         rc = yaml_emitter_initialize(&debug);
2571         if (rc == 0)
2572                 goto out_err;
2573
2574         yaml_emitter_set_indent(&debug, 6);
2575         yaml_emitter_set_output_file(&debug, stdout);
2576
2577         if (list_only) {
2578                 bool done = false;
2579
2580                 while (!done) {
2581                         yaml_event_t event;
2582                         char *value;
2583
2584                         rc = yaml_parser_parse(reply, &event);
2585                         if (rc == 0)
2586                                 goto report_reply_error;
2587
2588                         if (event.type != YAML_SCALAR_EVENT)
2589                                 goto merge_event;
2590
2591                         value = (char *)event.data.scalar.value;
2592                         if (strcmp(value, "peer") == 0) {
2593                                 yaml_event_delete(&event);
2594
2595                                 yaml_scalar_event_initialize(&event, NULL,
2596                                                              (yaml_char_t *)YAML_STR_TAG,
2597                                                              (yaml_char_t *)"peer list",
2598                                                              strlen("peer list"),
2599                                                              1, 0,
2600                                                              YAML_PLAIN_SCALAR_STYLE);
2601                         } else if (strcmp(value, "primary nid") == 0) {
2602                                 yaml_event_delete(&event);
2603
2604                                 yaml_scalar_event_initialize(&event, NULL,
2605                                                              (yaml_char_t *)YAML_STR_TAG,
2606                                                              (yaml_char_t *)"nid",
2607                                                              strlen("nid"),
2608                                                              1, 0,
2609                                                              YAML_PLAIN_SCALAR_STYLE);
2610                                 rc = yaml_emitter_emit(&debug, &event);
2611                                 if (rc == 0)
2612                                         break;
2613
2614                                 /* Now print NID address */
2615                                 rc = yaml_parser_parse(reply, &event);
2616                                 if (rc == 0)
2617                                         goto report_reply_error;
2618
2619                                 rc = yaml_emitter_emit(&debug, &event);
2620                                 if (rc == 0)
2621                                         break;
2622
2623                                 /* skip reset */
2624                                 while (event.type != YAML_MAPPING_END_EVENT) {
2625                                         rc = yaml_parser_parse(reply, &event);
2626                                         if (rc == 0)
2627                                                 goto report_reply_error;
2628                                 }
2629
2630                                 /* we can have map end, seq end, map end or
2631                                  * just map end event. If we see seq end event
2632                                  * then skip to next mapping end event
2633                                  */
2634                                 rc = yaml_parser_parse(reply, &event);
2635                                 if (rc == 0)
2636                                         goto report_reply_error;
2637
2638                                 if (event.type == YAML_SEQUENCE_END_EVENT) {
2639                                         yaml_event_delete(&event);
2640
2641                                         rc = yaml_parser_parse(reply, &event);
2642                                         if (rc == 0)
2643                                                 goto report_reply_error;
2644                                 }
2645                         }
2646 merge_event:
2647                         rc = yaml_emitter_emit(&debug, &event);
2648                         if (rc == 0)
2649                                 break;
2650
2651                         done = (event.type == YAML_DOCUMENT_END_EVENT);
2652                 }
2653         } else {
2654                 yaml_document_t errmsg;
2655
2656                 rc = yaml_parser_load(reply, &errmsg);
2657                 if (rc == 1)
2658                         rc = yaml_emitter_dump(&debug, &errmsg);
2659                 yaml_document_delete(&errmsg);
2660         }
2661 out_err:
2662         if (rc == 0)
2663                 yaml_emitter_log_error(&debug, stderr);
2664 report_reply_error:
2665         yaml_emitter_delete(&debug);
2666
2667         return rc;
2668 }
2669
2670 static int yaml_lnet_peer(char *prim_nid, char *nidstr, bool disable_mr,
2671                           int health_value, int state, bool list_only,
2672                           int version, int flags)
2673 {
2674         struct nl_sock *sk = NULL;
2675         const char *msg = NULL;
2676         yaml_emitter_t output;
2677         yaml_parser_t reply;
2678         yaml_event_t event;
2679         int rc;
2680
2681         /* Create Netlink emitter to send request to kernel */
2682         sk = nl_socket_alloc();
2683         if (!sk)
2684                 return -EOPNOTSUPP;
2685
2686         /* Setup parser to receive Netlink packets */
2687         rc = yaml_parser_initialize(&reply);
2688         if (rc == 0) {
2689                 nl_socket_free(sk);
2690                 return -EOPNOTSUPP;
2691         }
2692
2693         rc = yaml_parser_set_input_netlink(&reply, sk, false);
2694         if (rc == 0) {
2695                 msg = yaml_parser_get_reader_error(&reply);
2696                 goto free_reply;
2697         }
2698
2699         /* Create Netlink emitter to send request to kernel */
2700         rc = yaml_emitter_initialize(&output);
2701         if (rc == 0) {
2702                 msg = "failed to initialize emitter";
2703                 goto free_reply;
2704         }
2705
2706         rc = yaml_emitter_set_output_netlink(&output, sk, LNET_GENL_NAME,
2707                                              version, LNET_CMD_PEERS, flags);
2708         if (rc == 0)
2709                 goto emitter_error;
2710
2711         yaml_emitter_open(&output);
2712         yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
2713         rc = yaml_emitter_emit(&output, &event);
2714         if (rc == 0)
2715                 goto emitter_error;
2716
2717         yaml_mapping_start_event_initialize(&event, NULL,
2718                                             (yaml_char_t *)YAML_MAP_TAG,
2719                                             1, YAML_ANY_MAPPING_STYLE);
2720         rc = yaml_emitter_emit(&output, &event);
2721         if (rc == 0)
2722                 goto emitter_error;
2723
2724         yaml_scalar_event_initialize(&event, NULL,
2725                                      (yaml_char_t *)YAML_STR_TAG,
2726                                      (yaml_char_t *)"peer",
2727                                      strlen("peer"), 1, 0,
2728                                      YAML_PLAIN_SCALAR_STYLE);
2729         rc = yaml_emitter_emit(&output, &event);
2730         if (rc == 0)
2731                 goto emitter_error;
2732
2733         if (prim_nid) {
2734                 yaml_sequence_start_event_initialize(&event, NULL,
2735                                                      (yaml_char_t *)YAML_SEQ_TAG,
2736                                                      1,
2737                                                      YAML_BLOCK_SEQUENCE_STYLE);
2738                 rc = yaml_emitter_emit(&output, &event);
2739                 if (rc == 0)
2740                         goto emitter_error;
2741
2742                 yaml_mapping_start_event_initialize(&event, NULL,
2743                                                     (yaml_char_t *)YAML_MAP_TAG,
2744                                                     1,
2745                                                     YAML_BLOCK_MAPPING_STYLE);
2746                 rc = yaml_emitter_emit(&output, &event);
2747                 if (rc == 0)
2748                         goto emitter_error;
2749
2750                 yaml_scalar_event_initialize(&event, NULL,
2751                                              (yaml_char_t *)YAML_STR_TAG,
2752                                              (yaml_char_t *)"primary nid",
2753                                              strlen("primary nid"), 1, 0,
2754                                              YAML_PLAIN_SCALAR_STYLE);
2755                 rc = yaml_emitter_emit(&output, &event);
2756                 if (rc == 0)
2757                         goto emitter_error;
2758
2759                 yaml_scalar_event_initialize(&event, NULL,
2760                                              (yaml_char_t *)YAML_STR_TAG,
2761                                              (yaml_char_t *)prim_nid,
2762                                              strlen(prim_nid), 1, 0,
2763                                              YAML_PLAIN_SCALAR_STYLE);
2764                 rc = yaml_emitter_emit(&output, &event);
2765                 if (rc == 0)
2766                         goto emitter_error;
2767
2768                 yaml_mapping_end_event_initialize(&event);
2769                 rc = yaml_emitter_emit(&output, &event);
2770                 if (rc == 0)
2771                         goto emitter_error;
2772
2773                 yaml_sequence_end_event_initialize(&event);
2774                 rc = yaml_emitter_emit(&output, &event);
2775                 if (rc == 0)
2776                         goto emitter_error;
2777         } else {
2778                 yaml_scalar_event_initialize(&event, NULL,
2779                                              (yaml_char_t *)YAML_STR_TAG,
2780                                              (yaml_char_t *)"",
2781                                              strlen(""), 1, 0,
2782                                              YAML_PLAIN_SCALAR_STYLE);
2783                 rc = yaml_emitter_emit(&output, &event);
2784                 if (rc == 0)
2785                         goto emitter_error;
2786         }
2787
2788         yaml_mapping_end_event_initialize(&event);
2789         rc = yaml_emitter_emit(&output, &event);
2790         if (rc == 0)
2791                 goto emitter_error;
2792
2793         yaml_document_end_event_initialize(&event, 0);
2794         rc = yaml_emitter_emit(&output, &event);
2795         if (rc == 0)
2796                 goto emitter_error;
2797
2798         rc = yaml_emitter_close(&output);
2799 emitter_error:
2800         if (rc == 0) {
2801                 yaml_emitter_log_error(&output, stderr);
2802                 rc = -EINVAL;
2803         } else {
2804                 rc = yaml_lnet_peer_display(&reply, list_only);
2805                 if (rc == 0) {
2806                         msg = yaml_parser_get_reader_error(&reply);
2807                         /* If we didn't find any peers just be silent */
2808                         if (msg && strcmp(msg, "No peers found") == 0)
2809                                 rc = 1;
2810                 }
2811
2812         }
2813         yaml_emitter_delete(&output);
2814 free_reply:
2815         if (rc == 0) {
2816                 yaml_lnet_print_error(flags, "peer", msg);
2817                 rc = -EINVAL;
2818         }
2819         yaml_parser_delete(&reply);
2820         nl_socket_free(sk);
2821
2822         return rc == 1 ? 0 : rc;
2823 }
2824
2825 static int jt_set_peer_ni_value(int argc, char **argv)
2826 {
2827         return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
2828 }
2829
2830 static int jt_show_recovery(int argc, char **argv)
2831 {
2832         int rc, opt;
2833         struct cYAML *err_rc = NULL, *show_rc = NULL;
2834         const char *const short_options = "lp";
2835         static const struct option long_options[] = {
2836                 { .name = "local", .has_arg = no_argument, .val = 'l' },
2837                 { .name = "peer", .has_arg = no_argument, .val = 'p' },
2838                 { .name = NULL } };
2839
2840         rc = check_cmd(debug_cmds, "debug", "recovery", 0, argc, argv);
2841         if (rc)
2842                 return rc;
2843
2844         while ((opt = getopt_long(argc, argv, short_options,
2845                                    long_options, NULL)) != -1) {
2846                 switch (opt) {
2847                 case 'l':
2848                         rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
2849                         break;
2850                 case 'p':
2851                         rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
2852                         break;
2853                 default:
2854                         return 0;
2855                 }
2856         }
2857
2858         if (rc != LUSTRE_CFG_RC_NO_ERR)
2859                 cYAML_print_tree2file(stderr, err_rc);
2860         else if (show_rc)
2861                 cYAML_print_tree(show_rc);
2862
2863         cYAML_free_tree(err_rc);
2864         cYAML_free_tree(show_rc);
2865
2866         return rc;
2867 }
2868
2869 static int jt_show_peer_debug_info(int argc, char **argv)
2870 {
2871         int rc, opt;
2872         struct cYAML *err_rc = NULL;
2873         char *peer_nid = optarg;
2874         const char *const short_opts = "k";
2875         const struct option long_opts[] = {
2876         { .name = "nid", .has_arg = required_argument, .val = 'k' },
2877         { .name = NULL } };
2878
2879         rc = check_cmd(debug_cmds, "debug", "peer", 0, argc, argv);
2880
2881         if (rc)
2882                 return rc;
2883
2884         while ((opt = getopt_long(argc, argv, short_opts,
2885                                    long_opts, NULL)) != -1) {
2886                 switch (opt) {
2887                 case 'k':
2888                         peer_nid = optarg;
2889                         break;
2890                 default:
2891                         return 0;
2892                 }
2893         }
2894
2895         rc = lustre_lnet_show_peer_debug_info(peer_nid, -1, &err_rc);
2896
2897         if (rc != LUSTRE_CFG_RC_NO_ERR)
2898                 cYAML_print_tree2file(stderr, err_rc);
2899
2900         cYAML_free_tree(err_rc);
2901
2902         return rc;
2903 }
2904
2905 static int jt_show_net(int argc, char **argv)
2906 {
2907         char *network = NULL;
2908         int rc, opt;
2909         struct cYAML *err_rc = NULL, *show_rc = NULL;
2910         long int detail = 0;
2911         const char *const short_options = "n:v";
2912         static const struct option long_options[] = {
2913                 { .name = "net",     .has_arg = required_argument, .val = 'n' },
2914                 { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
2915                 { .name = NULL } };
2916
2917         rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
2918         if (rc)
2919                 return rc;
2920
2921         while ((opt = getopt_long(argc, argv, short_options,
2922                                    long_options, NULL)) != -1) {
2923                 switch (opt) {
2924                 case 'n':
2925                         network = optarg;
2926                         break;
2927                 case 'v':
2928                         if ((!optarg) && (argv[optind] != NULL) &&
2929                             (argv[optind][0] != '-')) {
2930                                 if (parse_long(argv[optind++], &detail) != 0)
2931                                         detail = 1;
2932                         } else {
2933                                 detail = 1;
2934                         }
2935                         break;
2936                 case '?':
2937                         print_help(net_cmds, "net", "show");
2938                 default:
2939                         return 0;
2940                 }
2941         }
2942
2943         rc = yaml_lnet_config_ni(network, NULL, NULL, NULL, NULL,
2944                                  detail, NLM_F_DUMP);
2945         if (rc <= 0) {
2946                 if (rc != -EOPNOTSUPP)
2947                         return rc;
2948         }
2949
2950         rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
2951                                   false);
2952
2953         if (rc != LUSTRE_CFG_RC_NO_ERR)
2954                 cYAML_print_tree2file(stderr, err_rc);
2955         else if (show_rc)
2956                 cYAML_print_tree(show_rc);
2957
2958         cYAML_free_tree(err_rc);
2959         cYAML_free_tree(show_rc);
2960
2961         return rc;
2962 }
2963
2964 static int jt_show_routing(int argc, char **argv)
2965 {
2966         struct cYAML *err_rc = NULL, *show_rc = NULL;
2967         int rc;
2968
2969         rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
2970         if (rc)
2971                 return rc;
2972
2973         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
2974
2975         if (rc != LUSTRE_CFG_RC_NO_ERR)
2976                 cYAML_print_tree2file(stderr, err_rc);
2977         else if (show_rc)
2978                 cYAML_print_tree(show_rc);
2979
2980         cYAML_free_tree(err_rc);
2981         cYAML_free_tree(show_rc);
2982
2983         return rc;
2984 }
2985
2986 static int jt_show_stats(int argc, char **argv)
2987 {
2988         int rc;
2989         struct cYAML *show_rc = NULL, *err_rc = NULL;
2990
2991         rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
2992         if (rc)
2993                 return rc;
2994
2995         rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
2996
2997         if (rc != LUSTRE_CFG_RC_NO_ERR)
2998                 cYAML_print_tree2file(stderr, err_rc);
2999         else if (show_rc)
3000                 cYAML_print_tree(show_rc);
3001
3002         cYAML_free_tree(err_rc);
3003         cYAML_free_tree(show_rc);
3004
3005         return rc;
3006 }
3007
3008 static int jt_show_udsp(int argc, char **argv)
3009 {
3010         long int idx = -1;
3011         int rc, opt;
3012         struct cYAML *err_rc = NULL, *show_rc = NULL;
3013
3014         const char *const short_options = "i:";
3015         static const struct option long_options[] = {
3016                 { .name = "idx", .has_arg = required_argument, .val = 'i' },
3017                 { .name = NULL }
3018         };
3019
3020         rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
3021         if (rc)
3022                 return rc;
3023
3024         while ((opt = getopt_long(argc, argv, short_options,
3025                                    long_options, NULL)) != -1) {
3026                 switch (opt) {
3027                 case 'i':
3028                         rc = parse_long(optarg, &idx);
3029                         if (rc != 0 || idx < -1) {
3030                                 printf("Invalid index \"%s\"\n", optarg);
3031                                 return -EINVAL;
3032                         }
3033                         break;
3034                 case '?':
3035                         print_help(net_cmds, "net", "show");
3036                 default:
3037                         return 0;
3038                 }
3039         }
3040
3041         rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
3042
3043         if (rc != LUSTRE_CFG_RC_NO_ERR)
3044                 cYAML_print_tree2file(stderr, err_rc);
3045         else if (show_rc)
3046                 cYAML_print_tree(show_rc);
3047
3048         cYAML_free_tree(err_rc);
3049         cYAML_free_tree(show_rc);
3050
3051         return rc;
3052 }
3053
3054 static int jt_show_global(int argc, char **argv)
3055 {
3056         int rc;
3057         struct cYAML *show_rc = NULL, *err_rc = NULL;
3058
3059         rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
3060         if (rc)
3061                 return rc;
3062
3063         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3064         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3065                 cYAML_print_tree2file(stderr, err_rc);
3066                 goto out;
3067         }
3068
3069         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3070         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3071                 cYAML_print_tree2file(stderr, err_rc);
3072                 goto out;
3073         }
3074
3075         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3076         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3077                 cYAML_print_tree2file(stderr, err_rc);
3078                 goto out;
3079         }
3080
3081         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3082         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3083                 cYAML_print_tree2file(stderr, err_rc);
3084                 goto out;
3085         }
3086
3087         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3088         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3089                 cYAML_print_tree2file(stderr, err_rc);
3090                 goto out;
3091         }
3092
3093         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3094         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3095                 cYAML_print_tree2file(stderr, err_rc);
3096                 goto out;
3097         }
3098
3099         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3100         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3101                 cYAML_print_tree2file(stderr, err_rc);
3102                 goto out;
3103         }
3104
3105         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3106         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3107                 cYAML_print_tree2file(stderr, err_rc);
3108                 goto out;
3109         }
3110
3111         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3112         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3113                 cYAML_print_tree2file(stderr, err_rc);
3114                 goto out;
3115         }
3116
3117         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3118         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3119                 cYAML_print_tree2file(stderr, err_rc);
3120                 goto out;
3121         }
3122
3123         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3124         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3125                 cYAML_print_tree2file(stderr, err_rc);
3126                 goto out;
3127         }
3128
3129         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3130         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3131                 cYAML_print_tree2file(stderr, err_rc);
3132                 goto out;
3133         }
3134
3135         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3136         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3137                 cYAML_print_tree2file(stderr, err_rc);
3138                 goto out;
3139         }
3140
3141         if (show_rc)
3142                 cYAML_print_tree(show_rc);
3143
3144 out:
3145         cYAML_free_tree(err_rc);
3146         cYAML_free_tree(show_rc);
3147
3148         return rc;
3149 }
3150
3151 static int jt_lnet(int argc, char **argv)
3152 {
3153         int rc;
3154
3155         rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
3156         if (rc)
3157                 return rc;
3158
3159         return cfs_parser(argc, argv, lnet_cmds);
3160 }
3161
3162 static int jt_route(int argc, char **argv)
3163 {
3164         int rc;
3165
3166         rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
3167         if (rc)
3168                 return rc;
3169
3170         return cfs_parser(argc, argv, route_cmds);
3171 }
3172
3173 static int jt_net(int argc, char **argv)
3174 {
3175         int rc;
3176
3177         rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
3178         if (rc)
3179                 return rc;
3180
3181         return cfs_parser(argc, argv, net_cmds);
3182 }
3183
3184 static int jt_routing(int argc, char **argv)
3185 {
3186         int rc;
3187
3188         rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
3189         if (rc)
3190                 return rc;
3191
3192         return cfs_parser(argc, argv, routing_cmds);
3193 }
3194
3195 static int jt_stats(int argc, char **argv)
3196 {
3197         int rc;
3198
3199         rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
3200         if (rc)
3201                 return rc;
3202
3203         return cfs_parser(argc, argv, stats_cmds);
3204 }
3205
3206 static int jt_debug(int argc, char **argv)
3207 {
3208         int rc;
3209
3210         rc = check_cmd(debug_cmds, "debug", NULL, 2, argc, argv);
3211         if (rc)
3212                 return rc;
3213
3214         return cfs_parser(argc, argv, debug_cmds);
3215 }
3216
3217 static int jt_global(int argc, char **argv)
3218 {
3219         int rc;
3220
3221         rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
3222         if (rc)
3223                 return rc;
3224
3225         return cfs_parser(argc, argv, global_cmds);
3226 }
3227
3228 static int jt_peers(int argc, char **argv)
3229 {
3230         int rc;
3231
3232         rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
3233         if (rc)
3234                 return rc;
3235
3236         return cfs_parser(argc, argv, peer_cmds);
3237 }
3238
3239 static int jt_set(int argc, char **argv)
3240 {
3241         int rc;
3242
3243         rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
3244         if (rc)
3245                 return rc;
3246
3247         return cfs_parser(argc, argv, set_cmds);
3248 }
3249
3250 static int jt_udsp(int argc, char **argv)
3251 {
3252         int rc;
3253
3254         rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
3255         if (rc)
3256                 return rc;
3257
3258         return cfs_parser(argc, argv, udsp_cmds);
3259 }
3260
3261 static int jt_import(int argc, char **argv)
3262 {
3263         char *file = NULL;
3264         struct cYAML *err_rc = NULL;
3265         struct cYAML *show_rc = NULL;
3266         int rc = 0, return_rc = 0, opt, opt_found = 0;
3267         char cmd = 'a';
3268
3269         const char *const short_options = "adseh";
3270         static const struct option long_options[] = {
3271                 { .name = "add",  .has_arg = no_argument, .val = 'a' },
3272                 { .name = "del",  .has_arg = no_argument, .val = 'd' },
3273                 { .name = "show", .has_arg = no_argument, .val = 's' },
3274                 { .name = "exec", .has_arg = no_argument, .val = 'e' },
3275                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3276                 { .name = NULL } };
3277
3278         while ((opt = getopt_long(argc, argv, short_options,
3279                                    long_options, NULL)) != -1) {
3280                 opt_found = 1;
3281                 switch (opt) {
3282                 case 'a':
3283                         cmd = opt;
3284                         break;
3285                 case 'd':
3286                 case 's':
3287                         cmd = opt;
3288                         break;
3289                 case 'e':
3290                         cmd = opt;
3291                         break;
3292                 case 'h':
3293                         printf("import FILE\n"
3294                                "import < FILE : import a file\n"
3295                                "\t--add: add configuration\n"
3296                                "\t--del: delete configuration\n"
3297                                "\t--show: show configuration\n"
3298                                "\t--exec: execute command\n"
3299                                "\t--help: display this help\n"
3300                                "If no command option is given then --add"
3301                                " is assumed by default\n");
3302                         return 0;
3303                 default:
3304                         return 0;
3305                 }
3306         }
3307
3308         /* grab the file name if one exists */
3309         if (opt_found && argc == 3)
3310                 file = argv[2];
3311         else if (!opt_found && argc == 2)
3312                 file = argv[1];
3313
3314         switch (cmd) {
3315         case 'a':
3316                 rc = lustre_yaml_config(file, &err_rc);
3317                 return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3318                 cYAML_print_tree(show_rc);
3319                 cYAML_free_tree(show_rc);
3320                 break;
3321         case 'd':
3322                 rc = lustre_yaml_del(file, &err_rc);
3323                 break;
3324         case 's':
3325                 rc = lustre_yaml_show(file, &show_rc, &err_rc);
3326                 cYAML_print_tree(show_rc);
3327                 cYAML_free_tree(show_rc);
3328                 break;
3329         case 'e':
3330                 rc = lustre_yaml_exec(file, &show_rc, &err_rc);
3331                 cYAML_print_tree(show_rc);
3332                 cYAML_free_tree(show_rc);
3333                 break;
3334         }
3335
3336         if (rc || return_rc) {
3337                 cYAML_print_tree2file(stderr, err_rc);
3338                 cYAML_free_tree(err_rc);
3339         }
3340
3341         return rc;
3342 }
3343
3344 static int jt_export(int argc, char **argv)
3345 {
3346         struct cYAML *show_rc = NULL;
3347         struct cYAML *err_rc = NULL;
3348         int rc;
3349         FILE *f = NULL;
3350         int opt;
3351         bool backup = false;
3352         char *file = NULL;
3353
3354         const char *const short_options = "bh";
3355         static const struct option long_options[] = {
3356                 { .name = "backup", .has_arg = no_argument, .val = 'b' },
3357                 { .name = "help", .has_arg = no_argument, .val = 'h' },
3358                 { .name = NULL } };
3359
3360         while ((opt = getopt_long(argc, argv, short_options,
3361                                    long_options, NULL)) != -1) {
3362                 switch (opt) {
3363                 case 'b':
3364                         backup = true;
3365                         break;
3366                 case 'h':
3367                 default:
3368                         printf("export > FILE.yaml : export configuration\n"
3369                                "\t--backup: export only what's necessary for reconfig\n"
3370                                "\t--help: display this help\n");
3371                         return 0;
3372                 }
3373         }
3374
3375         if (backup && argc >= 3)
3376                 file = argv[2];
3377         else if (!backup && argc >= 2)
3378                 file = argv[1];
3379         else
3380                 f = stdout;
3381
3382         if (file) {
3383                 f = fopen(file, "w");
3384                 if (f == NULL)
3385                         return -1;
3386         }
3387
3388         rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
3389         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3390                 cYAML_print_tree2file(stderr, err_rc);
3391                 cYAML_free_tree(err_rc);
3392                 err_rc = NULL;
3393         }
3394
3395         rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
3396                                     &err_rc, backup);
3397         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3398                 cYAML_print_tree2file(stderr, err_rc);
3399                 cYAML_free_tree(err_rc);
3400                 err_rc = NULL;
3401         }
3402
3403         rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
3404         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3405                 cYAML_print_tree2file(stderr, err_rc);
3406                 cYAML_free_tree(err_rc);
3407                 err_rc = NULL;
3408         }
3409
3410         rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
3411         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3412                 cYAML_print_tree2file(stderr, err_rc);
3413                 cYAML_free_tree(err_rc);
3414                 err_rc = NULL;
3415         }
3416
3417         rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
3418         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3419                 cYAML_print_tree2file(stderr, err_rc);
3420                 cYAML_free_tree(err_rc);
3421                 err_rc = NULL;
3422         }
3423
3424         rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
3425         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3426                 cYAML_print_tree2file(stderr, err_rc);
3427                 cYAML_free_tree(err_rc);
3428                 err_rc = NULL;
3429         }
3430
3431         rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
3432         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3433                 cYAML_print_tree2file(stderr, err_rc);
3434                 cYAML_free_tree(err_rc);
3435                 err_rc = NULL;
3436         }
3437
3438         rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
3439         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3440                 cYAML_print_tree2file(stderr, err_rc);
3441                 cYAML_free_tree(err_rc);
3442                 err_rc = NULL;
3443         }
3444
3445         rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
3446         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3447                 cYAML_print_tree2file(stderr, err_rc);
3448                 err_rc = NULL;
3449         }
3450
3451         rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
3452         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3453                 cYAML_print_tree2file(stderr, err_rc);
3454                 err_rc = NULL;
3455         }
3456
3457         rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
3458         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3459                 cYAML_print_tree2file(stderr, err_rc);
3460                 err_rc = NULL;
3461         }
3462
3463         rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
3464         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3465                 cYAML_print_tree2file(stderr, err_rc);
3466                 err_rc = NULL;
3467         }
3468
3469         rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
3470         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3471                 cYAML_print_tree2file(stderr, err_rc);
3472                 err_rc = NULL;
3473         }
3474
3475         rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
3476         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3477                 cYAML_print_tree2file(stderr, err_rc);
3478                 err_rc = NULL;
3479         }
3480
3481         rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
3482         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3483                 cYAML_print_tree2file(stderr, err_rc);
3484                 cYAML_free_tree(err_rc);
3485                 err_rc = NULL;
3486         }
3487
3488         rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
3489         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3490                 cYAML_print_tree2file(stderr, err_rc);
3491                 cYAML_free_tree(err_rc);
3492                 err_rc = NULL;
3493         }
3494
3495         rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc, &err_rc);
3496         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3497                 cYAML_print_tree2file(stderr, err_rc);
3498                 cYAML_free_tree(err_rc);
3499                 err_rc = NULL;
3500         }
3501
3502         rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
3503         if (rc != LUSTRE_CFG_RC_NO_ERR) {
3504                 cYAML_print_tree2file(stderr, err_rc);
3505                 cYAML_free_tree(err_rc);
3506                 err_rc = NULL;
3507         }
3508
3509         if (show_rc != NULL) {
3510                 cYAML_print_tree2file(f, show_rc);
3511                 cYAML_free_tree(show_rc);
3512         }
3513
3514         if (argc >= 2)
3515                 fclose(f);
3516
3517         return 0;
3518 }
3519
3520 static int jt_peer_nid_common(int argc, char **argv, int cmd)
3521 {
3522         int rc = LUSTRE_CFG_RC_NO_ERR, opt;
3523         bool is_mr = true;
3524         char *prim_nid = NULL, *nidstr = NULL;
3525         char err_str[LNET_MAX_STR_LEN] = "Error";
3526         struct cYAML *err_rc = NULL;
3527         int force_lock = 0;
3528
3529         const char *const short_opts = "k:m:n:f:l";
3530         const struct option long_opts[] = {
3531         { .name = "prim_nid",   .has_arg = required_argument,   .val = 'k' },
3532         { .name = "non_mr",     .has_arg = no_argument,         .val = 'm' },
3533         { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3534         { .name = "force",      .has_arg = no_argument,         .val = 'f' },
3535         { .name = "lock_prim",  .has_arg = no_argument,         .val = 'l' },
3536         { .name = NULL } };
3537
3538         rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
3539         if (rc)
3540                 return rc;
3541
3542         while ((opt = getopt_long(argc, argv, short_opts,
3543                                   long_opts, NULL)) != -1) {
3544                 switch (opt) {
3545                 case 'k':
3546                         prim_nid = optarg;
3547                         break;
3548                 case 'n':
3549                         nidstr = optarg;
3550                         break;
3551                 case 'm':
3552                         if (cmd == LNETCTL_DEL_CMD) {
3553                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3554                                 snprintf(err_str, LNET_MAX_STR_LEN,
3555                                          "Unrecognized option '-%c'", opt);
3556                                 goto build_error;
3557                         }
3558                         is_mr = false;
3559                         break;
3560                 case 'f':
3561                         if (cmd == LNETCTL_ADD_CMD) {
3562                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3563                                 snprintf(err_str, LNET_MAX_STR_LEN,
3564                                          "Unrecognized option '-%c'", opt);
3565                         }
3566                         force_lock = 1;
3567                         break;
3568                 case 'l':
3569                         if (cmd == LNETCTL_DEL_CMD) {
3570                                 rc = LUSTRE_CFG_RC_BAD_PARAM;
3571                                 snprintf(err_str, LNET_MAX_STR_LEN,
3572                                          "Unrecognized option '-%c'", opt);
3573                         }
3574                         force_lock = 1;
3575                         break;
3576                 case '?':
3577                         print_help(peer_cmds, "peer",
3578                                    cmd == LNETCTL_ADD_CMD ? "add" : "del");
3579                 default:
3580                         return 0;
3581                 }
3582         }
3583
3584         rc = lustre_lnet_modify_peer(prim_nid, nidstr, is_mr, cmd,
3585                                      force_lock, -1, &err_rc);
3586         if (rc != LUSTRE_CFG_RC_NO_ERR)
3587                 goto out;
3588
3589 build_error:
3590         cYAML_build_error(rc, -1, "peer",
3591                           cmd == LNETCTL_ADD_CMD ? "add" : "del",
3592                           err_str, &err_rc);
3593
3594 out:
3595         if (rc != LUSTRE_CFG_RC_NO_ERR)
3596                 cYAML_print_tree2file(stderr, err_rc);
3597
3598         cYAML_free_tree(err_rc);
3599
3600         return rc;
3601 }
3602
3603 static int jt_add_peer_nid(int argc, char **argv)
3604 {
3605         return jt_peer_nid_common(argc, argv, LNETCTL_ADD_CMD);
3606 }
3607
3608 static int jt_del_peer_nid(int argc, char **argv)
3609 {
3610         return jt_peer_nid_common(argc, argv, LNETCTL_DEL_CMD);
3611 }
3612
3613 static int jt_show_peer(int argc, char **argv)
3614 {
3615         char *nid = NULL;
3616         int rc, opt;
3617         struct cYAML *err_rc = NULL, *show_rc = NULL;
3618         long int detail = 0;
3619         const char *const short_opts = "hn:v::";
3620         const struct option long_opts[] = {
3621                 { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3622                 { .name = "nid",        .has_arg = required_argument,   .val = 'n' },
3623                 { .name = "verbose",    .has_arg = optional_argument,   .val = 'v' },
3624                 { .name = NULL }
3625         };
3626
3627         rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
3628         if (rc)
3629                 return rc;
3630
3631         while ((opt = getopt_long(argc, argv, short_opts,
3632                                   long_opts, NULL)) != -1) {
3633                 switch (opt) {
3634                 case 'n':
3635                         nid = optarg;
3636                         break;
3637                 case 'v':
3638                         if ((!optarg) && (argv[optind] != NULL) &&
3639                             (argv[optind][0] != '-')) {
3640                                 if (parse_long(argv[optind++], &detail) != 0)
3641                                         detail = 1;
3642                         } else {
3643                                 detail = 1;
3644                         }
3645                         break;
3646                 case '?':
3647                         print_help(peer_cmds, "peer", "show");
3648                 default:
3649                         return 0;
3650                 }
3651         }
3652
3653         rc = yaml_lnet_peer(nid, NULL, false, -1, -1, false, detail,
3654                             NLM_F_DUMP);
3655         if (rc <= 0) {
3656                 if (rc == -EOPNOTSUPP)
3657                         goto old_api;
3658                 return rc;
3659         }
3660 old_api:
3661         rc = lustre_lnet_show_peer(nid, (int) detail, -1, &show_rc, &err_rc,
3662                                    false);
3663
3664         if (rc != LUSTRE_CFG_RC_NO_ERR)
3665                 cYAML_print_tree2file(stderr, err_rc);
3666         else if (show_rc)
3667                 cYAML_print_tree(show_rc);
3668
3669         cYAML_free_tree(err_rc);
3670         cYAML_free_tree(show_rc);
3671
3672         return rc;
3673 }
3674
3675 static int jt_list_peer(int argc, char **argv)
3676 {
3677         int rc;
3678         struct cYAML *err_rc = NULL, *list_rc = NULL;
3679
3680         rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
3681         if (rc)
3682                 return rc;
3683
3684         rc = yaml_lnet_peer(NULL, NULL, false, -1, -1, true, 0, NLM_F_DUMP);
3685         if (rc <= 0) {
3686                 if (rc == -EOPNOTSUPP)
3687                         goto old_api;
3688                 return rc;
3689         }
3690 old_api:
3691         if (rc != LUSTRE_CFG_RC_NO_ERR)
3692                 cYAML_print_tree2file(stderr, err_rc);
3693         else if (list_rc)
3694                 cYAML_print_tree(list_rc);
3695
3696         cYAML_free_tree(err_rc);
3697         cYAML_free_tree(list_rc);
3698
3699         return rc;
3700 }
3701
3702 static int jt_ping(int argc, char **argv)
3703 {
3704         struct cYAML *err_rc = NULL;
3705         struct cYAML *show_rc = NULL;
3706         int timeout = 1000;
3707         int rc = 0, opt;
3708         char *src_nidstr = NULL;
3709
3710         const char *const short_options = "hs:t:";
3711         const struct option long_options[] = {
3712         { .name = "help",       .has_arg = no_argument,         .val = 'h' },
3713         { .name = "timeout",    .has_arg = required_argument,   .val = 't' },
3714         { .name = "source",     .has_arg = required_argument,   .val = 's' },
3715         { .name = NULL } };
3716
3717         while ((opt = getopt_long(argc, argv, short_options,
3718                                   long_options, NULL)) != -1) {
3719                 switch (opt) {
3720                 case 's':
3721                         src_nidstr = optarg;
3722                         break;
3723                 case 't':
3724                         timeout = 1000 * atol(optarg);
3725                         break;
3726                 case 'h':
3727                         printf("ping nid[,nid,...]\n"
3728                                "\t --source: source nid\n"
3729                                "\t --timeout: ping timeout\n"
3730                                "\t --help: display this help\n");
3731                         return 0;
3732                 default:
3733                         return 0;
3734                 }
3735         }
3736
3737         for (; optind < argc; optind++)
3738                 rc = lustre_lnet_ping_nid(argv[optind], src_nidstr, timeout, -1,
3739                                           &show_rc, &err_rc);
3740
3741         if (show_rc)
3742                 cYAML_print_tree(show_rc);
3743
3744         if (err_rc)
3745                 cYAML_print_tree2file(stderr, err_rc);
3746
3747         cYAML_free_tree(err_rc);
3748         cYAML_free_tree(show_rc);
3749
3750         return rc;
3751 }
3752
3753 static int jt_discover(int argc, char **argv)
3754 {
3755         struct cYAML *err_rc = NULL;
3756         struct cYAML *show_rc = NULL;
3757         int force = 0;
3758         int rc = 0, opt;
3759
3760         const char *const short_options = "fh";
3761         const struct option long_options[] = {
3762                 { .name = "force",      .has_arg = no_argument, .val = 'f' },
3763                 { .name = "help",       .has_arg = no_argument, .val = 'h' },
3764                 { .name = NULL } };
3765
3766         while ((opt = getopt_long(argc, argv, short_options,
3767                                   long_options, NULL)) != -1) {
3768                 switch (opt) {
3769                 case 'f':
3770                         force = 1;
3771                         break;
3772                 case 'h':
3773                         printf("discover nid[,nid,...]\n"
3774                                "\t --force: force discovery\n"
3775                                "\t --help: display this help\n");
3776                         return 0;
3777                 default:
3778                         return 0;
3779                 }
3780         }
3781
3782         if (optind == argc) {
3783                 printf("Missing nid argument\n");
3784                 return -1;
3785         }
3786
3787         for (; optind < argc; optind++)
3788                 rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
3789                                               &err_rc);
3790
3791         if (show_rc)
3792                 cYAML_print_tree(show_rc);
3793
3794         if (err_rc)
3795                 cYAML_print_tree2file(stderr, err_rc);
3796
3797         cYAML_free_tree(err_rc);
3798         cYAML_free_tree(show_rc);
3799
3800         return rc;
3801 }
3802
3803 static int jt_add_udsp(int argc, char **argv)
3804 {
3805         char *src = NULL, *dst = NULL, *rte = NULL;
3806         struct cYAML *err_rc = NULL;
3807         union lnet_udsp_action udsp_action;
3808         long int idx = -1, priority = -1;
3809         int opt, rc = 0;
3810         char *action_type = "pref";
3811
3812         const char *const short_options = "s:d:r:p:i:";
3813         static const struct option long_options[] = {
3814         { .name = "src",         .has_arg = required_argument, .val = 's' },
3815         { .name = "dst",         .has_arg = required_argument, .val = 'd' },
3816         { .name = "rte",         .has_arg = required_argument, .val = 'r' },
3817         { .name = "priority",    .has_arg = required_argument, .val = 'p' },
3818         { .name = "idx",         .has_arg = required_argument, .val = 'i' },
3819         { .name = NULL } };
3820
3821         rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
3822         if (rc)
3823                 return rc;
3824
3825         while ((opt = getopt_long(argc, argv, short_options,
3826                                   long_options, NULL)) != -1) {
3827                 switch (opt) {
3828                 case 's':
3829                         src = optarg;
3830                         break;
3831                 case 'd':
3832                         dst = optarg;
3833                         break;
3834                 case 'r':
3835                         rte = optarg;
3836                         break;
3837                 case 'p':
3838                         rc = parse_long(optarg, &priority);
3839                         if (rc != 0 || priority < 0) {
3840                                 printf("Invalid priority \"%s\"\n", optarg);
3841                                 return -EINVAL;
3842                         }
3843                         action_type = "priority";
3844                         udsp_action.udsp_priority = priority;
3845                         break;
3846                 case 'i':
3847                         rc = parse_long(optarg, &idx);
3848                         if (rc != 0 || idx < 0) {
3849                                 printf("Invalid index \"%s\"\n", optarg);
3850                                 return -EINVAL;
3851                         }
3852                         break;
3853                 case '?':
3854                         print_help(udsp_cmds, "udsp", "add");
3855                 default:
3856                         return 0;
3857                 }
3858         }
3859
3860         if (!(src || dst || rte)) {
3861                 print_help(udsp_cmds, "udsp", "add");
3862                 return 0;
3863         }
3864
3865         rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
3866                                   idx, -1, &err_rc);
3867
3868         if (rc != LUSTRE_CFG_RC_NO_ERR)
3869                 cYAML_print_tree2file(stderr, err_rc);
3870
3871         cYAML_free_tree(err_rc);
3872
3873         return rc;
3874 }
3875
3876 static int jt_del_udsp(int argc, char **argv)
3877 {
3878         struct cYAML *err_rc = NULL;
3879         long int idx = -2;
3880         int opt, rc = 0;
3881         bool all = false;
3882
3883         const char *const short_options = "ai:";
3884         static const struct option long_options[] = {
3885         { .name = "all",        .has_arg = no_argument, .val = 'a' },
3886         { .name = "idx",        .has_arg = required_argument, .val = 'i' },
3887         { .name = NULL } };
3888
3889         rc = check_cmd(udsp_cmds, "udsp", "del", 0, argc, argv);
3890         if (rc)
3891                 return rc;
3892
3893         while ((opt = getopt_long(argc, argv, short_options,
3894                                   long_options, NULL)) != -1) {
3895                 switch (opt) {
3896                 case 'a':
3897                         all = true;
3898                         break;
3899                 case 'i':
3900                         rc = parse_long(optarg, &idx);
3901                         if (rc != 0 || idx < -1) {
3902                                 printf("Invalid index \"%s\"\n", optarg);
3903                                 return -EINVAL;
3904                         }
3905                         break;
3906                 case '?':
3907                         print_help(udsp_cmds, "udsp", "del");
3908                 default:
3909                         return 0;
3910                 }
3911         }
3912
3913         if (all && idx != -2) {
3914                 printf("Cannot combine --all with --idx\n");
3915                 return -EINVAL;
3916         } else if (all) {
3917                 idx = -1;
3918         } else if (idx == -2) {
3919                 printf("Must specify --idx or --all\n");
3920                 return -EINVAL;
3921         }
3922
3923         rc = lustre_lnet_del_udsp(idx, -1, &err_rc);
3924         if (rc != LUSTRE_CFG_RC_NO_ERR)
3925                 cYAML_print_tree2file(stderr, err_rc);
3926
3927         cYAML_free_tree(err_rc);
3928
3929         return rc;
3930 }
3931
3932 int main(int argc, char **argv)
3933 {
3934         int rc = 0;
3935         struct cYAML *err_rc = NULL;
3936
3937         rc = lustre_lnet_config_lib_init();
3938         if (rc < 0) {
3939                 cYAML_build_error(-1, -1, "lnetctl", "startup",
3940                                   "cannot register LNet device", &err_rc);
3941                 cYAML_print_tree2file(stderr, err_rc);
3942                 return rc;
3943         }
3944
3945         return cfs_parser(argc, argv, cmd_list);
3946 }