4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2014, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * libcfs/libcfs/util/nidstrings.c
38 * Author: Phil Schwan <phil@clusterfs.com>
41 #define DEBUG_SUBSYSTEM S_LNET
50 #include <libcfs/util/string.h>
51 #include <lnet/types.h>
52 #include <lnet/nidstr.h>
57 /* max value for numeric network address */
58 #define MAX_NUMERIC_VALUE 0xffffffff
60 #define IPSTRING_LENGTH 16
62 /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
63 * consistent in all conversion functions. Some code fragments are copied
64 * around for the sake of clarity...
67 /* CAVEAT EMPTOR! Racey temporary buffer allocation!
68 * Choose the number of nidstrings to support the MAXIMUM expected number of
69 * concurrent users. If there are more, the returned string will be volatile.
70 * NB this number must allow for a process to be descheduled for a timeslice
71 * between getting its string and using it.
74 static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
75 static int libcfs_nidstring_idx;
78 libcfs_next_nidstring(void)
82 str = libcfs_nidstrings[libcfs_nidstring_idx++];
83 if (libcfs_nidstring_idx ==
84 sizeof(libcfs_nidstrings)/sizeof(libcfs_nidstrings[0]))
85 libcfs_nidstring_idx = 0;
90 static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr);
91 static void libcfs_ip_addr2str(__u32 addr, char *str, size_t size);
92 static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr);
93 static bool cfs_ip_is_contiguous(struct list_head *nidlist);
94 static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
95 static void libcfs_decnum_addr2str(__u32 addr, char *str, size_t size);
96 static void libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size);
97 static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
98 static int libcfs_num_parse(char *str, int len, struct list_head *list);
99 static int libcfs_num_match(__u32 addr, struct list_head *list);
100 static int libcfs_num_addr_range_print(char *buffer, int count,
101 struct list_head *list);
102 static int libcfs_ip_addr_range_print(char *buffer, int count,
103 struct list_head *list);
104 static bool cfs_num_is_contiguous(struct list_head *nidlist);
105 static void cfs_num_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
107 static struct netstrfns libcfs_netstrfns[] = {
108 {/* .nf_type */ LOLND,
110 /* .nf_modname */ "klolnd",
111 /* .nf_addr2str */ libcfs_decnum_addr2str,
112 /* .nf_str2addr */ libcfs_lo_str2addr,
113 /* .nf_parse_addr*/ libcfs_num_parse,
114 /* .nf_print_addrlist*/ libcfs_num_addr_range_print,
115 /* .nf_match_addr*/ libcfs_num_match,
116 /* .nf_is_contiguous */ cfs_num_is_contiguous,
117 /* .nf_min_max */ cfs_num_min_max},
118 {/* .nf_type */ SOCKLND,
119 /* .nf_name */ "tcp",
120 /* .nf_modname */ "ksocklnd",
121 /* .nf_addr2str */ libcfs_ip_addr2str,
122 /* .nf_str2addr */ libcfs_ip_str2addr,
123 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
124 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
125 /* .nf_match_addr*/ cfs_ip_addr_match,
126 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
127 /* .nf_min_max */ cfs_ip_min_max},
128 {/* .nf_type */ O2IBLND,
129 /* .nf_name */ "o2ib",
130 /* .nf_modname */ "ko2iblnd",
131 /* .nf_addr2str */ libcfs_ip_addr2str,
132 /* .nf_str2addr */ libcfs_ip_str2addr,
133 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
134 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
135 /* .nf_match_addr*/ cfs_ip_addr_match,
136 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
137 /* .nf_min_max */ cfs_ip_min_max},
138 {/* .nf_type */ CIBLND,
139 /* .nf_name */ "cib",
140 /* .nf_modname */ "kciblnd",
141 /* .nf_addr2str */ libcfs_ip_addr2str,
142 /* .nf_str2addr */ libcfs_ip_str2addr,
143 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
144 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
145 /* .nf_match_addr*/ cfs_ip_addr_match,
146 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
147 /* .nf_min_max */ cfs_ip_min_max},
148 {/* .nf_type */ OPENIBLND,
149 /* .nf_name */ "openib",
150 /* .nf_modname */ "kopeniblnd",
151 /* .nf_addr2str */ libcfs_ip_addr2str,
152 /* .nf_str2addr */ libcfs_ip_str2addr,
153 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
154 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
155 /* .nf_match_addr*/ cfs_ip_addr_match,
156 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
157 /* .nf_min_max */ cfs_ip_min_max},
158 {/* .nf_type */ IIBLND,
159 /* .nf_name */ "iib",
160 /* .nf_modname */ "kiiblnd",
161 /* .nf_addr2str */ libcfs_ip_addr2str,
162 /* .nf_str2addr */ libcfs_ip_str2addr,
163 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
164 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
165 /* .nf_match_addr*/ cfs_ip_addr_match,
166 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
167 /* .nf_min_max */ cfs_ip_min_max},
168 {/* .nf_type */ VIBLND,
169 /* .nf_name */ "vib",
170 /* .nf_modname */ "kviblnd",
171 /* .nf_addr2str */ libcfs_ip_addr2str,
172 /* .nf_str2addr */ libcfs_ip_str2addr,
173 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
174 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
175 /* .nf_match_addr*/ cfs_ip_addr_match,
176 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
177 /* .nf_min_max */ cfs_ip_min_max},
178 {/* .nf_type */ RALND,
180 /* .nf_modname */ "kralnd",
181 /* .nf_addr2str */ libcfs_ip_addr2str,
182 /* .nf_str2addr */ libcfs_ip_str2addr,
183 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
184 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
185 /* .nf_match_addr*/ cfs_ip_addr_match,
186 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
187 /* .nf_min_max */ cfs_ip_min_max},
188 {/* .nf_type */ QSWLND,
189 /* .nf_name */ "elan",
190 /* .nf_modname */ "kqswlnd",
191 /* .nf_addr2str */ libcfs_decnum_addr2str,
192 /* .nf_str2addr */ libcfs_num_str2addr,
193 /* .nf_parse_addrlist*/ libcfs_num_parse,
194 /* .nf_print_addrlist*/ libcfs_num_addr_range_print,
195 /* .nf_match_addr*/ libcfs_num_match,
196 /* .nf_is_contiguous */ cfs_num_is_contiguous,
197 /* .nf_min_max */ cfs_num_min_max},
198 {/* .nf_type */ GMLND,
200 /* .nf_modname */ "kgmlnd",
201 /* .nf_addr2str */ libcfs_hexnum_addr2str,
202 /* .nf_str2addr */ libcfs_num_str2addr,
203 /* .nf_parse_addrlist*/ libcfs_num_parse,
204 /* .nf_print_addrlist*/ libcfs_num_addr_range_print,
205 /* .nf_match_addr*/ libcfs_num_match,
206 /* .nf_is_contiguous */ cfs_num_is_contiguous,
207 /* .nf_min_max */ cfs_num_min_max},
208 {/* .nf_type */ MXLND,
210 /* .nf_modname */ "kmxlnd",
211 /* .nf_addr2str */ libcfs_ip_addr2str,
212 /* .nf_str2addr */ libcfs_ip_str2addr,
213 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
214 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
215 /* .nf_match_addr*/ cfs_ip_addr_match,
216 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
217 /* .nf_min_max */ cfs_ip_min_max},
218 {/* .nf_type */ PTLLND,
219 /* .nf_name */ "ptl",
220 /* .nf_modname */ "kptllnd",
221 /* .nf_addr2str */ libcfs_decnum_addr2str,
222 /* .nf_str2addr */ libcfs_num_str2addr,
223 /* .nf_parse_addrlist*/ libcfs_num_parse,
224 /* .nf_print_addrlist*/ libcfs_num_addr_range_print,
225 /* .nf_match_addr*/ libcfs_num_match,
226 /* .nf_is_contiguous */ cfs_num_is_contiguous,
227 /* .nf_min_max */ cfs_num_min_max},
228 {/* .nf_type */ GNILND,
229 /* .nf_name */ "gni",
230 /* .nf_modname */ "kgnilnd",
231 /* .nf_addr2str */ libcfs_decnum_addr2str,
232 /* .nf_str2addr */ libcfs_num_str2addr,
233 /* .nf_parse_addrlist*/ libcfs_num_parse,
234 /* .nf_print_addrlist*/ libcfs_num_addr_range_print,
235 /* .nf_match_addr*/ libcfs_num_match,
236 /* .nf_is_contiguous */ cfs_num_is_contiguous,
237 /* .nf_min_max */ cfs_num_min_max},
238 {/* .nf_type */ GNIIPLND,
239 /* .nf_name */ "gip",
240 /* .nf_modname */ "kgnilnd",
241 /* .nf_addr2str */ libcfs_ip_addr2str,
242 /* .nf_str2addr */ libcfs_ip_str2addr,
243 /* .nf_parse_addrlist*/ cfs_ip_addr_parse,
244 /* .nf_print_addrlist*/ libcfs_ip_addr_range_print,
245 /* .nf_match_addr*/ cfs_ip_addr_match,
246 /* .nf_is_contiguous */ cfs_ip_is_contiguous,
247 /* .nf_min_max */ cfs_ip_min_max},
248 /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */
252 static const size_t libcfs_nnetstrfns =
253 sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
256 libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
263 libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
265 snprintf(str, size, "%u.%u.%u.%u",
266 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
267 (addr >> 8) & 0xff, addr & 0xff);
270 /* CAVEAT EMPTOR XscanfX
271 * I use "%n" at the end of a sscanf format to detect trailing junk. However
272 * sscanf may return immediately if it sees the terminating '0' in a string, so
273 * I initialise the %n variable to the expected length. If sscanf sets it;
274 * fine, if it doesn't, then the scan ended at the end of the string, which is
277 libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
283 int n = nob; /* XscanfX */
286 if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
288 (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
289 (c & ~0xff) == 0 && (d & ~0xff) == 0) {
290 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
294 #ifdef HAVE_GETHOSTBYNAME
295 /* known hostname? */
296 if (('a' <= str[0] && str[0] <= 'z') ||
297 ('A' <= str[0] && str[0] <= 'Z')) {
300 tmp = calloc(1, nob + 1);
304 memcpy(tmp, str, nob);
307 he = gethostbyname(tmp);
312 __u32 ip = *(__u32 *)he->h_addr;
324 libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
326 snprintf(str, size, "%u", addr);
330 libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size)
332 snprintf(str, size, "0x%x", addr);
336 libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
341 if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
345 if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
349 if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
355 static struct netstrfns *
356 libcfs_lnd2netstrfns(__u32 lnd)
360 for (i = 0; i < libcfs_nnetstrfns; i++)
361 if (lnd == libcfs_netstrfns[i].nf_type)
362 return &libcfs_netstrfns[i];
367 static struct netstrfns *
368 libcfs_namenum2netstrfns(const char *name)
370 struct netstrfns *nf;
373 for (i = 0; i < libcfs_nnetstrfns; i++) {
374 nf = &libcfs_netstrfns[i];
375 if (nf->nf_type >= 0 &&
376 !strncmp(name, nf->nf_name, strlen(nf->nf_name)))
382 static struct netstrfns *
383 libcfs_name2netstrfns(const char *name)
387 for (i = 0; i < libcfs_nnetstrfns; i++)
388 if (libcfs_netstrfns[i].nf_type >= 0 &&
389 !strcmp(libcfs_netstrfns[i].nf_name, name))
390 return &libcfs_netstrfns[i];
396 libcfs_isknown_lnd(__u32 lnd)
398 return libcfs_lnd2netstrfns(lnd) != NULL;
402 libcfs_lnd2modname(__u32 lnd)
404 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
406 return (nf == NULL) ? NULL : nf->nf_modname;
410 libcfs_str2lnd(const char *str)
412 struct netstrfns *nf = libcfs_name2netstrfns(str);
421 libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size)
423 struct netstrfns *nf;
425 nf = libcfs_lnd2netstrfns(lnd);
427 snprintf(buf, buf_size, "?%u?", lnd);
429 snprintf(buf, buf_size, "%s", nf->nf_name);
435 libcfs_net2str_r(__u32 net, char *buf, size_t buf_size)
437 __u32 nnum = LNET_NETNUM(net);
438 __u32 lnd = LNET_NETTYP(net);
439 struct netstrfns *nf;
441 nf = libcfs_lnd2netstrfns(lnd);
443 snprintf(buf, buf_size, "<%u:%u>", lnd, nnum);
445 snprintf(buf, buf_size, "%s", nf->nf_name);
447 snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum);
453 libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size)
455 __u32 addr = LNET_NIDADDR(nid);
456 __u32 net = LNET_NIDNET(nid);
457 __u32 nnum = LNET_NETNUM(net);
458 __u32 lnd = LNET_NETTYP(net);
459 struct netstrfns *nf;
461 if (nid == LNET_NID_ANY) {
462 strncpy(buf, "<?>", buf_size);
463 buf[buf_size - 1] = '\0';
467 nf = libcfs_lnd2netstrfns(lnd);
469 snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum);
473 nf->nf_addr2str(addr, buf, buf_size);
474 addr_len = strlen(buf);
476 snprintf(buf + addr_len, buf_size - addr_len, "@%s",
479 snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
486 static struct netstrfns *
487 libcfs_str2net_internal(const char *str, __u32 *net)
489 struct netstrfns *nf = NULL;
494 for (i = 0; i < libcfs_nnetstrfns; i++) {
495 nf = &libcfs_netstrfns[i];
496 if (nf->nf_type >= 0 &&
497 !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
501 if (i == libcfs_nnetstrfns)
504 nob = strlen(nf->nf_name);
506 if (strlen(str) == (unsigned int)nob) {
509 if (nf->nf_type == LOLND) /* net number not allowed */
514 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
515 i != (int)strlen(str))
519 *net = LNET_MKNET(nf->nf_type, netnum);
524 libcfs_str2net(const char *str)
528 if (libcfs_str2net_internal(str, &net) != NULL)
531 return LNET_NIDNET(LNET_NID_ANY);
535 libcfs_str2nid(const char *str)
537 const char *sep = strchr(str, '@');
538 struct netstrfns *nf;
543 nf = libcfs_str2net_internal(sep + 1, &net);
547 sep = str + strlen(str);
548 net = LNET_MKNET(SOCKLND, 0);
549 nf = libcfs_lnd2netstrfns(SOCKLND);
553 if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
556 return LNET_MKNID(net, addr);
560 libcfs_id2str(lnet_process_id_t id)
562 char *str = libcfs_next_nidstring();
564 if (id.pid == LNET_PID_ANY) {
565 snprintf(str, LNET_NIDSTR_SIZE,
566 "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
570 snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
571 ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
572 (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
577 libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
579 if (!strcmp(str, "*")) {
580 *nidp = LNET_NID_ANY;
584 *nidp = libcfs_str2nid(str);
585 return *nidp != LNET_NID_ANY;
589 * Nid range list syntax.
592 * <nidlist> :== <nidrange> [ ' ' <nidrange> ]
593 * <nidrange> :== <addrrange> '@' <net>
594 * <addrrange> :== '*' |
597 * <ipaddr_range> :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
599 * <cfs_expr_list> :== <number> |
601 * <expr_list> :== '[' <range_expr> [ ',' <range_expr>] ']'
602 * <range_expr> :== <number> |
603 * <number> '-' <number> |
604 * <number> '-' <number> '/' <number>
605 * <net> :== <netname> | <netname><number>
606 * <netname> :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
607 * "vib" | "ra" | "elan" | "mx" | "ptl"
612 * Structure to represent \<nidrange\> token of the syntax.
614 * One of this is created for each \<net\> parsed.
618 * Link to list of this structures which is built on nid range
621 struct list_head nr_link;
623 * List head for addrrange::ar_link.
625 struct list_head nr_addrranges;
627 * Flag indicating that *@<net> is found.
631 * Pointer to corresponding element of libcfs_netstrfns.
633 struct netstrfns *nr_netstrfns;
635 * Number of network. E.g. 5 if \<net\> is "elan5".
641 * Structure to represent \<addrrange\> token of the syntax.
645 * Link to nidrange::nr_addrranges.
647 struct list_head ar_link;
649 * List head for cfs_expr_list::el_list.
651 struct list_head ar_numaddr_ranges;
655 * Nf_parse_addrlist method for networks using numeric addresses.
657 * Examples of such networks are gm and elan.
659 * \retval 0 if \a str parsed to numeric address
660 * \retval errno otherwise
663 libcfs_num_parse(char *str, int len, struct list_head *list)
665 struct cfs_expr_list *el;
668 rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
670 list_add_tail(&el->el_link, list);
676 * Parses \<addrrange\> token on the syntax.
678 * Allocates struct addrrange and links to \a nidrange via
679 * (nidrange::nr_addrranges)
681 * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
682 * \retval -errno otherwise
685 parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
687 struct addrrange *addrrange;
689 if (src->ls_len == 1 && src->ls_str[0] == '*') {
690 nidrange->nr_all = 1;
694 addrrange = calloc(1, sizeof(struct addrrange));
695 if (addrrange == NULL)
697 list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
698 INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
700 return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
702 &addrrange->ar_numaddr_ranges);
706 * Finds or creates struct nidrange.
708 * Checks if \a src is a valid network name, looks for corresponding
709 * nidrange on the ist of nidranges (\a nidlist), creates new struct
710 * nidrange if it is not found.
712 * \retval pointer to struct nidrange matching network specified via \a src
713 * \retval NULL if \a src does not match any network
715 static struct nidrange *
716 add_nidrange(const struct cfs_lstr *src,
717 struct list_head *nidlist)
719 struct netstrfns *nf;
724 if (src->ls_len >= LNET_NIDSTR_SIZE)
727 nf = libcfs_namenum2netstrfns(src->ls_str);
730 endlen = src->ls_len - strlen(nf->nf_name);
732 /* network name only, e.g. "elan" or "tcp" */
735 /* e.g. "elan25" or "tcp23", refuse to parse if
736 * network name is not appended with decimal or
737 * hexadecimal number */
738 if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
739 endlen, &netnum, 0, MAX_NUMERIC_VALUE))
743 list_for_each_entry(nr, nidlist, nr_link) {
744 if (nr->nr_netstrfns != nf)
746 if (nr->nr_netnum != netnum)
751 nr = calloc(1, sizeof(struct nidrange));
754 list_add_tail(&nr->nr_link, nidlist);
755 INIT_LIST_HEAD(&nr->nr_addrranges);
756 nr->nr_netstrfns = nf;
758 nr->nr_netnum = netnum;
764 * Parses \<nidrange\> token of the syntax.
766 * \retval 1 if \a src parses to \<addrrange\> '@' \<net\>
767 * \retval 0 otherwise
770 parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
772 struct cfs_lstr addrrange;
778 if (cfs_gettok(src, '@', &addrrange) == 0)
781 if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
784 nr = add_nidrange(&net, nidlist);
788 if (parse_addrange(&addrrange, nr) != 0)
793 fprintf(stderr, "can't parse nidrange: \"%.*s\"\n",
794 tmp.ls_len, tmp.ls_str);
799 * Frees addrrange structures of \a list.
801 * For each struct addrrange structure found on \a list it frees
802 * cfs_expr_list list attached to it and frees the addrrange itself.
807 free_addrranges(struct list_head *list)
809 while (!list_empty(list)) {
810 struct addrrange *ar;
812 ar = list_entry(list->next, struct addrrange, ar_link);
814 cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
815 list_del(&ar->ar_link);
821 * Frees nidrange strutures of \a list.
823 * For each struct nidrange structure found on \a list it frees
824 * addrrange list attached to it and frees the nidrange itself.
829 cfs_free_nidlist(struct list_head *list)
831 struct list_head *pos, *next;
834 list_for_each_safe(pos, next, list) {
835 nr = list_entry(pos, struct nidrange, nr_link);
836 free_addrranges(&nr->nr_addrranges);
843 * Parses nid range list.
845 * Parses with rigorous syntax and overflow checking \a str into
846 * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
847 * structures and links that structure to \a nidlist. The resulting
848 * list can be used to match a NID againts set of NIDS defined by \a
852 * \retval 1 on success
853 * \retval 0 otherwise
856 cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
864 INIT_LIST_HEAD(nidlist);
866 rc = cfs_gettok(&src, ' ', &res);
868 cfs_free_nidlist(nidlist);
871 rc = parse_nidrange(&res, nidlist);
873 cfs_free_nidlist(nidlist);
881 * Nf_match_addr method for networks using numeric addresses
884 * \retval 0 otherwise
887 libcfs_num_match(__u32 addr, struct list_head *numaddr)
889 struct cfs_expr_list *el;
891 assert(!list_empty(numaddr));
892 el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
894 return cfs_expr_list_match(addr, el);
898 * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
900 * \see cfs_parse_nidlist()
903 * \retval 0 otherwises
905 int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
908 struct addrrange *ar;
910 list_for_each_entry(nr, nidlist, nr_link) {
911 if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
913 if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
917 list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
918 if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
919 &ar->ar_numaddr_ranges))
926 libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
928 struct cfs_expr_list *el;
931 list_for_each_entry(el, list, el_link) {
933 i += cfs_expr_list_print(buffer + i, count - i, el);
939 libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
942 struct cfs_expr_list *el;
944 list_for_each_entry(el, list, el_link) {
947 i += snprintf(buffer + i, count - i, ".");
948 i += cfs_expr_list_print(buffer + i, count - i, el);
955 * Print the network part of the nidrange \a nr into the specified \a buffer.
957 * \retval number of characters written
960 cfs_print_network(char *buffer, int count, struct nidrange *nr)
962 struct netstrfns *nf = nr->nr_netstrfns;
964 if (nr->nr_netnum == 0)
965 return snprintf(buffer, count, "@%s", nf->nf_name);
967 return snprintf(buffer, count, "@%s%u",
968 nf->nf_name, nr->nr_netnum);
973 * Print a list of addrrange (\a addrranges) into the specified \a buffer.
974 * At max \a count characters can be printed into \a buffer.
976 * \retval number of characters written
979 cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges,
983 struct addrrange *ar;
984 struct netstrfns *nf = nr->nr_netstrfns;
986 list_for_each_entry(ar, addrranges, ar_link) {
988 i += snprintf(buffer + i, count - i, " ");
989 i += nf->nf_print_addrlist(buffer + i, count - i,
990 &ar->ar_numaddr_ranges);
991 i += cfs_print_network(buffer + i, count - i, nr);
997 * Print a list of nidranges (\a nidlist) into the specified \a buffer.
998 * At max \a count characters can be printed into \a buffer.
999 * Nidranges are separated by a space character.
1001 * \retval number of characters written
1003 int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
1006 struct nidrange *nr;
1011 list_for_each_entry(nr, nidlist, nr_link) {
1013 i += snprintf(buffer + i, count - i, " ");
1015 if (nr->nr_all != 0) {
1016 assert(list_empty(&nr->nr_addrranges));
1017 i += snprintf(buffer + i, count - i, "*");
1018 i += cfs_print_network(buffer + i, count - i, nr);
1020 i += cfs_print_addrranges(buffer + i, count - i,
1021 &nr->nr_addrranges, nr);
1028 * Determines minimum and maximum addresses for a single
1029 * numeric address range
1035 static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1038 struct cfs_expr_list *el;
1039 struct cfs_range_expr *re;
1040 __u32 tmp_ip_addr = 0;
1041 unsigned int min_ip[4] = {0};
1042 unsigned int max_ip[4] = {0};
1045 list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
1046 list_for_each_entry(re, &el->el_exprs, re_link) {
1047 min_ip[re_count] = re->re_lo;
1048 max_ip[re_count] = re->re_hi;
1053 tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) |
1054 (min_ip[2] << 8) | min_ip[3]);
1056 if (min_nid != NULL)
1057 *min_nid = tmp_ip_addr;
1059 tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) |
1060 (max_ip[2] << 8) | max_ip[3]);
1062 if (max_nid != NULL)
1063 *max_nid = tmp_ip_addr;
1067 * Determines minimum and maximum addresses for a single
1068 * numeric address range
1074 static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1077 struct cfs_expr_list *el;
1078 struct cfs_range_expr *re;
1079 unsigned int min_addr = 0;
1080 unsigned int max_addr = 0;
1082 list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
1083 list_for_each_entry(re, &el->el_exprs, re_link) {
1084 if (re->re_lo < min_addr || min_addr == 0)
1085 min_addr = re->re_lo;
1086 if (re->re_hi > max_addr)
1087 max_addr = re->re_hi;
1091 if (min_nid != NULL)
1092 *min_nid = min_addr;
1093 if (max_nid != NULL)
1094 *max_nid = max_addr;
1098 * Determines whether an expression list in an nidrange contains exactly
1099 * one contiguous address range. Calls the correct netstrfns for the LND
1103 * \retval true if contiguous
1104 * \retval false if not contiguous
1106 bool cfs_nidrange_is_contiguous(struct list_head *nidlist)
1108 struct nidrange *nr;
1109 struct netstrfns *nf = NULL;
1110 char *lndname = NULL;
1113 list_for_each_entry(nr, nidlist, nr_link) {
1114 nf = nr->nr_netstrfns;
1115 if (lndname == NULL)
1116 lndname = nf->nf_name;
1118 netnum = nr->nr_netnum;
1120 if (strcmp(lndname, nf->nf_name) != 0 ||
1121 netnum != nr->nr_netnum)
1128 if (!nf->nf_is_contiguous(nidlist))
1135 * Determines whether an expression list in an num nidrange contains exactly
1136 * one contiguous address range.
1140 * \retval true if contiguous
1141 * \retval false if not contiguous
1143 static bool cfs_num_is_contiguous(struct list_head *nidlist)
1145 struct nidrange *nr;
1146 struct addrrange *ar;
1147 struct cfs_expr_list *el;
1148 struct cfs_range_expr *re;
1150 __u32 last_end_nid = 0;
1151 __u32 current_start_nid = 0;
1152 __u32 current_end_nid = 0;
1154 list_for_each_entry(nr, nidlist, nr_link) {
1155 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1156 cfs_num_ar_min_max(ar, ¤t_start_nid,
1158 if (last_end_nid != 0 &&
1159 (current_start_nid - last_end_nid != 1))
1161 last_end_nid = current_end_nid;
1162 list_for_each_entry(el, &ar->ar_numaddr_ranges,
1164 list_for_each_entry(re, &el->el_exprs,
1166 if (re->re_stride > 1)
1168 else if (last_hi != 0 &&
1169 re->re_hi - last_hi != 1)
1171 last_hi = re->re_hi;
1181 * Determines whether an expression list in an ip nidrange contains exactly
1182 * one contiguous address range.
1186 * \retval true if contiguous
1187 * \retval false if not contiguous
1189 static bool cfs_ip_is_contiguous(struct list_head *nidlist)
1191 struct nidrange *nr;
1192 struct addrrange *ar;
1193 struct cfs_expr_list *el;
1194 struct cfs_range_expr *re;
1198 __u32 last_end_nid = 0;
1199 __u32 current_start_nid = 0;
1200 __u32 current_end_nid = 0;
1202 list_for_each_entry(nr, nidlist, nr_link) {
1203 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1206 cfs_ip_ar_min_max(ar, ¤t_start_nid,
1208 if (last_end_nid != 0 &&
1209 (current_start_nid - last_end_nid != 1))
1211 last_end_nid = current_end_nid;
1212 list_for_each_entry(el,
1213 &ar->ar_numaddr_ranges,
1216 list_for_each_entry(re, &el->el_exprs,
1219 if (re->re_stride > 1 ||
1220 (last_diff > 0 && last_hi != 255) ||
1221 (last_diff > 0 && last_hi == 255 &&
1224 last_hi = re->re_hi;
1225 last_diff = re->re_hi - re->re_lo;
1235 * Takes a linked list of nidrange expressions, determines the minimum
1236 * and maximum nid and creates appropriate nid structures
1242 void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
1243 char *max_nid, size_t nidstr_length)
1245 struct nidrange *nr;
1246 struct netstrfns *nf = NULL;
1250 char *lndname = NULL;
1251 char min_addr_str[IPSTRING_LENGTH];
1252 char max_addr_str[IPSTRING_LENGTH];
1254 list_for_each_entry(nr, nidlist, nr_link) {
1255 nf = nr->nr_netstrfns;
1256 lndname = nf->nf_name;
1258 netnum = nr->nr_netnum;
1260 nf->nf_min_max(nidlist, &min_addr, &max_addr);
1262 nf->nf_addr2str(min_addr, min_addr_str, sizeof(min_addr_str));
1263 nf->nf_addr2str(max_addr, max_addr_str, sizeof(max_addr_str));
1265 snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
1267 snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
1272 * Determines the min and max NID values for num LNDs
1278 static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
1281 struct nidrange *nr;
1282 struct addrrange *ar;
1283 unsigned int tmp_min_addr = 0;
1284 unsigned int tmp_max_addr = 0;
1285 unsigned int min_addr = 0;
1286 unsigned int max_addr = 0;
1288 list_for_each_entry(nr, nidlist, nr_link) {
1289 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1290 cfs_num_ar_min_max(ar, &tmp_min_addr,
1292 if (tmp_min_addr < min_addr || min_addr == 0)
1293 min_addr = tmp_min_addr;
1294 if (tmp_max_addr > max_addr)
1295 max_addr = tmp_min_addr;
1298 *max_nid = max_addr;
1299 *min_nid = min_addr;
1303 * Takes an nidlist and determines the minimum and maximum
1310 static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
1313 struct nidrange *nr;
1314 struct addrrange *ar;
1315 __u32 tmp_min_ip_addr = 0;
1316 __u32 tmp_max_ip_addr = 0;
1317 __u32 min_ip_addr = 0;
1318 __u32 max_ip_addr = 0;
1320 list_for_each_entry(nr, nidlist, nr_link) {
1321 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1322 cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
1324 if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
1325 min_ip_addr = tmp_min_ip_addr;
1326 if (tmp_max_ip_addr > max_ip_addr)
1327 max_ip_addr = tmp_max_ip_addr;
1331 if (min_nid != NULL)
1332 *min_nid = min_ip_addr;
1333 if (max_nid != NULL)
1334 *max_nid = max_ip_addr;