* \retval 0 if \a str parsed to numeric address
* \retval errno otherwise
*/
-static int
+int
libcfs_num_parse(char *str, int len, struct list_head *list)
{
struct cfs_expr_list *el;
return 0;
}
+static __u32
+libcfs_net_str_len(const char *str)
+{
+ int i;
+ struct netstrfns *nf = NULL;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++) {
+ nf = &libcfs_netstrfns[i];
+ if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
+ return strlen(nf->nf_name);
+ }
+
+ return 0;
+}
+
+int
+parse_net_range(char *str, __u32 len, struct list_head *net_num,
+ __u32 *net_type)
+{
+ struct cfs_lstr next;
+ __u32 net_type_len;
+ __u32 net;
+ char *bracket;
+ char *star;
+
+ if (!str)
+ return -EINVAL;
+
+ next.ls_str = str;
+ next.ls_len = len;
+
+ net_type_len = libcfs_net_str_len(str);
+
+ if (net_type_len < len) {
+ char c = str[net_type_len];
+
+ str[net_type_len] = '\0';
+ net = libcfs_str2net(str);
+ str[net_type_len] = c;
+ } else {
+ net = libcfs_str2net(str);
+ }
+
+ if (net == LNET_NIDNET(LNET_NID_ANY))
+ return -EINVAL;
+
+ *net_type = LNET_NETTYP(net);
+
+ /*
+ * the net is either followed with an absolute number, *, or an
+ * expression enclosed in []
+ */
+ bracket = strchr(next.ls_str, '[');
+ star = strchr(next.ls_str, '*');
+
+ /* "*[" pattern not allowed */
+ if (bracket && star && star < bracket)
+ return -EINVAL;
+
+ if (!bracket) {
+ next.ls_str = str + net_type_len;
+ next.ls_len = strlen(next.ls_str);
+ } else {
+ next.ls_str = bracket;
+ next.ls_len = strlen(bracket);
+ }
+
+ /* if there is no net number just return */
+ if (next.ls_len == 0)
+ return 0;
+
+ return libcfs_num_parse(next.ls_str, next.ls_len,
+ net_num);
+}
+
+int
+parse_address(struct cfs_lstr *src, const __u32 net_type,
+ struct list_head *addr)
+{
+ int i;
+ struct netstrfns *nf = NULL;
+
+ for (i = 0; i < libcfs_nnetstrfns; i++) {
+ nf = &libcfs_netstrfns[i];
+ if (net_type == nf->nf_type)
+ return nf->nf_parse_addrlist(src->ls_str, src->ls_len,
+ addr);
+ }
+
+ return -EINVAL;
+}
+
+int
+cfs_parse_nid_parts(char *str, struct list_head *addr,
+ struct list_head *net_num, __u32 *net_type)
+{
+ struct cfs_lstr next;
+ struct cfs_lstr addrrange;
+ bool found = false;
+ int rc;
+
+ if (!str)
+ return -EINVAL;
+
+ next.ls_str = str;
+ next.ls_len = strlen(str);
+
+ rc = cfs_gettok(&next, '@', &addrrange);
+ if (!rc)
+ return -EINVAL;
+
+ if (!next.ls_str) {
+ /* only net is present */
+ next.ls_str = str;
+ next.ls_len = strlen(str);
+ } else {
+ found = true;
+ }
+
+ /* assume only net is present */
+ rc = parse_net_range(next.ls_str, next.ls_len, net_num, net_type);
+
+ /*
+ * if we successfully parsed the net range and there is no
+ * address, or if we fail to parse the net range then return
+ */
+ if ((!rc && !found) || rc)
+ return rc;
+
+ return parse_address(&addrrange, *net_type, addr);
+}
+
/**
* Frees addrrange structures of \a list.
*
__u32 libcfs_str2net(const char *str);
lnet_nid_t libcfs_str2nid(const char *str);
int libcfs_str2anynid(lnet_nid_t *nid, const char *str);
+int libcfs_num_parse(char *str, int len, struct list_head *list);
char *libcfs_id2str(struct lnet_process_id id);
void cfs_free_nidlist(struct list_head *list);
int cfs_parse_nidlist(char *str, int len, struct list_head *list);
+int cfs_parse_nid_parts(char *str, struct list_head *addr,
+ struct list_head *net_num, __u32 *net_type);
int cfs_print_nidlist(char *buffer, int count, struct list_head *list);
int cfs_match_nid(lnet_nid_t nid, struct list_head *list);
int cfs_expand_nidlist(struct list_head *nidlist, lnet_nid_t *lnet_nidlist,
int cfs_ip_addr_match(__u32 addr, struct list_head *list);
int cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
char *max_nid, __kernel_size_t nidstr_length);
+void cfs_expr_list_free_list(struct list_head *list);
struct netstrfns {
__u32 nf_type;
* \retval 0 if \a str parsed to numeric address
* \retval errno otherwise
*/
-static int
+int
libcfs_num_parse(char *str, int len, struct list_head *list)
{
struct cfs_expr_list *el;
#include <glob.h>
#include <libcfs/util/param.h>
-#define CONFIG_CMD "configure"
-#define UNCONFIG_CMD "unconfigure"
-#define ADD_CMD "add"
-#define DEL_CMD "del"
-#define SHOW_CMD "show"
-#define DBG_CMD "dbg"
-#define MANAGE_CMD "manage"
-
-#define MAX_NUM_IPS 128
-
-#define modparam_path "/sys/module/lnet/parameters/"
-#define o2ib_modparam_path "/sys/module/ko2iblnd/parameters/"
-#define gni_nid_path "/proc/cray_xt/"
-
#ifndef HAVE_USRSPC_RDMA_PS_TCP
#define RDMA_PS_TCP 0x0106
#endif
show_rc, err_rc);
}
+static int handle_yaml_config_udsp(struct cYAML *tree, struct cYAML **show_rc,
+ struct cYAML **err_rc)
+{
+ struct cYAML *seq_no, *src, *rte, *dst, *prio, *idx;
+ union lnet_udsp_action action;
+
+ seq_no = cYAML_get_object_item(tree, "seq_no");
+ src = cYAML_get_object_item(tree, "src");
+ rte = cYAML_get_object_item(tree, "rte");
+ dst = cYAML_get_object_item(tree, "dst");
+ prio = cYAML_get_object_item(tree, "priority");
+ idx = cYAML_get_object_item(tree, "idx");
+
+ action.udsp_priority = prio ? prio->cy_valueint : -1;
+
+ return lustre_lnet_add_udsp(src ? src->cy_valuestring : NULL,
+ dst ? dst->cy_valuestring : NULL,
+ rte ? rte->cy_valuestring : NULL,
+ prio ? "priority" : "",
+ &action,
+ idx ? idx->cy_valueint : -1,
+ seq_no ? seq_no->cy_valueint : -1,
+ 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_config_numa },
{ .name = "ping", .cb = handle_yaml_no_op },
{ .name = "discover", .cb = handle_yaml_no_op },
+ { .name = "udsp", .cb = handle_yaml_config_udsp },
{ .name = NULL } };
static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
#define LUSTRE_CFG_RC_MATCH -7
#define LUSTRE_CFG_RC_SKIP -8
#define LUSTRE_CFG_RC_LAST_ELEM -9
+#define LUSTRE_CFG_RC_MARSHAL_FAIL -10
+
+#define CONFIG_CMD "configure"
+#define UNCONFIG_CMD "unconfigure"
+#define ADD_CMD "add"
+#define DEL_CMD "del"
+#define SHOW_CMD "show"
+#define DBG_CMD "dbg"
+#define MANAGE_CMD "manage"
+
+#define MAX_NUM_IPS 128
+
+#define modparam_path "/sys/module/lnet/parameters/"
+#define o2ib_modparam_path "/sys/module/ko2iblnd/parameters/"
+#define gni_nid_path "/proc/cray_xt/"
enum lnetctl_cmd {
LNETCTL_CONFIG_CMD = 1,
} udsp_action;
};
+/* This union is passed from lnetctl to fill the action union in udsp
+ * structure
+ * TODO: The idea here is if we add extra actions, ex: drop, it can be
+ * added to the union
+ */
+union lnet_udsp_action {
+ int udsp_priority;
+};
+
/* forward declaration of the cYAML structure. */
struct cYAML;
int lustre_lnet_parse_nidstr(char *nidstr, lnet_nid_t *lnet_nidlist,
int max_nids, char *err_str);
+/* lustre_lnet_add_udsp
+ * Add a selection policy.
+ * src - source NID descriptor
+ * dst - destination NID descriptor
+ * rte - router NID descriptor
+ * type - action type
+ * action - union of the action
+ * idx - the index to delete
+ * seq_no - sequence number of the request
+ * err_rc - [OUT] struct cYAML tree describing the error. Freed by
+ * caller
+ */
+int lustre_lnet_add_udsp(char *src, char *dst, char *rte, char *type,
+ union lnet_udsp_action *action, int idx,
+ int seq_no, struct cYAML **err_rc);
+
#endif /* LIB_LNET_CONFIG_API_H */
#include <sys/types.h>
#include <fcntl.h>
#include <ctype.h>
+#include <linux/lnet/lnet-dlc.h>
#include "liblnetconfig.h"
static inline bool
return 0;
}
-int
+static int
lnet_udsp_marshal(struct lnet_udsp *udsp, void *bulk,
__s32 bulk_size)
{
return rc;
}
+static enum lnet_udsp_action_type
+lnet_str2udsp_action(char *type)
+{
+ if (!type)
+ return EN_LNET_UDSP_ACTION_NONE;
+
+ if (!strncmp(type, "priority", strlen("priority")))
+ return EN_LNET_UDSP_ACTION_PRIORITY;
+
+ if (!strncmp(type, "pref", strlen("pref")))
+ return EN_LNET_UDSP_ACTION_PREFERRED_LIST;
+
+ return EN_LNET_UDSP_ACTION_NONE;
+}
+
+int lustre_lnet_add_udsp(char *src, char *dst, char *rte,
+ char *type, union lnet_udsp_action *action,
+ int idx, int seq_no, struct cYAML **err_rc)
+{
+ struct lnet_udsp *udsp = NULL;
+ struct lnet_ioctl_udsp *udsp_bulk;
+ int rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ void *bulk = NULL;
+ __u32 bulk_size;
+ char err_str[LNET_MAX_STR_LEN];
+ enum lnet_udsp_action_type action_type;
+
+ snprintf(err_str, sizeof(err_str), "\"success\"");
+
+ action_type = lnet_str2udsp_action(type);
+ if (action_type == EN_LNET_UDSP_ACTION_NONE) {
+ snprintf(err_str, sizeof(err_str),
+ "\"bad action type specified: %s\"", type);
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
+ }
+
+ /* sanitize parameters:
+ * src-dst can be simultaneously present
+ * dst-rte can be simultaneously present
+ */
+ if ((!src && !rte && !dst) ||
+ (src && rte && dst) ||
+ (src && rte && !dst)) {
+ snprintf(err_str, sizeof(err_str),
+ "\"The combination of src, dst and rte is not supported\"");
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
+ }
+
+ udsp = lnet_udsp_alloc();
+ if (!udsp) {
+ snprintf(err_str, sizeof(err_str), "\"out of memory\"");
+ goto out;
+ }
+
+ udsp->udsp_idx = idx;
+ udsp->udsp_action_type = action_type;
+
+ /* a priority of -1 will result in the lowest possible priority */
+ if (action_type == EN_LNET_UDSP_ACTION_PRIORITY)
+ udsp->udsp_action.udsp_priority = action->udsp_priority;
+
+ /* override with the default
+ * if priority is expected, but not specified
+ */
+ if (!rte && ((dst && !src) || (src && !dst)) &&
+ action_type != EN_LNET_UDSP_ACTION_PRIORITY) {
+ udsp->udsp_action_type = EN_LNET_UDSP_ACTION_PRIORITY;
+ udsp->udsp_action.udsp_priority = 0;
+ }
+
+ if (src) {
+ rc = cfs_parse_nid_parts(src, &udsp->udsp_src.ud_addr_range,
+ &udsp->udsp_src.ud_net_id.udn_net_num_range,
+ &udsp->udsp_src.ud_net_id.udn_net_type);
+ if (rc < 0) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\failed to parse src parameter\"");
+ goto out;
+ }
+ }
+ if (dst) {
+ rc = cfs_parse_nid_parts(dst, &udsp->udsp_dst.ud_addr_range,
+ &udsp->udsp_dst.ud_net_id.udn_net_num_range,
+ &udsp->udsp_dst.ud_net_id.udn_net_type);
+ if (rc < 0) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\failed to parse dst parameter\"");
+ goto out;
+ }
+ }
+ if (rte) {
+ rc = cfs_parse_nid_parts(rte, &udsp->udsp_rte.ud_addr_range,
+ &udsp->udsp_rte.ud_net_id.udn_net_num_range,
+ &udsp->udsp_rte.ud_net_id.udn_net_type);
+ if (rc < 0) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\failed to parse rte parameter\"");
+ goto out;
+ }
+ }
+
+ bulk_size = lnet_get_udsp_size(udsp);
+ bulk = calloc(1, bulk_size);
+ if (!bulk) {
+ rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ snprintf(err_str, sizeof(err_str), "\"out of memory\"");
+ goto out;
+ }
+
+ udsp_bulk = bulk;
+ LIBCFS_IOC_INIT_V2(*udsp_bulk, iou_hdr);
+ udsp_bulk->iou_hdr.ioc_len = bulk_size;
+ udsp_bulk->iou_bulk_size = bulk_size - sizeof(*udsp_bulk);
+
+ rc = lnet_udsp_marshal(udsp, bulk, bulk_size);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ rc = LUSTRE_CFG_RC_MARSHAL_FAIL;
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"failed to marshal udsp\"");
+ goto out;
+ }
+
+ udsp_bulk->iou_bulk = bulk + sizeof(*udsp_bulk);
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_UDSP, bulk);
+ if (rc < 0) {
+ rc = errno;
+ snprintf(err_str, sizeof(err_str),
+ "\"cannot add udsp: %s\"", strerror(errno));
+ goto out;
+ }
+
+ rc = LUSTRE_CFG_RC_NO_ERR;
+
+out:
+ if (bulk)
+ free(bulk);
+ if (udsp)
+ lnet_udsp_free(udsp, false);
+ cYAML_build_error(rc, seq_no, ADD_CMD, "udsp", err_str, err_rc);
+ return rc;
+}
static int jt_set_discovery(int argc, char **argv);
static int jt_set_drop_asym_route(int argc, char **argv);
static int jt_list_peer(int argc, char **argv);
+static int jt_add_udsp(int argc, char **argv);
/*static int jt_show_peer(int argc, char **argv);*/
static int lnetctl_list_commands(int argc, char **argv);
static int jt_import(int argc, char **argv);
static int jt_set_peer_ni_value(int argc, char **argv);
static int jt_calc_service_id(int argc, char **argv);
static int jt_set_response_tracking(int argc, char **argv);
+static int jt_udsp(int argc, char **argv);
command_t cmd_list[] = {
{"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"},
{"ping", jt_ping, 0, "ping nid,[nid,...]"},
{"discover", jt_discover, 0, "discover nid[,nid,...]"},
{"service-id", jt_calc_service_id, 0, "Calculate IB Lustre service ID\n"},
+ {"udsp", jt_udsp, 0, "udsp {add | help}"},
{"help", Parser_help, 0, "help"},
{"exit", Parser_quit, 0, "quit"},
{"quit", Parser_quit, 0, "quit"},
{ 0, 0, 0, NULL }
};
+command_t udsp_cmds[] = {
+ {"add", jt_add_udsp, 0, "add a udsp\n"
+ "\t--src: ip2nets syntax specifying the local NID to match\n"
+ "\t--dst: ip2nets syntax specifying the remote NID to match\n"
+ "\t--rte: ip2nets syntax specifying the router NID to match\n"
+ "\t--priority: priority value (0 - highest priority)\n"
+ "\t--idx: index of where to insert the rule.\n"
+ "\t By default, appends to the end of the rule list.\n"},
+ { 0, 0, 0, NULL }
+};
+
static int jt_calc_service_id(int argc, char **argv)
{
int 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;
return rc;
}
+static int jt_add_udsp(int argc, char **argv)
+{
+ char *src = NULL, *dst = NULL, *rte = NULL;
+ struct cYAML *err_rc = NULL;
+ union lnet_udsp_action udsp_action;
+ long int idx = -1, priority = -1;
+ int opt, rc = 0;
+ char *action_type = "pref";
+
+ const char *const short_options = "s:d:r:p:i:";
+ static const struct option long_options[] = {
+ { .name = "src", .has_arg = required_argument, .val = 's' },
+ { .name = "dst", .has_arg = required_argument, .val = 'd' },
+ { .name = "rte", .has_arg = required_argument, .val = 'r' },
+ { .name = "priority", .has_arg = required_argument, .val = 'p' },
+ { .name = "idx", .has_arg = required_argument, .val = 'i' },
+ { .name = NULL } };
+
+ rc = check_cmd(udsp_cmds, "udsp", "add", 0, argc, argv);
+ if (rc)
+ return rc;
+
+ while ((opt = getopt_long(argc, argv, short_options,
+ long_options, NULL)) != -1) {
+ switch (opt) {
+ case 's':
+ src = optarg;
+ break;
+ case 'd':
+ dst = optarg;
+ break;
+ case 'r':
+ rte = optarg;
+ break;
+ case 'p':
+ rc = parse_long(optarg, &priority);
+ if (rc != 0)
+ priority = -1;
+ action_type = "priority";
+ udsp_action.udsp_priority = priority;
+ break;
+ case 'i':
+ rc = parse_long(optarg, &idx);
+ if (rc != 0)
+ idx = 0;
+ break;
+ case '?':
+ print_help(udsp_cmds, "udsp", "add");
+ default:
+ return 0;
+ }
+ }
+
+ rc = lustre_lnet_add_udsp(src, dst, rte, action_type, &udsp_action,
+ idx, -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 lnetctl_list_commands(int argc, char **argv)
{
char buffer[81] = ""; /* 80 printable chars + terminating NUL */