+ case 'p':
+ rc = parse_long(optarg, &prio);
+ if (rc != 0) {
+ /* ingore option */
+ prio = -1;
+ continue;
+ }
+ break;
+ case 's':
+ rc = parse_long(optarg, &sen);
+ if (rc != 0) {
+ /* ingore option */
+ sen = -1;
+ continue;
+ }
+ break;
+
+ case '?':
+ print_help(route_cmds, "route", "add");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_config_route(network, gateway, hop, prio, sen, -1,
+ &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_add_ni(int argc, char **argv)
+{
+ char *ip2net = NULL;
+ long int pto = -1, pc = -1, pbc = -1, cre = -1, cpp = -1;
+ struct cYAML *err_rc = NULL;
+ int rc, opt, cpt_rc = -1;
+ struct lnet_dlc_network_descr nw_descr;
+ struct cfs_expr_list *global_cpts = NULL;
+ struct lnet_ioctl_config_lnd_tunables tunables;
+ bool found = false;
+ bool skip_mr_route_setup = false;
+
+ memset(&tunables, 0, sizeof(tunables));
+ lustre_lnet_init_nw_descr(&nw_descr);
+
+ const char *const short_options = "b:c:i:k:m:n:p:r:s:t:";
+ static const struct option long_options[] = {
+ { .name = "peer-buffer-credits",
+ .has_arg = required_argument, .val = 'b' },
+ { .name = "peer-credits", .has_arg = required_argument, .val = 'c' },
+ { .name = "if", .has_arg = required_argument, .val = 'i' },
+ { .name = "skip-mr-route-setup",
+ .has_arg = no_argument, .val = 'k' },
+ { .name = "conns-per-peer",
+ .has_arg = required_argument, .val = 'm' },
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "ip2net", .has_arg = required_argument, .val = 'p' },
+ { .name = "credits", .has_arg = required_argument, .val = 'r' },
+ { .name = "cpt", .has_arg = required_argument, .val = 's' },
+ { .name = "peer-timeout", .has_arg = required_argument, .val = 't' },
+ { .name = NULL } };
+
+ rc = check_cmd(net_cmds, "net", "add", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'b':
+ rc = parse_long(optarg, &pbc);
+ if (rc != 0) {
+ /* ignore option */
+ pbc = -1;
+ continue;
+ }
+ break;
+ case 'c':
+ rc = parse_long(optarg, &pc);
+ if (rc != 0) {
+ /* ignore option */
+ pc = -1;
+ continue;
+ }
+ break;
+ case 'i':
+ rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
+ if (rc != 0) {
+ cYAML_build_error(-1, -1, "ni", "add",
+ "bad interface list",
+ &err_rc);
+ goto failed;
+ }
+ break;
+ case 'k':
+ skip_mr_route_setup = true;
+ break;
+ case 'm':
+ rc = parse_long(optarg, &cpp);
+ if (rc != 0) {
+ /* ignore option */
+ cpp = -1;
+ continue;
+ }
+ break;
+
+ case 'n':
+ nw_descr.nw_id = libcfs_str2net(optarg);
+ break;
+ case 'p':
+ ip2net = optarg;
+ break;
+ case 'r':
+ rc = parse_long(optarg, &cre);
+ if (rc != 0) {
+ /* ignore option */
+ cre = -1;
+ continue;
+ }
+ break;
+ case 's':
+ cpt_rc = cfs_expr_list_parse(optarg,
+ strlen(optarg), 0,
+ UINT_MAX, &global_cpts);
+ break;
+ case 't':
+ rc = parse_long(optarg, &pto);
+ if (rc != 0) {
+ /* ignore option */
+ pto = -1;
+ continue;
+ }
+ break;
+ case '?':
+ print_help(net_cmds, "net", "add");
+ default:
+ return 0;
+ }
+ }
+
+ if (pto > 0 || pc > 0 || pbc > 0 || cre > 0 || cpp > -1) {
+ tunables.lt_cmn.lct_peer_timeout = pto;
+ tunables.lt_cmn.lct_peer_tx_credits = pc;
+ tunables.lt_cmn.lct_peer_rtr_credits = pbc;
+ tunables.lt_cmn.lct_max_tx_credits = cre;
+ found = true;
+ }
+
+ rc = lustre_lnet_config_ni(&nw_descr,
+ (cpt_rc == 0) ? global_cpts: NULL,
+ ip2net, (found) ? &tunables : NULL,
+ cpp, -1, &err_rc);
+
+ if (global_cpts != NULL)
+ cfs_expr_list_free(global_cpts);
+
+failed:
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ if (rc == LUSTRE_CFG_RC_NO_ERR && !skip_mr_route_setup) {
+ err_rc = NULL;
+ rc = lustre_lnet_setup_mrrouting(&err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+ }
+
+ return rc;
+}
+
+static int jt_del_route(int argc, char **argv)
+{
+ char *network = NULL, *gateway = NULL;
+ struct cYAML *err_rc = NULL;
+ int rc, opt;
+
+ const char *const short_options = "n:g:";
+ static const struct option long_options[] = {
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "gateway", .has_arg = required_argument, .val = 'g' },
+ { .name = NULL } };
+
+ rc = check_cmd(route_cmds, "route", "del", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ network = optarg;
+ break;
+ case 'g':
+ gateway = optarg;
+ break;
+ case '?':
+ print_help(route_cmds, "route", "del");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_del_route(network, gateway, -1, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_del_ni(int argc, char **argv)
+{
+ struct cYAML *err_rc = NULL;
+ int rc, opt;
+ struct lnet_dlc_network_descr nw_descr;
+
+ lustre_lnet_init_nw_descr(&nw_descr);
+
+ const char *const short_options = "n:i:";
+ static const struct option long_options[] = {
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "if", .has_arg = required_argument, .val = 'i' },
+ { .name = NULL } };
+
+ rc = check_cmd(net_cmds, "net", "del", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ nw_descr.nw_id = libcfs_str2net(optarg);
+ break;
+ case 'i':
+ rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
+ if (rc != 0) {
+ cYAML_build_error(-1, -1, "ni", "add",
+ "bad interface list",
+ &err_rc);
+ goto out;
+ }
+ break;
+ case '?':
+ print_help(net_cmds, "net", "del");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
+
+out:
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_show_route(int argc, char **argv)
+{
+ char *network = NULL, *gateway = NULL;
+ long int hop = -1, prio = -1;
+ int detail = 0, rc, opt;
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+
+ const char *const short_options = "n:g:h:p:v";
+ static const struct option long_options[] = {
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "gateway", .has_arg = required_argument, .val = 'g' },
+ { .name = "hop-count", .has_arg = required_argument, .val = 'c' },
+ { .name = "priority", .has_arg = required_argument, .val = 'p' },
+ { .name = "verbose", .has_arg = no_argument, .val = 'v' },
+ { .name = NULL } };
+
+ rc = check_cmd(route_cmds, "route", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ network = optarg;
+ break;
+ case 'g':
+ gateway = optarg;
+ break;
+ case 'c':
+ rc = parse_long(optarg, &hop);
+ if (rc != 0) {
+ /* ignore option */
+ hop = -1;
+ continue;
+ }
+ break;
+ case 'p':
+ rc = parse_long(optarg, &prio);
+ if (rc != 0) {
+ /* ignore option */
+ prio = -1;
+ continue;
+ }
+ break;
+ case 'v':
+ detail = 1;
+ break;
+ case '?':
+ print_help(route_cmds, "route", "show");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_show_route(network, gateway, hop, prio, detail, -1,
+ &show_rc, &err_rc, false);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int set_value_helper(int argc, char **argv,
+ int (*cb)(int, bool, char*, int, struct cYAML**))
+{
+ char *nid = NULL;
+ long int healthv = -1;
+ bool all = false;
+ int rc, opt;
+ struct cYAML *err_rc = NULL;
+
+ const char *const short_options = "t:n:a";
+ static const struct option long_options[] = {
+ { .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = "health", .has_arg = required_argument, .val = 't' },
+ { .name = "all", .has_arg = no_argument, .val = 'a' },
+ { .name = NULL } };
+
+ rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ nid = optarg;
+ break;
+ case 't':
+ if (parse_long(optarg, &healthv) != 0)
+ healthv = -1;
+ break;
+ case 'a':
+ all = true;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ rc = cb(healthv, all, nid, -1, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_set_ni_value(int argc, char **argv)
+{
+ char *nid = NULL;
+ long int healthv = -1, cpp = -1;
+ bool all = false;
+ int rc, opt;
+ struct cYAML *err_rc = NULL;
+
+ const char *const short_options = "a:m:n:t:";
+ static const struct option long_options[] = {
+ { .name = "all", .has_arg = no_argument, .val = 'a' },
+ { .name = "conns-per-peer", .has_arg = required_argument, .val = 'm' },
+ { .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = "health", .has_arg = required_argument, .val = 't' },
+ { .name = NULL } };
+
+ rc = check_cmd(net_cmds, "net", "set", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'a':
+ all = true;
+ break;
+ case 'm':
+ rc = parse_long(optarg, &cpp);
+ if (rc != 0) {
+ /* ignore option */
+ cpp = -1;
+ continue;
+ }
+ break;
+ case 'n':
+ nid = optarg;
+ break;
+ case 't':
+ if (parse_long(optarg, &healthv) != 0) {
+ /* ignore option */
+ healthv = -1;
+ continue;
+ }
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ if (cpp > -1)
+ rc = lustre_lnet_config_ni_conns_per_peer(cpp, all, nid,
+ -1, &err_rc);
+ if (healthv > -1)
+ rc = lustre_lnet_config_ni_healthv(healthv, all, nid,
+ -1, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_set_peer_ni_value(int argc, char **argv)
+{
+ return set_value_helper(argc, argv, lustre_lnet_config_peer_ni_healthv);
+}
+
+static int jt_show_recovery(int argc, char **argv)
+{
+ int rc, opt;
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+
+ const char *const short_options = "lp";
+ static const struct option long_options[] = {
+ { .name = "local", .has_arg = no_argument, .val = 'l' },
+ { .name = "peer", .has_arg = no_argument, .val = 'p' },
+ { .name = NULL } };
+
+ rc = check_cmd(debug_cmds, "recovery", NULL, 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'l':
+ rc = lustre_lnet_show_local_ni_recovq(-1, &show_rc, &err_rc);
+ break;
+ case 'p':
+ rc = lustre_lnet_show_peer_ni_recovq(-1, &show_rc, &err_rc);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_show_net(int argc, char **argv)
+{
+ char *network = NULL;
+ int rc, opt;
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+ long int detail = 0;
+
+ const char *const short_options = "n:v";
+ static const struct option long_options[] = {
+ { .name = "net", .has_arg = required_argument, .val = 'n' },
+ { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
+ { .name = NULL } };
+
+ rc = check_cmd(net_cmds, "net", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ network = optarg;
+ break;
+ case 'v':
+ if ((!optarg) && (argv[optind] != NULL) &&
+ (argv[optind][0] != '-')) {
+ if (parse_long(argv[optind++], &detail) != 0)
+ detail = 1;
+ } else {
+ detail = 1;
+ }
+ break;
+ case '?':
+ print_help(net_cmds, "net", "show");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_show_net(network, (int) detail, -1, &show_rc, &err_rc,
+ false);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_show_routing(int argc, char **argv)
+{
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+ int rc;
+
+ rc = check_cmd(routing_cmds, "routing", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, false);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_show_stats(int argc, char **argv)
+{
+ int rc;
+ struct cYAML *show_rc = NULL, *err_rc = NULL;
+
+ rc = check_cmd(stats_cmds, "stats", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ rc = lustre_lnet_show_stats(-1, &show_rc, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_show_udsp(int argc, char **argv)
+{
+ int idx = -1;
+ int rc, opt;
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+
+ const char *const short_options = "i:";
+ static const struct option long_options[] = {
+ { .name = "idx", .has_arg = required_argument, .val = 'i' },
+ { .name = NULL }
+ };
+
+ rc = check_cmd(udsp_cmds, "udsp", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'i':
+ idx = atoi(optarg);
+ break;
+ case '?':
+ print_help(net_cmds, "net", "show");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_show_udsp(idx, -1, &show_rc, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_show_global(int argc, char **argv)
+{
+ int rc;
+ struct cYAML *show_rc = NULL, *err_rc = NULL;
+
+ rc = check_cmd(global_cmds, "global", "show", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ goto out;
+ }
+
+ if (show_rc)
+ cYAML_print_tree(show_rc);
+
+out:
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_lnet(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(lnet_cmds, "lnet", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], lnet_cmds);
+}
+
+static int jt_route(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(route_cmds, "route", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], route_cmds);
+}
+
+static int jt_net(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(net_cmds, "net", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], net_cmds);
+}
+
+static int jt_routing(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(routing_cmds, "routing", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], routing_cmds);
+}
+
+static int jt_stats(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(stats_cmds, "stats", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], stats_cmds);
+}
+
+static int jt_debug(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(debug_cmds, "recovery", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], debug_cmds);
+}
+
+static int jt_global(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(global_cmds, "global", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], global_cmds);
+}
+
+static int jt_peers(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(peer_cmds, "peer", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], peer_cmds);
+}
+
+static int jt_set(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(set_cmds, "set", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], set_cmds);
+}
+
+static int jt_udsp(int argc, char **argv)
+{
+ int rc;
+
+ rc = check_cmd(udsp_cmds, "udsp", NULL, 2, argc, argv);
+ if (rc)
+ return rc;
+
+ return Parser_execarg(argc - 1, &argv[1], udsp_cmds);
+}
+
+static int jt_import(int argc, char **argv)
+{
+ char *file = NULL;
+ struct cYAML *err_rc = NULL;
+ struct cYAML *show_rc = NULL;
+ int rc = 0, return_rc = 0, opt, opt_found = 0;
+ char cmd = 'a';
+
+ const char *const short_options = "adseh";
+ static const struct option long_options[] = {
+ { .name = "add", .has_arg = no_argument, .val = 'a' },
+ { .name = "del", .has_arg = no_argument, .val = 'd' },
+ { .name = "show", .has_arg = no_argument, .val = 's' },
+ { .name = "exec", .has_arg = no_argument, .val = 'e' },
+ { .name = "help", .has_arg = no_argument, .val = 'h' },
+ { .name = NULL } };
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ opt_found = 1;
+ switch (opt) {
+ case 'a':
+ cmd = opt;
+ break;
+ case 'd':
+ case 's':
+ cmd = opt;
+ break;
+ case 'e':
+ cmd = opt;
+ break;
+ case 'h':
+ printf("import FILE\n"
+ "import < FILE : import a file\n"
+ "\t--add: add configuration\n"
+ "\t--del: delete configuration\n"
+ "\t--show: show configuration\n"
+ "\t--exec: execute command\n"
+ "\t--help: display this help\n"
+ "If no command option is given then --add"
+ " is assumed by default\n");
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ /* grab the file name if one exists */
+ if (opt_found && argc == 3)
+ file = argv[2];
+ else if (!opt_found && argc == 2)
+ file = argv[1];
+
+ switch (cmd) {
+ case 'a':
+ rc = lustre_yaml_config(file, &err_rc);
+ return_rc = lustre_yaml_exec(file, &show_rc, &err_rc);
+ cYAML_print_tree(show_rc);
+ cYAML_free_tree(show_rc);
+ break;
+ case 'd':
+ rc = lustre_yaml_del(file, &err_rc);
+ break;
+ case 's':
+ rc = lustre_yaml_show(file, &show_rc, &err_rc);
+ cYAML_print_tree(show_rc);
+ cYAML_free_tree(show_rc);
+ break;
+ case 'e':
+ rc = lustre_yaml_exec(file, &show_rc, &err_rc);
+ cYAML_print_tree(show_rc);
+ cYAML_free_tree(show_rc);
+ break;
+ }
+
+ if (rc || return_rc) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ }
+
+ return rc;
+}
+
+static int jt_export(int argc, char **argv)
+{
+ struct cYAML *show_rc = NULL;
+ struct cYAML *err_rc = NULL;
+ int rc;
+ FILE *f = NULL;
+ int opt;
+ bool backup = false;
+ char *file = NULL;
+
+ const char *const short_options = "bh";
+ static const struct option long_options[] = {
+ { .name = "backup", .has_arg = no_argument, .val = 'b' },
+ { .name = "help", .has_arg = no_argument, .val = 'h' },
+ { .name = NULL } };
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'b':
+ backup = true;
+ break;
+ case 'h':
+ default:
+ printf("export > FILE.yaml : export configuration\n"
+ "\t--backup: export only what's necessary for reconfig\n"
+ "\t--help: display this help\n");
+ return 0;
+ }
+ }
+
+ if (backup && argc >= 3)
+ file = argv[2];
+ else if (!backup && argc >= 2)
+ file = argv[1];
+ else
+ f = stdout;
+
+ if (file) {
+ f = fopen(file, "w");
+ if (f == NULL)
+ return -1;
+ }
+
+ rc = lustre_lnet_show_net(NULL, 2, -1, &show_rc, &err_rc, backup);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_route(NULL, NULL, -1, -1, 1, -1, &show_rc,
+ &err_rc, backup);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_routing(-1, &show_rc, &err_rc, backup);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_peer(NULL, 2, -1, &show_rc, &err_rc, backup);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_numa_range(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_max_intf(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_discovery(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_drop_asym_route(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_retry_count(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_transaction_to(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_hsensitivity(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_recov_intrv(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_lnd_timeout(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_response_tracking(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_recovery_limit(-1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ rc = lustre_lnet_show_udsp(-1, -1, &show_rc, &err_rc);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ cYAML_print_tree2file(stderr, err_rc);
+ cYAML_free_tree(err_rc);
+ err_rc = NULL;
+ }
+
+ if (show_rc != NULL) {
+ cYAML_print_tree2file(f, show_rc);
+ cYAML_free_tree(show_rc);
+ }
+
+ if (argc >= 2)
+ fclose(f);
+
+ return 0;
+}
+
+static int jt_peer_nid_common(int argc, char **argv, int cmd)
+{
+ int rc = LUSTRE_CFG_RC_NO_ERR, opt;
+ bool is_mr = true;
+ char *prim_nid = NULL, *nidstr = NULL;
+ char err_str[LNET_MAX_STR_LEN] = "Error";
+ struct cYAML *err_rc = NULL;
+
+ const char *const short_opts = "k:mn:";
+ const struct option long_opts[] = {
+ { .name = "prim_nid", .has_arg = required_argument, .val = 'k' },
+ { .name = "non_mr", .has_arg = no_argument, .val = 'm' },
+ { .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = NULL } };
+
+ rc = check_cmd(peer_cmds, "peer", "add", 2, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_opts,
+ long_opts, NULL)) != -1) {
+ switch (opt) {
+ case 'k':
+ prim_nid = optarg;
+ break;
+ case 'n':
+ nidstr = optarg;