1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
5 * Author: Phil Schwan <phil@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 # define EXPORT_SYMTAB
27 #define DEBUG_SUBSYSTEM S_LNET
29 #include <lnet/lnet.h>
30 #include <libcfs/kp30.h>
32 #ifdef HAVE_GETHOSTBYNAME
37 /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
38 * consistent in all conversion functions. Some code fragments are copied
39 * around for the sake of clarity...
42 /* CAVEAT EMPTOR! Racey temporary buffer allocation!
43 * Choose the number of nidstrings to support the MAXIMUM expected number of
44 * concurrent users. If there are more, the returned string will be volatile.
45 * NB this number must allow for a process to be descheduled for a timeslice
46 * between getting its string and using it.
49 #define LNET_NIDSTR_COUNT 128 /* # of nidstrings */
50 #define LNET_NIDSTR_SIZE 32 /* size of each one (see below for usage) */
52 static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
53 static int libcfs_nidstring_idx = 0;
56 static spinlock_t libcfs_nidstring_lock;
58 void libcfs_init_nidstrings (void)
60 spin_lock_init(&libcfs_nidstring_lock);
63 # define NIDSTR_LOCK(f) spin_lock_irqsave(&libcfs_nidstring_lock, f)
64 # define NIDSTR_UNLOCK(f) spin_unlock_irqrestore(&libcfs_nidstring_lock, f)
66 # define NIDSTR_LOCK(f) (f=0) /* avoid unused var warnings */
67 # define NIDSTR_UNLOCK(f) (f=0)
71 libcfs_next_nidstring (void)
78 str = libcfs_nidstrings[libcfs_nidstring_idx++];
79 if (libcfs_nidstring_idx ==
80 sizeof(libcfs_nidstrings)/sizeof(libcfs_nidstrings[0]))
81 libcfs_nidstring_idx = 0;
87 static int libcfs_lo_str2addr(char *str, int nob, __u32 *addr);
88 static void libcfs_ip_addr2str(__u32 addr, char *str);
89 static int libcfs_ip_str2addr(char *str, int nob, __u32 *addr);
90 static void libcfs_decnum_addr2str(__u32 addr, char *str);
91 static void libcfs_hexnum_addr2str(__u32 addr, char *str);
92 static int libcfs_num_str2addr(char *str, int nob, __u32 *addr);
98 void (*nf_addr2str)(__u32 addr, char *str);
99 int (*nf_str2addr)(char *str, int nob, __u32 *addr);
102 static struct netstrfns libcfs_netstrfns[] = {
103 {/* .nf_type */ LOLND,
105 /* .nf_modname */ "klolnd",
106 /* .nf_addr2str */ libcfs_decnum_addr2str,
107 /* .nf_str2addr */ libcfs_lo_str2addr},
108 {/* .nf_type */ SOCKLND,
109 /* .nf_name */ "tcp",
110 /* .nf_modname */ "ksocklnd",
111 /* .nf_addr2str */ libcfs_ip_addr2str,
112 /* .nf_str2addr */ libcfs_ip_str2addr},
113 {/* .nf_type */ O2IBLND,
114 /* .nf_name */ "o2ib",
115 /* .nf_modname */ "ko2iblnd",
116 /* .nf_addr2str */ libcfs_ip_addr2str,
117 /* .nf_str2addr */ libcfs_ip_str2addr},
118 {/* .nf_type */ CIBLND,
119 /* .nf_name */ "cib",
120 /* .nf_modname */ "kciblnd",
121 /* .nf_addr2str */ libcfs_ip_addr2str,
122 /* .nf_str2addr */ libcfs_ip_str2addr},
123 {/* .nf_type */ OPENIBLND,
124 /* .nf_name */ "openib",
125 /* .nf_modname */ "kopeniblnd",
126 /* .nf_addr2str */ libcfs_ip_addr2str,
127 /* .nf_str2addr */ libcfs_ip_str2addr},
128 {/* .nf_type */ IIBLND,
129 /* .nf_name */ "iib",
130 /* .nf_modname */ "kiiblnd",
131 /* .nf_addr2str */ libcfs_ip_addr2str,
132 /* .nf_str2addr */ libcfs_ip_str2addr},
133 {/* .nf_type */ VIBLND,
134 /* .nf_name */ "vib",
135 /* .nf_modname */ "kviblnd",
136 /* .nf_addr2str */ libcfs_ip_addr2str,
137 /* .nf_str2addr */ libcfs_ip_str2addr},
138 {/* .nf_type */ RALND,
140 /* .nf_modname */ "kralnd",
141 /* .nf_addr2str */ libcfs_ip_addr2str,
142 /* .nf_str2addr */ libcfs_ip_str2addr},
143 {/* .nf_type */ QSWLND,
144 /* .nf_name */ "elan",
145 /* .nf_modname */ "kqswlnd",
146 /* .nf_addr2str */ libcfs_decnum_addr2str,
147 /* .nf_str2addr */ libcfs_num_str2addr},
148 {/* .nf_type */ GMLND,
150 /* .nf_modname */ "kgmlnd",
151 /* .nf_addr2str */ libcfs_hexnum_addr2str,
152 /* .nf_str2addr */ libcfs_num_str2addr},
153 {/* .nf_type */ MXLND,
155 /* .nf_modname */ "kmxlnd",
156 /* .nf_addr2str */ libcfs_ip_addr2str,
157 /* .nf_str2addr */ libcfs_ip_str2addr},
158 {/* .nf_type */ PTLLND,
159 /* .nf_name */ "ptl",
160 /* .nf_modname */ "kptllnd",
161 /* .nf_addr2str */ libcfs_decnum_addr2str,
162 /* .nf_str2addr */ libcfs_num_str2addr},
163 /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */
167 const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
170 libcfs_lo_str2addr(char *str, int nob, __u32 *addr)
177 libcfs_ip_addr2str(__u32 addr, char *str)
179 #if 0 /* never lookup */
180 #if !defined(__KERNEL__) && defined HAVE_GETHOSTBYNAME
181 __u32 netip = htonl(addr);
182 struct hostent *he = gethostbyaddr(&netip, sizeof(netip), AF_INET);
185 snprintf(str, LNET_NIDSTR_SIZE, "%s", he->h_name);
190 snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
191 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
192 (addr >> 8) & 0xff, addr & 0xff);
195 /* CAVEAT EMPTOR XscanfX
196 * I use "%n" at the end of a sscanf format to detect trailing junk. However
197 * sscanf may return immediately if it sees the terminating '0' in a string, so
198 * I initialise the %n variable to the expected length. If sscanf sets it;
199 * fine, if it doesn't, then the scan ended at the end of the string, which is
203 libcfs_ip_str2addr(char *str, int nob, __u32 *addr)
209 int n = nob; /* XscanfX */
212 if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
214 (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
215 (c & ~0xff) == 0 && (d & ~0xff) == 0) {
216 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
220 #if !defined(__KERNEL__) && defined HAVE_GETHOSTBYNAME
221 /* known hostname? */
222 if (('a' <= str[0] && str[0] <= 'z') ||
223 ('A' <= str[0] && str[0] <= 'Z')) {
226 LIBCFS_ALLOC(tmp, nob + 1);
230 memcpy(tmp, str, nob);
233 he = gethostbyname(tmp);
235 LIBCFS_FREE(tmp, nob);
238 __u32 ip = *(__u32 *)he->h_addr;
250 libcfs_decnum_addr2str(__u32 addr, char *str)
252 snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
256 libcfs_hexnum_addr2str(__u32 addr, char *str)
258 snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
262 libcfs_num_str2addr(char *str, int nob, __u32 *addr)
267 if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
271 if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
275 if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
282 libcfs_lnd2netstrfns(int lnd)
287 for (i = 0; i < libcfs_nnetstrfns; i++)
288 if (lnd == libcfs_netstrfns[i].nf_type)
289 return &libcfs_netstrfns[i];
295 libcfs_name2netstrfns(char *name)
299 for (i = 0; i < libcfs_nnetstrfns; i++)
300 if (libcfs_netstrfns[i].nf_type >= 0 &&
301 !strcmp(libcfs_netstrfns[i].nf_name, name))
302 return &libcfs_netstrfns[i];
308 libcfs_isknown_lnd(int type)
310 return libcfs_lnd2netstrfns(type) != NULL;
314 libcfs_lnd2modname(int lnd)
316 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
318 return (nf == NULL) ? NULL : nf->nf_modname;
322 libcfs_lnd2str(int lnd)
325 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
330 str = libcfs_next_nidstring();
331 snprintf(str, LNET_NIDSTR_SIZE, "?%u?", lnd);
336 libcfs_str2lnd(char *str)
338 struct netstrfns *nf = libcfs_name2netstrfns(str);
347 libcfs_net2str(__u32 net)
349 int lnd = LNET_NETTYP(net);
350 int num = LNET_NETNUM(net);
351 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
352 char *str = libcfs_next_nidstring();
355 snprintf(str, LNET_NIDSTR_SIZE, "<%u:%u>", lnd, num);
357 snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name);
359 snprintf(str, LNET_NIDSTR_SIZE, "%s%u", nf->nf_name, num);
365 libcfs_nid2str(lnet_nid_t nid)
367 __u32 addr = LNET_NIDADDR(nid);
368 __u32 net = LNET_NIDNET(nid);
369 int lnd = LNET_NETTYP(net);
370 int nnum = LNET_NETNUM(net);
371 struct netstrfns *nf;
375 if (nid == LNET_NID_ANY)
376 return "LNET_NID_ANY";
378 nf = libcfs_lnd2netstrfns(lnd);
379 str = libcfs_next_nidstring();
382 snprintf(str, LNET_NIDSTR_SIZE, "%x@<%u:%u>", addr, lnd, nnum);
384 nf->nf_addr2str(addr, str);
387 snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s",
390 snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%u",
397 static struct netstrfns *
398 libcfs_str2net_internal(char *str, __u32 *net)
400 struct netstrfns *nf;
405 for (i = 0; i < libcfs_nnetstrfns; i++) {
406 nf = &libcfs_netstrfns[i];
407 if (nf->nf_type >= 0 &&
408 !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
412 if (i == libcfs_nnetstrfns)
415 nob = strlen(nf->nf_name);
417 if (strlen(str) == (unsigned int)nob) {
420 if (nf->nf_type == LOLND) /* net number not allowed */
425 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
426 i != (int)strlen(str))
430 *net = LNET_MKNET(nf->nf_type, netnum);
435 libcfs_str2net(char *str)
439 if (libcfs_str2net_internal(str, &net) != NULL)
442 return LNET_NIDNET(LNET_NID_ANY);
446 libcfs_str2nid(char *str)
448 char *sep = strchr(str, '@');
449 struct netstrfns *nf;
454 nf = libcfs_str2net_internal(sep + 1, &net);
458 sep = str + strlen(str);
459 net = LNET_MKNET(SOCKLND, 0);
460 nf = libcfs_lnd2netstrfns(SOCKLND);
461 LASSERT (nf != NULL);
464 if (!nf->nf_str2addr(str, sep - str, &addr))
467 return LNET_MKNID(net, addr);
471 libcfs_id2str(lnet_process_id_t id)
473 char *str = libcfs_next_nidstring();
475 snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
476 ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
477 (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
482 libcfs_str2anynid(lnet_nid_t *nidp, char *str)
484 if (!strcmp(str, "*")) {
485 *nidp = LNET_NID_ANY;
489 *nidp = libcfs_str2nid(str);
490 return *nidp != LNET_NID_ANY;
495 libcfs_setnet0alias(int lnd)
497 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
498 struct netstrfns *nf0 = &libcfs_netstrfns[libcfs_nnetstrfns - 1];
500 /* Ghastly hack to allow LNET to inter-operate with portals.
501 * NET type 0 becomes an alias for whatever local network we have, and
502 * this assignment here means we can parse and print its NIDs */
504 LASSERT (nf != NULL);
505 LASSERT (nf0->nf_type < 0);
507 nf0->nf_name = "zero";//nf->nf_name;
508 nf0->nf_modname = nf->nf_modname;
509 nf0->nf_addr2str = nf->nf_addr2str;
510 nf0->nf_str2addr = nf->nf_str2addr;
515 EXPORT_SYMBOL(libcfs_isknown_lnd);
516 EXPORT_SYMBOL(libcfs_lnd2modname);
517 EXPORT_SYMBOL(libcfs_lnd2str);
518 EXPORT_SYMBOL(libcfs_str2lnd);
519 EXPORT_SYMBOL(libcfs_net2str);
520 EXPORT_SYMBOL(libcfs_nid2str);
521 EXPORT_SYMBOL(libcfs_str2net);
522 EXPORT_SYMBOL(libcfs_str2nid);
523 EXPORT_SYMBOL(libcfs_id2str);
524 EXPORT_SYMBOL(libcfs_str2anynid);
525 EXPORT_SYMBOL(libcfs_setnet0alias);
526 #else /* __KERNEL__ */
528 libcfs_setnet0alias(int lnd)
530 LCONSOLE_ERROR("Liblustre cannot interoperate with old Portals.\n"
531 "portals_compatibility must be set to 'none'.\n");