*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* lnet/lnet/nidstrings.c
*
#define DEBUG_SUBSYSTEM S_LNET
+#include <linux/sunrpc/addr.h>
#include <libcfs/libcfs.h>
#include <uapi/linux/lnet/nidstr.h>
+#include <lnet/lib-types.h>
/* max value for numeric network address */
#define MAX_NUMERIC_VALUE 0xffffffff
(addr >> 8) & 0xff, addr & 0xff);
}
+static void
+libcfs_ip_addr2str_size(const __be32 *addr, size_t asize,
+ char *str, size_t size)
+{
+ struct sockaddr_storage sa = {};
+
+ switch (asize) {
+ case 4:
+ sa.ss_family = AF_INET;
+ memcpy(&((struct sockaddr_in *)(&sa))->sin_addr.s_addr,
+ addr, asize);
+ break;
+ case 16:
+ sa.ss_family = AF_INET6;
+ memcpy(&((struct sockaddr_in6 *)(&sa))->sin6_addr.s6_addr,
+ addr, asize);
+ break;
+ default:
+ return;
+ }
+
+ rpc_ntop((struct sockaddr *)&sa, str, size);
+}
+
/* CAVEAT EMPTOR XscanfX
* I use "%n" at the end of a sscanf format to detect trailing junk. However
* sscanf may return immediately if it sees the terminating '0' in a string, so
return 0;
}
+static int
+libcfs_ip_str2addr_size(const char *str, int nob,
+ __be32 *addr, size_t *alen)
+{
+ struct sockaddr_storage sa;
+
+ /* Note: 'net' arg to rpc_pton is only needed for link-local
+ * addresses. Such addresses would not work with LNet routing,
+ * so we can assume they aren't used. So it doesn't matter
+ * which net namespace is passed.
+ */
+ if (rpc_pton(&init_net, str, nob,
+ (struct sockaddr *)&sa, sizeof(sa)) == 0)
+ return 0;
+ if (sa.ss_family == AF_INET6) {
+ memcpy(addr,
+ &((struct sockaddr_in6 *)(&sa))->sin6_addr.s6_addr,
+ 16);
+ *alen = 16;
+ return 1;
+ }
+ if (sa.ss_family == AF_INET) {
+ memcpy(addr,
+ &((struct sockaddr_in *)(&sa))->sin_addr.s_addr,
+ 4);
+ *alen = 4;
+ return 1;
+ }
+ return 0;
+}
+
+
/* Used by lnet/config.c so it can't be static */
int
cfs_ip_addr_parse(char *str, int len, struct list_head *list)
.nf_name = "tcp",
.nf_modname = "ksocklnd",
.nf_addr2str = libcfs_ip_addr2str,
+ .nf_addr2str_size = libcfs_ip_addr2str_size,
.nf_str2addr = libcfs_ip_str2addr,
+ .nf_str2addr_size = libcfs_ip_str2addr_size,
.nf_parse_addrlist = cfs_ip_addr_parse,
.nf_print_addrlist = libcfs_ip_addr_range_print,
.nf_match_addr = cfs_ip_addr_match
}
int
-cfs_match_nid_net(lnet_nid_t nid, __u32 net_type,
- struct list_head *net_num_list,
- struct list_head *addr)
+cfs_match_nid_net(struct lnet_nid *nid, __u32 net_type,
+ struct list_head *net_num_list,
+ struct list_head *addr)
{
__u32 address;
struct netstrfns *nf;
if (!addr || !net_num_list)
return 0;
- nf = type2net_info(LNET_NETTYP(LNET_NIDNET(nid)));
+ nf = type2net_info(LNET_NETTYP(LNET_NID_NET(nid)));
if (!nf || !net_num_list || !addr)
return 0;
- address = LNET_NIDADDR(nid);
+ /* FIXME handle long-addr nid */
+ address = LNET_NIDADDR(lnet_nid_to_nid4(nid));
/* if either the address or net number don't match then no match */
if (!nf->nf_match_addr(address, addr) ||
- !cfs_match_net(LNET_NIDNET(nid), net_type, net_num_list))
+ !cfs_match_net(LNET_NID_NET(nid), net_type, net_num_list))
return 0;
return 1;
}
EXPORT_SYMBOL(libcfs_nid2str_r);
+char *
+libcfs_nidstr_r(const struct lnet_nid *nid, char *buf, size_t buf_size)
+{
+ __u32 nnum = be16_to_cpu(nid->nid_num);
+ __u32 lnd = nid->nid_type;
+ struct netstrfns *nf;
+
+ if (LNET_NID_IS_ANY(nid)) {
+ strncpy(buf, "<?>", buf_size);
+ buf[buf_size - 1] = '\0';
+ return buf;
+ }
+
+ nf = libcfs_lnd2netstrfns(lnd);
+ if (nf) {
+ size_t addr_len;
+
+ if (nf->nf_addr2str_size)
+ nf->nf_addr2str_size(nid->nid_addr, NID_ADDR_BYTES(nid),
+ buf, buf_size);
+ else
+ nf->nf_addr2str(ntohl(nid->nid_addr[0]), buf, buf_size);
+ addr_len = strlen(buf);
+ if (nnum == 0)
+ snprintf(buf + addr_len, buf_size - addr_len, "@%s",
+ nf->nf_name);
+ else
+ snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
+ nf->nf_name, nnum);
+ } else {
+ int l = 0;
+ int words = DIV_ROUND_UP(NID_ADDR_BYTES(nid), 4);
+ int i;
+
+ for (i = 0; i < words && i < 4; i++)
+ l = snprintf(buf+l, buf_size-l, "%s%x",
+ i ? ":" : "", ntohl(nid->nid_addr[i]));
+ snprintf(buf+l, buf_size-l, "@<%u:%u>", lnd, nnum);
+ }
+
+ return buf;
+}
+EXPORT_SYMBOL(libcfs_nidstr_r);
+
static struct netstrfns *
libcfs_str2net_internal(const char *str, __u32 *net)
{
}
EXPORT_SYMBOL(libcfs_str2nid);
+int
+libcfs_strnid(struct lnet_nid *nid, const char *str)
+{
+ const char *sep = strchr(str, '@');
+ struct netstrfns *nf;
+ __u32 net;
+
+ if (sep != NULL) {
+ nf = libcfs_str2net_internal(sep + 1, &net);
+ if (nf == NULL)
+ return -EINVAL;
+ } else {
+ sep = str + strlen(str);
+ net = LNET_MKNET(SOCKLND, 0);
+ nf = libcfs_lnd2netstrfns(SOCKLND);
+ LASSERT(nf != NULL);
+ }
+
+ memset(nid, 0, sizeof(*nid));
+ nid->nid_type = LNET_NETTYP(net);
+ nid->nid_num = htons(LNET_NETNUM(net));
+ if (nf->nf_str2addr_size) {
+ size_t asize = 0;
+
+ if (!nf->nf_str2addr_size(str, (int)(sep - str),
+ nid->nid_addr, &asize))
+ return -EINVAL;
+ nid->nid_size = asize - 4;
+ } else {
+ __u32 addr;
+
+ if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
+ return -EINVAL;
+ nid->nid_addr[0] = htonl(addr);
+ nid->nid_size = 0;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(libcfs_strnid);
+
char *
libcfs_id2str(struct lnet_process_id id)
{
}
EXPORT_SYMBOL(libcfs_id2str);
+char *
+libcfs_idstr(struct lnet_processid *id)
+{
+ char *str = libcfs_next_nidstring();
+
+ if (id->pid == LNET_PID_ANY) {
+ snprintf(str, LNET_NIDSTR_SIZE,
+ "LNET_PID_ANY-%s", libcfs_nidstr(&id->nid));
+ return str;
+ }
+
+ snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
+ ((id->pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
+ (id->pid & ~LNET_PID_USERFLAG), libcfs_nidstr(&id->nid));
+ return str;
+}
+EXPORT_SYMBOL(libcfs_idstr);
+
int
libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
{