+static int jt_add_peer_nid(int argc, char **argv)
+{
+ char *prim_nid = NULL;
+ char **nids = NULL, **nids2 = NULL;
+ int size = 0;
+ struct cYAML *err_rc = NULL;
+ int rc = LUSTRE_CFG_RC_NO_ERR, opt, i;
+ bool non_mr = false;
+ bool ip2nets = false, nid_list = false, prim_nid_present = false;
+
+ 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 = "ip2nets", .has_arg = required_argument, .val = 'i' },
+ { .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_present = true;
+ if (ip2nets) {
+ cYAML_build_error(-1, -1, "peer", "add",
+ "ip2nets can not be specified"
+ " along side prim_nid parameter.",
+ &err_rc);
+ goto failed;
+ }
+ prim_nid = optarg;
+ break;
+ case 'i':
+ case 'n':
+ if (opt == 'i')
+ ip2nets = true;
+
+ if (opt == 'n')
+ nid_list = true;
+
+ if (ip2nets && (nid_list || prim_nid_present)) {
+ cYAML_build_error(-1, -1, "peer", "add",
+ "ip2nets can not be specified"
+ " along side nid or prim_nid"
+ " parameters", &err_rc);
+ goto failed;
+ }
+
+ size = lustre_lnet_parse_nids(optarg, nids, size,
+ &nids2);
+ if (nids2 == NULL)
+ goto failed;
+ nids = nids2;
+ rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ break;
+ case 'm':
+ non_mr = true;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ for (; optind < argc; optind++) {
+ size = lustre_lnet_parse_nids(argv[optind], nids, size,
+ &nids2);
+ if (nids2 == NULL)
+ goto failed;
+ nids = nids2;
+ }
+
+ rc = lustre_lnet_config_peer_nid(prim_nid, nids, size,
+ !non_mr, ip2nets, -1, &err_rc);
+
+failed:
+ if (nids) {
+ /* free the array of nids */
+ for (i = 0; i < size; i++)
+ free(nids[i]);
+ free(nids);
+ }
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_del_peer_nid(int argc, char **argv)
+{
+ char *prim_nid = NULL;
+ char **nids = NULL, **nids2 = NULL;
+ struct cYAML *err_rc = NULL;
+ int rc = LUSTRE_CFG_RC_NO_ERR, opt, i, size = 0;
+ bool ip2nets = false, nid_list = false, prim_nid_present = false;
+
+ const char *const short_opts = "k:n:";
+ const struct option long_opts[] = {
+ { .name = "prim_nid", .has_arg = required_argument, .val = 'k' },
+ { .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = "ip2nets", .has_arg = required_argument, .val = 'i' },
+ { .name = NULL } };
+
+ rc = check_cmd(peer_cmds, "peer", "del", 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_present = true;
+ if (ip2nets) {
+ cYAML_build_error(-1, -1, "peer", "add",
+ "ip2nets can not be specified"
+ " along side prim_nid parameter.",
+ &err_rc);
+ goto failed;
+ }
+ prim_nid = optarg;
+ break;
+ case 'i':
+ case 'n':
+ if (opt == 'i')
+ ip2nets = true;
+
+ if (opt == 'n')
+ nid_list = true;
+
+ if (ip2nets && (nid_list || prim_nid_present)) {
+ cYAML_build_error(-1, -1, "peer", "add",
+ "ip2nets can not be specified"
+ " along side nid or prim_nid"
+ " parameters", &err_rc);
+ goto failed;
+ }
+ size = lustre_lnet_parse_nids(optarg, nids, size,
+ &nids2);
+ if (nids2 == NULL)
+ goto failed;
+ nids = nids2;
+ rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ for (; optind < argc; optind++) {
+ size = lustre_lnet_parse_nids(argv[optind], nids, size,
+ &nids2);
+ if (nids2 == NULL)
+ goto failed;
+ nids = nids2;
+ }
+
+ rc = lustre_lnet_del_peer_nid(prim_nid, nids, size, ip2nets, -1, &err_rc);
+
+failed:
+ if (nids) {
+ for (i = 0; i < size; i++)
+ free(nids[i]);
+ free(nids);
+ }
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+
+ return rc;
+}
+
+static int jt_show_peer(int argc, char **argv)
+{
+ char *nid = NULL;
+ int rc, opt;
+ struct cYAML *err_rc = NULL, *show_rc = NULL;
+ long int detail = 0;
+
+ const char *const short_opts = "hn:v::";
+ const struct option long_opts[] = {
+ { .name = "help", .has_arg = no_argument, .val = 'h' },
+ { .name = "nid", .has_arg = required_argument, .val = 'n' },
+ { .name = "verbose", .has_arg = optional_argument, .val = 'v' },
+ { .name = NULL } };
+
+ rc = check_cmd(peer_cmds, "peer", "show", 1, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_opts,
+ long_opts, NULL)) != -1) {
+ switch (opt) {
+ case 'n':
+ nid = 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;
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_show_peer(nid, (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_list_peer(int argc, char **argv)
+{
+ int rc;
+ struct cYAML *err_rc = NULL, *list_rc = NULL;
+
+ rc = check_cmd(peer_cmds, "peer", "list", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ rc = lustre_lnet_list_peer(-1, &list_rc, &err_rc);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ cYAML_print_tree2file(stderr, err_rc);
+ else if (list_rc)
+ cYAML_print_tree(list_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(list_rc);
+
+ return rc;
+}
+
+static int jt_ping(int argc, char **argv)
+{
+ struct cYAML *err_rc = NULL;
+ struct cYAML *show_rc = NULL;
+ int timeout = 1000;
+ int rc = 0, opt;
+
+ const char *const short_options = "ht:";
+ const struct option long_options[] = {
+ { .name = "help", .has_arg = no_argument, .val = 'h' },
+ { .name = "timeout", .has_arg = required_argument, .val = 't' },
+ { .name = NULL } };
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 't':
+ timeout = 1000 * atol(optarg);
+ break;
+ case 'h':
+ printf("ping nid[,nid,...]\n"
+ "\t --timeout: ping timeout\n"
+ "\t --help: display this help\n");
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ for (; optind < argc; optind++)
+ rc = lustre_lnet_ping_nid(argv[optind], timeout, -1, &show_rc, &err_rc);
+
+ if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ if (err_rc)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int jt_discover(int argc, char **argv)
+{
+ struct cYAML *err_rc = NULL;
+ struct cYAML *show_rc = NULL;
+ int force = 0;
+ int rc = 0, opt;
+
+ const char *const short_options = "fh";
+ const struct option long_options[] = {
+ { .name = "force", .has_arg = no_argument, .val = 'f' },
+ { .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 'f':
+ force = 1;
+ break;
+ case 'h':
+ printf("discover nid[,nid,...]\n"
+ "\t --force: force discovery\n"
+ "\t --help: display this help\n");
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ for (; optind < argc; optind++)
+ rc = lustre_lnet_discover_nid(argv[optind], force, -1, &show_rc,
+ &err_rc);
+
+ if (show_rc)
+ cYAML_print_tree(show_rc);
+
+ if (err_rc)
+ cYAML_print_tree2file(stderr, err_rc);
+
+ cYAML_free_tree(err_rc);
+ cYAML_free_tree(show_rc);
+
+ return rc;
+}
+
+static int lnetctl_list_commands(int argc, char **argv)
+{
+ char buffer[81] = ""; /* 80 printable chars + terminating NUL */
+
+ Parser_list_commands(cmd_list, buffer, sizeof(buffer), NULL, 0, 4);
+
+ return 0;
+}