int cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res);
int cfs_str2num_check(char *str, int nob, unsigned *num,
unsigned min, unsigned max);
+int cfs_expr2str(struct list_head *list, char *str, size_t size);
int cfs_expr_list_match(__u32 value, struct cfs_expr_list *expr_list);
int cfs_expr_list_print(char *buffer, int count,
struct cfs_expr_list *expr_list);
return rc;
}
+int
+cfs_expr2str(struct list_head *list, char *str, size_t size)
+{
+ struct cfs_expr_list *expr;
+ struct cfs_range_expr *range;
+ char tmp[LNET_NIDSTR_SIZE];
+ size_t len;
+ bool first;
+ bool bracket = false;
+ char *format;
+ char *tmpc;
+
+ list_for_each_entry(expr, list, el_link) {
+ first = true;
+ list_for_each_entry(range, &expr->el_exprs, re_link) {
+ if (range->re_lo == range->re_hi) {
+ snprintf(tmp,
+ LNET_NIDSTR_SIZE,
+ "%u.", range->re_lo);
+ } else if (range->re_lo < range->re_hi) {
+ if (range->re_stride > 1) {
+ if (first)
+ format = "[%u-%u/%u,";
+ else
+ format = "%u-%u/%u,";
+ snprintf(tmp, LNET_NIDSTR_SIZE,
+ format, range->re_lo,
+ range->re_hi, range->re_stride);
+ bracket = true;
+ } else {
+ if (first)
+ format = "[%u-%u,";
+ else
+ format = "%u-%u,";
+ snprintf(tmp, LNET_NIDSTR_SIZE,
+ format, range->re_lo,
+ range->re_hi);
+ bracket = true;
+ }
+ } else {
+ return -EINVAL;
+ }
+ len = strlen(tmp);
+ size -= (len + 1);
+ if (size < 0)
+ return -ENOBUFS;
+
+ strncat(str, tmp, size + len);
+ first = false;
+ }
+ if (bracket) {
+ tmpc = str + (strlen(str) - 1);
+ size -= 1;
+ if (size < 0)
+ return -ENOBUFS;
+ *tmpc = ']';
+ *(tmpc+1) = '.';
+ bracket = false;
+ }
+ }
+
+ /*
+ * get rid of the trailing '.' at the end of the string
+ * only if we actually had something on the list passed in.
+ * otherwise we could write outside the array
+ */
+ if (!list_empty(list))
+ str[strlen(str)-1] = '\0';
+ return size;
+}
+
static int
libcfs_num_addr_range_expand(struct list_head *addrranges, __u32 *addrs,
int max_addrs)
return NULL;
}
+static int
+create_local_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
+ struct cYAML *net_node)
+{
+ char tmp[LNET_MAX_STR_LEN];
+ struct cYAML *udsp_net;
+ bool created = false;
+ struct cYAML *pref;
+ int i;
+
+ /* add the UDSP info */
+ udsp_net = cYAML_create_object(net_node, "udsp info");
+ if (!udsp_net)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ if (!cYAML_create_number(udsp_net, "net priority",
+ (int) udsp_info->cud_net_priority))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ if (!cYAML_create_number(udsp_net, "nid priority",
+ (int)udsp_info->cud_nid_priority))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ pref = udsp_net;
+
+ for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ if (udsp_info->cud_pref_rtr_nid[i] == 0)
+ break;
+ if (!created) {
+ pref = cYAML_create_object(udsp_net,
+ "Preferred gateway NIDs");
+ if (!pref)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ created = true;
+ }
+ snprintf(tmp, sizeof(tmp), "NID-%d", i);
+ if (!cYAML_create_string(pref, tmp,
+ libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ }
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+static int
+create_remote_udsp_info(struct lnet_ioctl_construct_udsp_info *udsp_info,
+ struct cYAML *nid_node)
+{
+ char tmp[LNET_MAX_STR_LEN];
+ struct cYAML *udsp_nid;
+ bool created = false;
+ struct cYAML *pref;
+ int i;
+
+ /* add the UDSP info */
+ udsp_nid = cYAML_create_object(nid_node, "udsp info");
+ if (!udsp_nid)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ if (!cYAML_create_number(udsp_nid, "net priority",
+ (int) udsp_info->cud_net_priority))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ if (!cYAML_create_number(udsp_nid, "nid priority",
+ (int) udsp_info->cud_nid_priority))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ pref = udsp_nid;
+ for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ if (udsp_info->cud_pref_rtr_nid[i] == 0)
+ break;
+ if (!created) {
+ pref = cYAML_create_object(udsp_nid,
+ "Preferred gateway NIDs");
+ if (!pref)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ created = true;
+ }
+ snprintf(tmp, sizeof(tmp), "NID-%d", i);
+ if (!cYAML_create_string(pref, tmp,
+ libcfs_nid2str(udsp_info->cud_pref_rtr_nid[i])))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ }
+
+ pref = udsp_nid;
+ created = false;
+ for (i = 0; i < LNET_MAX_SHOW_NUM_NID; i++) {
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ if (udsp_info->cud_pref_nid[i] == 0)
+ break;
+ if (!created) {
+ pref = cYAML_create_object(udsp_nid,
+ "Preferred source NIDs");
+ if (!pref)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ created = true;
+ }
+ snprintf(tmp, sizeof(tmp), "NID-%d", i);
+ if (!cYAML_create_string(pref, tmp,
+ libcfs_nid2str(udsp_info->cud_pref_nid[i])))
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+ }
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
int lustre_lnet_show_net(char *nw, int detail, int seq_no,
struct cYAML **show_rc, struct cYAML **err_rc,
bool backup)
struct lnet_ioctl_element_stats *stats;
struct lnet_ioctl_element_msg_stats msg_stats;
struct lnet_ioctl_local_ni_hstats hstats;
+ struct lnet_ioctl_construct_udsp_info udsp_info;
__u32 net = LNET_NET_ANY;
__u32 prev_net = LNET_NET_ANY;
int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
== NULL)
goto out;
+ if (detail < 4)
+ goto continue_without_udsp_info;
+
+ LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
+ udsp_info.cud_nid = ni_data->lic_nid;
+ udsp_info.cud_peer = false;
+ rc = l_ioctl(LNET_DEV_ID,
+ IOC_LIBCFS_GET_CONST_UDSP_INFO,
+ &udsp_info);
+ if (rc != 0) {
+ l_errno = errno;
+ goto continue_without_udsp_info;
+ }
+
+ rc = create_local_udsp_info(&udsp_info, item);
+ if (rc) {
+ l_errno = errno;
+ goto out;
+ }
+
+continue_without_udsp_info:
if (detail < 2)
goto continue_without_msg_stats;
struct lnet_ioctl_element_stats *lpni_stats;
struct lnet_ioctl_element_msg_stats *msg_stats;
struct lnet_ioctl_peer_ni_hstats *hstats;
+ struct lnet_ioctl_construct_udsp_info udsp_info;
lnet_nid_t *nidp;
int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
int i, j, k;
if (backup)
continue;
+ if (detail < 4)
+ goto continue_without_udsp_info;
+
+ LIBCFS_IOC_INIT_V2(udsp_info, cud_hdr);
+ udsp_info.cud_nid = *nidp;
+ udsp_info.cud_peer = true;
+ rc = l_ioctl(LNET_DEV_ID,
+ IOC_LIBCFS_GET_CONST_UDSP_INFO,
+ &udsp_info);
+ if (rc != 0) {
+ l_errno = errno;
+ goto continue_without_udsp_info;
+ }
+
+ rc = create_remote_udsp_info(&udsp_info, peer_ni);
+ if (rc) {
+ l_errno = errno;
+ goto out;
+ }
+
+continue_without_udsp_info:
if (cYAML_create_string(peer_ni, "state",
lpni_cri->cr_aliveness)
== NULL)
err_rc);
}
+static int handle_yaml_show_udsp(struct cYAML *tree, struct cYAML **show_rc,
+ struct cYAML **err_rc)
+{
+ struct cYAML *seq_no;
+ struct cYAML *idx;
+
+ seq_no = cYAML_get_object_item(tree, "seq_no");
+ idx = cYAML_get_object_item(tree, "idx");
+
+ return lustre_lnet_show_udsp(idx ? idx->cy_valueint : -1,
+ seq_no ? seq_no->cy_valueint : -1,
+ show_rc, err_rc);
+}
+
static int handle_yaml_config_global_settings(struct cYAML *tree,
struct cYAML **show_rc,
struct cYAML **err_rc)
{ .name = "numa", .cb = handle_yaml_show_numa },
{ .name = "ping", .cb = handle_yaml_no_op },
{ .name = "discover", .cb = handle_yaml_no_op },
+ { .name = "udsp", .cb = handle_yaml_show_udsp },
{ .name = NULL } };
static struct lookup_cmd_hdlr_tbl lookup_exec_tbl[] = {
*/
int lustre_lnet_del_udsp(unsigned int idx, int seq_no, struct cYAML **err_rc);
+/* lustre_lnet_show_udsp
+ * show selection policy.
+ * idx - the index to show. -1 to show all policies
+ * seq_no - sequence number of the request
+ * err_rc - [IN/OUT] struct cYAML tree containing udsp info
+ * err_rc - [OUT] struct cYAML tree describing the error. Freed by
+ * caller
+ */
+int lustre_lnet_show_udsp(int idx, int seq_no, struct cYAML **show_rc,
+ struct cYAML **err_rc);
+
#endif /* LIB_LNET_CONFIG_API_H */
cYAML_build_error(rc, seq_no, ADD_CMD, "udsp", err_str, err_rc);
return rc;
}
+
+int lustre_lnet_nid_descr2str(struct lnet_ud_nid_descr *d,
+ char *str, size_t size)
+{
+ int left = size;
+ int len;
+ char *net;
+ bool addr_found = false;
+
+ /* criteria not defined */
+ if (d->ud_net_id.udn_net_type == 0) {
+ strncat(str, "NA", left - 1);
+ return 0;
+ }
+
+ left = cfs_expr2str(&d->ud_addr_range, str, left);
+ if (left < 0)
+ return left;
+ net = libcfs_net2str(LNET_MKNET(d->ud_net_id.udn_net_type, 0));
+ if (left < size) {
+ len = strlen(net) + 2; /* account for @ and NULL termination */
+ addr_found = true;
+ } else {
+ len = strlen(net) + 1; /* account for NULL termination */
+ }
+
+ if (left - len < 0)
+ return -ENOBUFS;
+
+ if (addr_found) {
+ strncat(str, "@", left);
+ left -= 1;
+ }
+
+ strncat(str, net, left);
+
+ left -= strlen(net) + 1;
+
+ left = cfs_expr2str(&d->ud_net_id.udn_net_num_range, str, left);
+ if (left < 0)
+ return left;
+
+ return 0;
+}
+
+int yaml_add_udsp_action(struct cYAML *y, struct lnet_udsp *udsp)
+{
+ struct cYAML *action;
+
+ switch (udsp->udsp_action_type) {
+ case EN_LNET_UDSP_ACTION_PRIORITY:
+ action = cYAML_create_object(y, "action");
+ if (!action)
+ return -ENOMEM;
+ if (!cYAML_create_number(action, "priority",
+ udsp->udsp_action.udsp_priority))
+ return -ENOMEM;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+int lustre_lnet_show_udsp(int idx, int seq_no, struct cYAML **show_rc,
+ struct cYAML **err_rc)
+{
+ struct lnet_ioctl_udsp *data = NULL;
+ char *ioctl_buf = NULL;
+ struct lnet_ioctl_udsp get_size;
+ int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i;
+ int l_errno = 0;
+ int use_idx = 0;
+ struct cYAML *root = NULL, *udsp_node = NULL,
+ *first_seq = NULL;
+ struct cYAML *item = NULL;
+ char err_str[LNET_MAX_STR_LEN];
+ char tmp[LNET_MAX_STR_LEN];
+ struct lnet_udsp *udsp = NULL;
+ bool exist = false;
+
+ snprintf(err_str, sizeof(err_str), "\"out of memory\"");
+
+ root = cYAML_create_object(NULL, NULL);
+ if (!root)
+ goto out;
+
+ udsp_node = cYAML_create_seq(root, "udsp");
+ if (!udsp_node)
+ goto out;
+
+ for (i = 0;; i++) {
+ data = NULL;
+ ioctl_buf = NULL;
+ udsp = NULL;
+
+ LIBCFS_IOC_INIT_V2(get_size, iou_hdr);
+ if (idx != -1)
+ use_idx = idx;
+ else
+ use_idx = i;
+
+ get_size.iou_idx = use_idx;
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_UDSP_SIZE, &get_size);
+ if (rc != 0) {
+ l_errno = errno;
+ break;
+ }
+
+ ioctl_buf = calloc(get_size.iou_idx, 1);
+ if (!ioctl_buf) {
+ l_errno = errno;
+ break;
+ }
+
+ data = (struct lnet_ioctl_udsp *)ioctl_buf;
+
+ LIBCFS_IOC_INIT_V2(*data, iou_hdr);
+ data->iou_bulk_size = get_size.iou_idx - sizeof(*data);
+ data->iou_bulk = ioctl_buf + sizeof(*data);
+ data->iou_idx = use_idx;
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_UDSP, ioctl_buf);
+ if (rc != 0) {
+ l_errno = errno;
+ break;
+ }
+
+ udsp = lnet_udsp_demarshal(ioctl_buf,
+ data->iou_hdr.ioc_len + data->iou_bulk_size);
+ if (!udsp) {
+ l_errno = -EFAULT;
+ break;
+ }
+
+ rc = -EINVAL;
+ exist = true;
+
+ /* create the tree to be printed. */
+ item = cYAML_create_seq_item(udsp_node);
+ if (item == NULL)
+ goto out;
+
+ if (!first_seq)
+ first_seq = item;
+
+ if (cYAML_create_number(item, "idx",
+ udsp->udsp_idx) == NULL)
+ goto out;
+
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ rc = lustre_lnet_nid_descr2str(&udsp->udsp_src, tmp,
+ LNET_MAX_STR_LEN);
+
+ if (rc)
+ goto out;
+
+ if (cYAML_create_string(item, "src", tmp) == NULL)
+ goto out;
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ rc = lustre_lnet_nid_descr2str(&udsp->udsp_dst, tmp,
+ LNET_MAX_STR_LEN);
+
+ if (rc)
+ goto out;
+
+ if (cYAML_create_string(item, "dst", tmp) == NULL)
+ goto out;
+
+ memset(tmp, 0, LNET_MAX_STR_LEN);
+ rc = lustre_lnet_nid_descr2str(&udsp->udsp_rte, tmp,
+ LNET_MAX_STR_LEN);
+
+ if (rc)
+ goto out;
+
+ if (cYAML_create_string(item, "rte", tmp) == NULL)
+ goto out;
+
+ if (yaml_add_udsp_action(item, udsp))
+ goto out;
+
+ if (ioctl_buf)
+ free(ioctl_buf);
+ if (udsp)
+ lnet_udsp_free(udsp, true);
+ /* did we show the given index? */
+ if (idx != -1)
+ break;
+ }
+
+ /* Print out the net information only if show_rc is not provided */
+ if (show_rc == NULL)
+ cYAML_print_tree(root);
+
+ if (l_errno != ENOENT) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"cannot get udsp: %s\"",
+ strerror(l_errno));
+ rc = -l_errno;
+ goto out;
+ } else {
+ rc = LUSTRE_CFG_RC_NO_ERR;
+ }
+
+ snprintf(err_str, sizeof(err_str), "\"success\"");
+out:
+ if (ioctl_buf)
+ free(ioctl_buf);
+ if (udsp)
+ lnet_udsp_free(udsp, true);
+
+ if (show_rc == NULL || rc != LUSTRE_CFG_RC_NO_ERR || !exist) {
+ cYAML_free_tree(root);
+ } else if (show_rc != NULL && *show_rc != NULL) {
+ struct cYAML *show_node;
+ /* find the net node, if one doesn't exist
+ * then insert one. Otherwise add to the one there
+ */
+ show_node = cYAML_get_object_item(*show_rc, "udsp");
+ if (show_node != NULL && cYAML_is_sequence(show_node)) {
+ cYAML_insert_child(show_node, first_seq);
+ free(udsp_node);
+ free(root);
+ } else if (show_node == NULL) {
+ cYAML_insert_sibling((*show_rc)->cy_child,
+ udsp_node);
+ free(root);
+ } else {
+ cYAML_free_tree(root);
+ }
+ } else {
+ *show_rc = root;
+ }
+
+ cYAML_build_error(rc, seq_no, SHOW_CMD, "udsp", err_str, err_rc);
+
+ return rc;
+}
+
static int jt_show_peer(int argc, char **argv);
static int jt_show_recovery(int argc, char **argv);
static int jt_show_global(int argc, char **argv);
+static int jt_show_udsp(int argc, char **argv);
static int jt_set_tiny(int argc, char **argv);
static int jt_set_small(int argc, char **argv);
static int jt_set_large(int argc, char **argv);
"\t By default, appends to the end of the rule list.\n"},
{"del", jt_del_udsp, 0, "delete a udsp\n"
"\t--idx: index of the Policy.\n"},
+ {"show", jt_show_udsp, 0, "show udsps\n"
+ "\t --idx: index of the policy to show.\n"},
{ 0, 0, 0, NULL }
};
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;
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);