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.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2017, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
31 * libcfs/libcfs/util/nidstrings.c
33 * Author: Phil Schwan <phil@clusterfs.com>
36 #define DEBUG_SUBSYSTEM S_LNET
44 #include <arpa/inet.h>
46 #include <libcfs/util/string.h>
47 #include <linux/lnet/lnet-types.h>
48 #include <linux/lnet/nidstr.h>
53 /* max value for numeric network address */
54 #define MAX_NUMERIC_VALUE 0xffffffff
56 #define IPSTRING_LENGTH 16
58 /* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids
59 * consistent in all conversion functions. Some code fragments are copied
60 * around for the sake of clarity...
63 /* CAVEAT EMPTOR! Racey temporary buffer allocation!
64 * Choose the number of nidstrings to support the MAXIMUM expected number of
65 * concurrent users. If there are more, the returned string will be volatile.
66 * NB this number must allow for a process to be descheduled for a timeslice
67 * between getting its string and using it.
70 static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
71 static int libcfs_nidstring_idx;
74 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 libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
94 libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
96 snprintf(str, size, "%u.%u.%u.%u",
97 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
98 (addr >> 8) & 0xff, addr & 0xff);
102 libcfs_ip_addr2str_size(const __be32 *addr, size_t asize,
103 char *str, size_t size)
107 inet_ntop(AF_INET, addr, str, size);
110 inet_ntop(AF_INET6, addr, str, size);
117 /* CAVEAT EMPTOR XscanfX
118 * I use "%n" at the end of a sscanf format to detect trailing junk. However
119 * sscanf may return immediately if it sees the terminating '0' in a string, so
120 * I initialise the %n variable to the expected length. If sscanf sets it;
121 * fine, if it doesn't, then the scan ended at the end of the string, which is
124 libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
130 int n = nob; /* XscanfX */
133 if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
135 (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
136 (c & ~0xff) == 0 && (d & ~0xff) == 0) {
137 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
141 #ifdef HAVE_GETHOSTBYNAME
142 /* known hostname? */
143 if (('a' <= str[0] && str[0] <= 'z') ||
144 ('A' <= str[0] && str[0] <= 'Z')) {
147 tmp = calloc(1, nob + 1);
151 memcpy(tmp, str, nob);
154 he = gethostbyname(tmp);
159 __u32 ip = *(__u32 *)he->h_addr;
171 libcfs_ip_str2addr_size(const char *str, int nob,
172 __be32 *addr, size_t *alen)
174 char *tmp = malloc(nob+1);
179 memcpy(tmp, str, nob);
182 if (inet_pton(AF_INET, tmp, (struct in_addr *)addr) == 0) {
186 if (inet_pton(AF_INET6, tmp, (struct in6_addr *)addr) == 0) {
190 #ifdef HAVE_GETADDRINFO
191 /* known hostname? */
192 if (('a' <= str[0] && str[0] <= 'z') ||
193 ('A' <= str[0] && str[0] <= 'Z')) {
194 struct addrinfo *ai = NULL;
196 if (getaddrinfo(tmp, NULL, NULL, &ai) == 0) {
198 /* First look for an AF_INET address */
199 for (a = ai; a; a = a->ai_next) {
200 if (a->ai_family == AF_INET && a->ai_addr) {
201 struct sockaddr_in *sin =
204 memcpy(addr, &sin->sin_addr, 4);
210 /* Now consider AF_INET6 */
211 for (a = ai; a; a = a->ai_next) {
212 if (a->ai_family == AF_INET6 && a->ai_addr) {
213 struct sockaddr_in6 *sin6 =
216 memcpy(addr, &sin6->sin6_addr, 16);
233 cfs_ip_addr_parse(char *str, int len, struct list_head *list)
235 struct cfs_expr_list *el;
244 while (src.ls_str != NULL) {
247 if (!cfs_gettok(&src, '.', &res)) {
252 rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el);
256 list_add_tail(&el->el_link, list);
265 cfs_expr_list_free_list(list);
271 cfs_expr2str(struct list_head *list, char *str, size_t size)
273 struct cfs_expr_list *expr;
274 struct cfs_range_expr *range;
275 char tmp[LNET_NIDSTR_SIZE];
278 bool bracket = false;
282 list_for_each_entry(expr, list, el_link) {
284 list_for_each_entry(range, &expr->el_exprs, re_link) {
285 if (range->re_lo == range->re_hi) {
288 "%u.", range->re_lo);
289 } else if (range->re_lo < range->re_hi) {
290 if (range->re_stride > 1) {
292 format = "[%u-%u/%u,";
294 format = "%u-%u/%u,";
295 snprintf(tmp, LNET_NIDSTR_SIZE,
296 format, range->re_lo,
297 range->re_hi, range->re_stride);
304 snprintf(tmp, LNET_NIDSTR_SIZE,
305 format, range->re_lo,
317 strncat(str, tmp, size + len);
321 tmpc = str + (strlen(str) - 1);
332 * get rid of the trailing '.' at the end of the string
333 * only if we actually had something on the list passed in.
334 * otherwise we could write outside the array
336 if (!list_empty(list))
337 str[strlen(str)-1] = '\0';
342 libcfs_num_addr_range_expand(struct list_head *addrranges, __u32 *addrs,
345 struct cfs_expr_list *expr_list;
346 struct cfs_range_expr *range;
348 int max_idx = max_addrs - 1;
349 int addrs_idx = max_idx;
351 list_for_each_entry(expr_list, addrranges, el_link) {
352 list_for_each_entry(range, &expr_list->el_exprs, re_link) {
353 for (i = range->re_lo; i <= range->re_hi;
354 i += range->re_stride) {
358 addrs[addrs_idx] = i;
364 return max_idx - addrs_idx;
368 libcfs_ip_addr_range_expand(struct list_head *addrranges, __u32 *addrs,
373 rc = cfs_ip_addr_range_gen(addrs, max_addrs, addrranges);
378 return max_addrs - rc - 1;
382 libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
385 struct cfs_expr_list *el;
387 list_for_each_entry(el, list, el_link) {
390 i += scnprintf(buffer + i, count - i, ".");
391 i += cfs_expr_list_print(buffer + i, count - i, el);
397 cfs_ip_addr_range_gen_recurse(__u32 *ip_list, int *count, int shift,
398 __u32 result, struct list_head *head_el,
399 struct cfs_expr_list *octet_el)
403 struct cfs_expr_list *next_octet_el;
404 struct cfs_range_expr *octet_expr;
407 * each octet can have multiple expressions so we need to traverse
408 * all of the expressions
410 list_for_each_entry(octet_expr, &octet_el->el_exprs, re_link) {
411 for (i = octet_expr->re_lo; i <= octet_expr->re_hi; i++) {
412 if (((i - octet_expr->re_lo) % octet_expr->re_stride) == 0) {
414 * we have a hit calculate the result and
415 * pass it forward to the next iteration
419 list_entry(octet_el->el_link.next,
420 typeof(*next_octet_el),
422 value = result | (i << (shift * 8));
423 if (next_octet_el->el_link.next != head_el) {
425 * We still have more octets in
426 * the IP address so traverse
427 * that. We're doing a depth first
430 if (cfs_ip_addr_range_gen_recurse(ip_list, count,
433 next_octet_el) == -1)
437 * We have hit a leaf so store the
438 * calculated IP address in the
439 * list. If we have run out of
440 * space stop the recursion.
444 /* add ip to the list */
445 ip_list[*count] = value;
455 * only generate maximum of count ip addresses from the given expression
458 cfs_ip_addr_range_gen(__u32 *ip_list, int count, struct list_head *ip_addr_expr)
460 struct cfs_expr_list *octet_el;
463 octet_el = list_first_entry(ip_addr_expr, typeof(*octet_el), el_link);
465 (void) cfs_ip_addr_range_gen_recurse(ip_list, &idx, 3, 0, &octet_el->el_link, octet_el);
471 * Matches address (\a addr) against address set encoded in \a list.
473 * \retval 1 if \a addr matches
474 * \retval 0 otherwise
477 cfs_ip_addr_match(__u32 addr, struct list_head *list)
479 struct cfs_expr_list *el;
482 list_for_each_entry_reverse(el, list, el_link) {
483 if (!cfs_expr_list_match(addr & 0xff, el))
493 libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
495 snprintf(str, size, "%u", addr);
499 libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
504 if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
508 if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
512 if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
519 * Nf_parse_addrlist method for networks using numeric addresses.
521 * Examples of such networks are gm and elan.
523 * \retval 0 if \a str parsed to numeric address
524 * \retval errno otherwise
527 libcfs_num_parse(char *str, int len, struct list_head *list)
529 struct cfs_expr_list *el;
532 rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
534 list_add_tail(&el->el_link, list);
540 libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
542 struct cfs_expr_list *el;
545 list_for_each_entry(el, list, el_link) {
547 i += cfs_expr_list_print(buffer + i, count - i, el);
553 * Nf_match_addr method for networks using numeric addresses
556 * \retval 0 otherwise
559 libcfs_num_match(__u32 addr, struct list_head *numaddr)
561 struct cfs_expr_list *el;
563 assert(!list_empty(numaddr));
564 el = list_first_entry(numaddr, struct cfs_expr_list, el_link);
566 return cfs_expr_list_match(addr, el);
569 static int cfs_ip_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
570 static int cfs_num_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
572 static struct netstrfns libcfs_netstrfns[] = {
576 .nf_modname = "klolnd",
577 .nf_addr2str = libcfs_decnum_addr2str,
578 .nf_str2addr = libcfs_lo_str2addr,
579 .nf_parse_addrlist = libcfs_num_parse,
580 .nf_print_addrlist = libcfs_num_addr_range_print,
581 .nf_match_addr = libcfs_num_match,
582 .nf_min_max = cfs_num_min_max,
583 .nf_expand_addrrange = libcfs_num_addr_range_expand
588 .nf_modname = "ksocklnd",
589 .nf_addr2str = libcfs_ip_addr2str,
590 .nf_addr2str_size = libcfs_ip_addr2str_size,
591 .nf_str2addr = libcfs_ip_str2addr,
592 .nf_str2addr_size = libcfs_ip_str2addr_size,
593 .nf_parse_addrlist = cfs_ip_addr_parse,
594 .nf_print_addrlist = libcfs_ip_addr_range_print,
595 .nf_match_addr = cfs_ip_addr_match,
596 .nf_min_max = cfs_ip_min_max,
597 .nf_expand_addrrange = libcfs_ip_addr_range_expand
602 .nf_modname = "ko2iblnd",
603 .nf_addr2str = libcfs_ip_addr2str,
604 .nf_str2addr = libcfs_ip_str2addr,
605 .nf_parse_addrlist = cfs_ip_addr_parse,
606 .nf_print_addrlist = libcfs_ip_addr_range_print,
607 .nf_match_addr = cfs_ip_addr_match,
608 .nf_min_max = cfs_ip_min_max,
609 .nf_expand_addrrange = libcfs_ip_addr_range_expand
614 .nf_modname = "kgnilnd",
615 .nf_addr2str = libcfs_decnum_addr2str,
616 .nf_str2addr = libcfs_num_str2addr,
617 .nf_parse_addrlist = libcfs_num_parse,
618 .nf_print_addrlist = libcfs_num_addr_range_print,
619 .nf_match_addr = libcfs_num_match,
620 .nf_min_max = cfs_num_min_max,
621 .nf_expand_addrrange = libcfs_num_addr_range_expand
626 .nf_modname = "kgnilnd",
627 .nf_addr2str = libcfs_ip_addr2str,
628 .nf_str2addr = libcfs_ip_str2addr,
629 .nf_parse_addrlist = cfs_ip_addr_parse,
630 .nf_print_addrlist = libcfs_ip_addr_range_print,
631 .nf_match_addr = cfs_ip_addr_match,
632 .nf_min_max = cfs_ip_min_max,
633 .nf_expand_addrrange = libcfs_ip_addr_range_expand
638 .nf_modname = "kptl4lnd",
639 .nf_addr2str = libcfs_decnum_addr2str,
640 .nf_str2addr = libcfs_num_str2addr,
641 .nf_parse_addrlist = libcfs_num_parse,
642 .nf_print_addrlist = libcfs_num_addr_range_print,
643 .nf_match_addr = libcfs_num_match,
644 .nf_min_max = cfs_num_min_max,
645 .nf_expand_addrrange = libcfs_num_addr_range_expand
650 .nf_modname = "kkfilnd",
651 .nf_addr2str = libcfs_decnum_addr2str,
652 .nf_str2addr = libcfs_num_str2addr,
653 .nf_parse_addrlist = libcfs_num_parse,
654 .nf_print_addrlist = libcfs_num_addr_range_print,
655 .nf_match_addr = libcfs_num_match,
656 .nf_min_max = cfs_num_min_max,
657 .nf_expand_addrrange = libcfs_num_addr_range_expand
661 static const size_t libcfs_nnetstrfns =
662 sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
664 static struct netstrfns *
665 libcfs_lnd2netstrfns(__u32 lnd)
669 for (i = 0; i < libcfs_nnetstrfns; i++)
670 if (lnd == libcfs_netstrfns[i].nf_type)
671 return &libcfs_netstrfns[i];
676 static struct netstrfns *
677 libcfs_namenum2netstrfns(const char *name)
679 struct netstrfns *nf;
682 for (i = 0; i < libcfs_nnetstrfns; i++) {
683 nf = &libcfs_netstrfns[i];
684 if (!strncmp(name, nf->nf_name, strlen(nf->nf_name)))
690 static struct netstrfns *
691 libcfs_name2netstrfns(const char *name)
695 for (i = 0; i < libcfs_nnetstrfns; i++)
696 if (!strcmp(libcfs_netstrfns[i].nf_name, name))
697 return &libcfs_netstrfns[i];
703 libcfs_isknown_lnd(__u32 lnd)
705 return libcfs_lnd2netstrfns(lnd) != NULL;
709 libcfs_lnd2modname(__u32 lnd)
711 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
713 return (nf == NULL) ? NULL : nf->nf_modname;
717 libcfs_str2lnd(const char *str)
719 struct netstrfns *nf = libcfs_name2netstrfns(str);
728 libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size)
730 struct netstrfns *nf;
732 nf = libcfs_lnd2netstrfns(lnd);
734 snprintf(buf, buf_size, "?%u?", lnd);
736 snprintf(buf, buf_size, "%s", nf->nf_name);
742 libcfs_net2str_r(__u32 net, char *buf, size_t buf_size)
744 __u32 nnum = LNET_NETNUM(net);
745 __u32 lnd = LNET_NETTYP(net);
746 struct netstrfns *nf;
748 nf = libcfs_lnd2netstrfns(lnd);
750 snprintf(buf, buf_size, "<%u:%u>", lnd, nnum);
752 snprintf(buf, buf_size, "%s", nf->nf_name);
754 snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum);
760 libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size)
762 __u32 addr = LNET_NIDADDR(nid);
763 __u32 net = LNET_NIDNET(nid);
764 __u32 nnum = LNET_NETNUM(net);
765 __u32 lnd = LNET_NETTYP(net);
766 struct netstrfns *nf;
768 if (nid == LNET_NID_ANY) {
769 strncpy(buf, "<?>", buf_size);
770 buf[buf_size - 1] = '\0';
774 nf = libcfs_lnd2netstrfns(lnd);
776 snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum);
780 nf->nf_addr2str(addr, buf, buf_size);
781 addr_len = strlen(buf);
783 snprintf(buf + addr_len, buf_size - addr_len, "@%s",
786 snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
794 libcfs_nidstr_r(const struct lnet_nid *nid, char *buf, size_t buf_size)
798 struct netstrfns *nf;
800 if (LNET_NID_IS_ANY(nid)) {
801 strncpy(buf, "<?>", buf_size);
802 buf[buf_size - 1] = '\0';
806 nnum = __be16_to_cpu(nid->nid_num);
808 nf = libcfs_lnd2netstrfns(lnd);
811 /* Avoid take address in packed array */
812 __u32 addr[4] = { nid->nid_addr[0], nid->nid_addr[1],
813 nid->nid_addr[2], nid->nid_addr[3]};
815 if (nf->nf_addr2str_size)
816 nf->nf_addr2str_size(addr, NID_ADDR_BYTES(nid),
819 nf->nf_addr2str(ntohl(nid->nid_addr[0]), buf, buf_size);
820 addr_len = strlen(buf);
822 snprintf(buf + addr_len, buf_size - addr_len, "@%s",
825 snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
829 int words = (NID_ADDR_BYTES(nid) + 3) / 4;
832 for (i = 0; i < words && i < 4; i++)
833 l = snprintf(buf+l, buf_size-l, "%s%x",
834 i ? ":" : "", ntohl(nid->nid_addr[i]));
835 snprintf(buf+l, buf_size-l, "@<%u:%u>", lnd, nnum);
841 static struct netstrfns *
842 libcfs_str2net_internal(const char *str, __u32 *net)
844 struct netstrfns *nf = NULL;
849 for (i = 0; i < libcfs_nnetstrfns; i++) {
850 nf = &libcfs_netstrfns[i];
851 if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
855 if (i == libcfs_nnetstrfns)
858 nob = strlen(nf->nf_name);
860 if (strlen(str) == (unsigned int)nob) {
863 if (nf->nf_type == LOLND) /* net number not allowed */
868 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
869 i != (int)strlen(str))
873 *net = LNET_MKNET(nf->nf_type, netnum);
878 libcfs_str2net(const char *str)
882 if (libcfs_str2net_internal(str, &net) != NULL)
889 libcfs_str2nid(const char *str)
891 const char *sep = strchr(str, '@');
892 struct netstrfns *nf;
897 nf = libcfs_str2net_internal(sep + 1, &net);
901 sep = str + strlen(str);
902 net = LNET_MKNET(SOCKLND, 0);
903 nf = libcfs_lnd2netstrfns(SOCKLND);
907 if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
910 return LNET_MKNID(net, addr);
914 libcfs_strnid(struct lnet_nid *nid, const char *str)
916 const char *sep = strchr(str, '@');
917 struct netstrfns *nf;
921 nf = libcfs_str2net_internal(sep + 1, &net);
925 sep = str + strlen(str);
926 net = LNET_MKNET(SOCKLND, 0);
927 nf = libcfs_lnd2netstrfns(SOCKLND);
931 memset(nid, 0, sizeof(*nid));
932 nid->nid_type = LNET_NETTYP(net);
933 nid->nid_num = htons(LNET_NETNUM(net));
934 if (nf->nf_str2addr_size) {
938 if (!nf->nf_str2addr_size(str, (int)(sep - str),
942 /* Avoid take address in packed array */
943 nid->nid_addr[0] = addr[0];
944 nid->nid_addr[1] = addr[1];
945 nid->nid_addr[2] = addr[2];
946 nid->nid_addr[3] = addr[3];
947 nid->nid_size = asize - 4;
951 if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
953 nid->nid_addr[0] = htonl(addr);
960 libcfs_id2str(struct lnet_process_id id)
962 char *str = libcfs_next_nidstring();
964 if (id.pid == LNET_PID_ANY) {
965 snprintf(str, LNET_NIDSTR_SIZE,
966 "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
970 snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
971 ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
972 (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
977 libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
979 if (!strcmp(str, "*")) {
980 *nidp = LNET_NID_ANY;
984 *nidp = libcfs_str2nid(str);
985 return *nidp != LNET_NID_ANY;
989 * Nid range list syntax.
992 * <nidlist> :== <nidrange> [ ' ' <nidrange> ]
993 * <nidrange> :== <addrrange> '@' <net>
994 * <addrrange> :== '*' |
997 * <ipaddr_range> :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
999 * <cfs_expr_list> :== <number> |
1001 * <expr_list> :== '[' <range_expr> [ ',' <range_expr>] ']'
1002 * <range_expr> :== <number> |
1003 * <number> '-' <number> |
1004 * <number> '-' <number> '/' <number>
1005 * <net> :== <netname> | <netname><number>
1006 * <netname> :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
1007 * "vib" | "ra" | "elan" | "mx" | "ptl"
1012 * Structure to represent \<nidrange\> token of the syntax.
1014 * One of this is created for each \<net\> parsed.
1018 * Link to list of this structures which is built on nid range
1021 struct list_head nr_link;
1023 * List head for addrrange::ar_link.
1025 struct list_head nr_addrranges;
1027 * Flag indicating that *@<net> is found.
1031 * Pointer to corresponding element of libcfs_netstrfns.
1033 struct netstrfns *nr_netstrfns;
1035 * Number of network. E.g. 5 if \<net\> is "elan5".
1041 * Structure to represent \<addrrange\> token of the syntax.
1045 * Link to nidrange::nr_addrranges.
1047 struct list_head ar_link;
1049 * List head for cfs_expr_list::el_list.
1051 struct list_head ar_numaddr_ranges;
1055 * Parses \<addrrange\> token on the syntax.
1057 * Allocates struct addrrange and links to \a nidrange via
1058 * (nidrange::nr_addrranges)
1060 * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
1061 * \retval -errno otherwise
1064 parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
1066 struct addrrange *addrrange;
1068 if (src->ls_len == 1 && src->ls_str[0] == '*') {
1069 nidrange->nr_all = 1;
1073 addrrange = calloc(1, sizeof(struct addrrange));
1074 if (addrrange == NULL)
1076 list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
1077 INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
1079 return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
1081 &addrrange->ar_numaddr_ranges);
1085 * Finds or creates struct nidrange.
1087 * Checks if \a src is a valid network name, looks for corresponding
1088 * nidrange on the ist of nidranges (\a nidlist), creates new struct
1089 * nidrange if it is not found.
1091 * \retval pointer to struct nidrange matching network specified via \a src
1092 * \retval NULL if \a src does not match any network
1094 static struct nidrange *
1095 add_nidrange(const struct cfs_lstr *src,
1096 struct list_head *nidlist)
1098 struct netstrfns *nf;
1099 struct nidrange *nr;
1103 if (src->ls_len >= LNET_NIDSTR_SIZE)
1106 nf = libcfs_namenum2netstrfns(src->ls_str);
1109 endlen = src->ls_len - strlen(nf->nf_name);
1111 /* network name only, e.g. "elan" or "tcp" */
1114 /* e.g. "elan25" or "tcp23", refuse to parse if
1115 * network name is not appended with decimal or
1116 * hexadecimal number */
1117 if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
1118 endlen, &netnum, 0, MAX_NUMERIC_VALUE))
1122 list_for_each_entry(nr, nidlist, nr_link) {
1123 if (nr->nr_netstrfns != nf)
1125 if (nr->nr_netnum != netnum)
1130 nr = calloc(1, sizeof(struct nidrange));
1133 list_add_tail(&nr->nr_link, nidlist);
1134 INIT_LIST_HEAD(&nr->nr_addrranges);
1135 nr->nr_netstrfns = nf;
1137 nr->nr_netnum = netnum;
1143 * Parses \<nidrange\> token of the syntax.
1145 * \retval 1 if \a src parses to \<addrrange\> '@' \<net\>
1146 * \retval 0 otherwise
1149 parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
1151 struct cfs_lstr addrrange;
1152 struct cfs_lstr net;
1153 struct cfs_lstr tmp;
1154 struct nidrange *nr;
1157 if (cfs_gettok(src, '@', &addrrange) == 0)
1160 if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
1163 nr = add_nidrange(&net, nidlist);
1167 if (parse_addrange(&addrrange, nr) != 0)
1172 fprintf(stderr, "can't parse nidrange: \"%.*s\"\n",
1173 tmp.ls_len, tmp.ls_str);
1178 libcfs_net_str_len(const char *str)
1181 struct netstrfns *nf = NULL;
1183 for (i = 0; i < libcfs_nnetstrfns; i++) {
1184 nf = &libcfs_netstrfns[i];
1185 if (!strncmp(str, nf->nf_name, strlen(nf->nf_name)))
1186 return strlen(nf->nf_name);
1193 parse_net_range(char *str, __u32 len, struct list_head *net_num,
1196 struct cfs_lstr next;
1208 net_type_len = libcfs_net_str_len(str);
1210 if (net_type_len < len) {
1211 char c = str[net_type_len];
1213 str[net_type_len] = '\0';
1214 net = libcfs_str2net(str);
1215 str[net_type_len] = c;
1217 net = libcfs_str2net(str);
1220 if (net == LNET_NIDNET(LNET_NID_ANY))
1223 *net_type = LNET_NETTYP(net);
1226 * the net is either followed with an absolute number, *, or an
1227 * expression enclosed in []
1229 bracket = strchr(next.ls_str, '[');
1230 star = strchr(next.ls_str, '*');
1232 /* "*[" pattern not allowed */
1233 if (bracket && star && star < bracket)
1237 next.ls_str = str + net_type_len;
1238 next.ls_len = strlen(next.ls_str);
1240 next.ls_str = bracket;
1241 next.ls_len = strlen(bracket);
1244 /* if there is no net number just return */
1245 if (next.ls_len == 0)
1248 return libcfs_num_parse(next.ls_str, next.ls_len,
1253 parse_address(struct cfs_lstr *src, const __u32 net_type,
1254 struct list_head *addr)
1257 struct netstrfns *nf = NULL;
1259 for (i = 0; i < libcfs_nnetstrfns; i++) {
1260 nf = &libcfs_netstrfns[i];
1261 if (net_type == nf->nf_type)
1262 return nf->nf_parse_addrlist(src->ls_str, src->ls_len,
1270 cfs_parse_nid_parts(char *str, struct list_head *addr,
1271 struct list_head *net_num, __u32 *net_type)
1273 struct cfs_lstr next;
1274 struct cfs_lstr addrrange;
1282 next.ls_len = strlen(str);
1284 rc = cfs_gettok(&next, '@', &addrrange);
1289 /* only net is present */
1291 next.ls_len = strlen(str);
1296 /* assume only net is present */
1297 rc = parse_net_range(next.ls_str, next.ls_len, net_num, net_type);
1300 * if we successfully parsed the net range and there is no
1301 * address, or if we fail to parse the net range then return
1303 if ((!rc && !found) || rc)
1306 return parse_address(&addrrange, *net_type, addr);
1310 * Frees addrrange structures of \a list.
1312 * For each struct addrrange structure found on \a list it frees
1313 * cfs_expr_list list attached to it and frees the addrrange itself.
1318 free_addrranges(struct list_head *list)
1320 while (!list_empty(list)) {
1321 struct addrrange *ar;
1323 ar = list_first_entry(list, struct addrrange, ar_link);
1325 cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
1326 list_del(&ar->ar_link);
1332 * Frees nidrange strutures of \a list.
1334 * For each struct nidrange structure found on \a list it frees
1335 * addrrange list attached to it and frees the nidrange itself.
1340 cfs_free_nidlist(struct list_head *list)
1342 struct list_head *pos, *next;
1343 struct nidrange *nr;
1345 list_for_each_safe(pos, next, list) {
1346 nr = list_entry(pos, struct nidrange, nr_link);
1347 free_addrranges(&nr->nr_addrranges);
1354 * Parses nid range list.
1356 * Parses with rigorous syntax and overflow checking \a str into
1357 * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
1358 * structures and links that structure to \a nidlist. The resulting
1359 * list can be used to match a NID againts set of NIDS defined by \a
1361 * \see cfs_match_nid
1363 * \retval 1 on success
1364 * \retval 0 otherwise
1367 cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
1369 struct cfs_lstr src;
1370 struct cfs_lstr res;
1375 INIT_LIST_HEAD(nidlist);
1376 while (src.ls_str) {
1377 rc = cfs_gettok(&src, ' ', &res);
1379 cfs_free_nidlist(nidlist);
1382 rc = parse_nidrange(&res, nidlist);
1384 cfs_free_nidlist(nidlist);
1392 * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
1394 * \see cfs_parse_nidlist()
1396 * \retval 1 on match
1397 * \retval 0 otherwises
1399 int cfs_match_nid(struct lnet_nid *nid, struct list_head *nidlist)
1401 struct nidrange *nr;
1402 struct addrrange *ar;
1404 if (!nid_is_nid4(nid))
1406 list_for_each_entry(nr, nidlist, nr_link) {
1407 if (nr->nr_netstrfns->nf_type != nid->nid_type)
1409 if (nr->nr_netnum != __be16_to_cpu(nid->nid_num))
1413 list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
1414 if (nr->nr_netstrfns->nf_match_addr(
1415 __be32_to_cpu(nid->nid_addr[0]),
1416 &ar->ar_numaddr_ranges))
1423 cfs_match_net(__u32 net_id, __u32 net_type, struct list_head *net_num_list)
1430 if (net_type != LNET_NETTYP(net_id))
1433 net_num = LNET_NETNUM(net_id);
1436 * if there is a net number but the list passed in is empty, then
1437 * there is no match.
1439 if (!net_num && list_empty(net_num_list))
1441 else if (list_empty(net_num_list))
1444 if (!libcfs_num_match(net_num, net_num_list))
1451 * Print the network part of the nidrange \a nr into the specified \a buffer.
1453 * \retval number of characters written
1456 cfs_print_network(char *buffer, int count, struct nidrange *nr)
1458 struct netstrfns *nf = nr->nr_netstrfns;
1460 if (nr->nr_netnum == 0)
1461 return scnprintf(buffer, count, "@%s", nf->nf_name);
1463 return scnprintf(buffer, count, "@%s%u",
1464 nf->nf_name, nr->nr_netnum);
1469 * Print a list of addrrange (\a addrranges) into the specified \a buffer.
1470 * At max \a count characters can be printed into \a buffer.
1472 * \retval number of characters written
1475 cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges,
1476 struct nidrange *nr)
1479 struct addrrange *ar;
1480 struct netstrfns *nf = nr->nr_netstrfns;
1482 list_for_each_entry(ar, addrranges, ar_link) {
1484 i += scnprintf(buffer + i, count - i, " ");
1485 i += nf->nf_print_addrlist(buffer + i, count - i,
1486 &ar->ar_numaddr_ranges);
1487 i += cfs_print_network(buffer + i, count - i, nr);
1493 * Print a list of nidranges (\a nidlist) into the specified \a buffer.
1494 * At max \a count characters can be printed into \a buffer.
1495 * Nidranges are separated by a space character.
1497 * \retval number of characters written
1499 int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
1502 struct nidrange *nr;
1507 list_for_each_entry(nr, nidlist, nr_link) {
1509 i += scnprintf(buffer + i, count - i, " ");
1511 if (nr->nr_all != 0) {
1512 assert(list_empty(&nr->nr_addrranges));
1513 i += scnprintf(buffer + i, count - i, "*");
1514 i += cfs_print_network(buffer + i, count - i, nr);
1516 i += cfs_print_addrranges(buffer + i, count - i,
1517 &nr->nr_addrranges, nr);
1524 * Determines minimum and maximum addresses for a single
1525 * numeric address range
1528 * \param[out] *min_nid __u32 representation of min NID
1529 * \param[out] *max_nid __u32 representation of max NID
1530 * \retval -EINVAL unsupported LNET range
1531 * \retval -ERANGE non-contiguous LNET range
1533 static int cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1536 struct cfs_expr_list *expr_list;
1537 struct cfs_range_expr *range;
1538 unsigned int min_ip[4] = {0};
1539 unsigned int max_ip[4] = {0};
1541 bool expect_full_octet = false;
1543 list_for_each_entry(expr_list, &ar->ar_numaddr_ranges, el_link) {
1546 list_for_each_entry(range, &expr_list->el_exprs, re_link) {
1547 /* XXX: add support for multiple & non-contig. re's */
1551 /* if a previous octet was ranged, then all remaining
1552 * octets must be full for contiguous range */
1553 if (expect_full_octet && (range->re_lo != 0 ||
1554 range->re_hi != 255))
1557 if (range->re_stride != 1)
1560 if (range->re_lo > range->re_hi)
1563 if (range->re_lo != range->re_hi)
1564 expect_full_octet = true;
1566 min_ip[cur_octet] = range->re_lo;
1567 max_ip[cur_octet] = range->re_hi;
1575 if (min_nid != NULL)
1576 *min_nid = ((min_ip[0] << 24) | (min_ip[1] << 16) |
1577 (min_ip[2] << 8) | min_ip[3]);
1579 if (max_nid != NULL)
1580 *max_nid = ((max_ip[0] << 24) | (max_ip[1] << 16) |
1581 (max_ip[2] << 8) | max_ip[3]);
1587 * Determines minimum and maximum addresses for a single
1588 * numeric address range
1591 * \param[out] *min_nid __u32 representation of min NID
1592 * \param[out] *max_nid __u32 representation of max NID
1593 * \retval -EINVAL unsupported LNET range
1595 static int cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1598 struct cfs_expr_list *el;
1599 struct cfs_range_expr *re;
1600 unsigned int min_addr = 0;
1601 unsigned int max_addr = 0;
1603 list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
1606 list_for_each_entry(re, &el->el_exprs, re_link) {
1609 if (re->re_lo > re->re_hi)
1612 if (re->re_lo < min_addr || min_addr == 0)
1613 min_addr = re->re_lo;
1614 if (re->re_hi > max_addr)
1615 max_addr = re->re_hi;
1621 if (min_nid != NULL)
1622 *min_nid = min_addr;
1623 if (max_nid != NULL)
1624 *max_nid = max_addr;
1630 * Takes a linked list of nidrange expressions, determines the minimum
1631 * and maximum nid and creates appropriate nid structures
1634 * \param[out] *min_nid string representation of min NID
1635 * \param[out] *max_nid string representation of max NID
1636 * \retval -EINVAL unsupported LNET range
1637 * \retval -ERANGE non-contiguous LNET range
1639 int cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
1640 char *max_nid, size_t nidstr_length)
1642 struct nidrange *first_nidrange;
1644 struct netstrfns *nf;
1648 char min_addr_str[IPSTRING_LENGTH];
1649 char max_addr_str[IPSTRING_LENGTH];
1652 first_nidrange = list_first_entry(nidlist, struct nidrange, nr_link);
1654 netnum = first_nidrange->nr_netnum;
1655 nf = first_nidrange->nr_netstrfns;
1656 lndname = nf->nf_name;
1658 rc = nf->nf_min_max(nidlist, &min_addr, &max_addr);
1662 nf->nf_addr2str(min_addr, min_addr_str, sizeof(min_addr_str));
1663 nf->nf_addr2str(max_addr, max_addr_str, sizeof(max_addr_str));
1665 snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
1667 snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
1674 * Determines the min and max NID values for num LNDs
1677 * \param[out] *min_nid if provided, returns string representation of min NID
1678 * \param[out] *max_nid if provided, returns string representation of max NID
1679 * \retval -EINVAL unsupported LNET range
1680 * \retval -ERANGE non-contiguous LNET range
1682 static int cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
1685 struct nidrange *nr;
1686 struct addrrange *ar;
1687 unsigned int tmp_min_addr = 0;
1688 unsigned int tmp_max_addr = 0;
1689 unsigned int min_addr = 0;
1690 unsigned int max_addr = 0;
1691 int nidlist_count = 0;
1694 list_for_each_entry(nr, nidlist, nr_link) {
1695 if (nidlist_count > 0)
1698 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1699 rc = cfs_num_ar_min_max(ar, &tmp_min_addr,
1704 if (tmp_min_addr < min_addr || min_addr == 0)
1705 min_addr = tmp_min_addr;
1706 if (tmp_max_addr > max_addr)
1707 max_addr = tmp_min_addr;
1710 if (max_nid != NULL)
1711 *max_nid = max_addr;
1712 if (min_nid != NULL)
1713 *min_nid = min_addr;
1719 * Takes an nidlist and determines the minimum and maximum
1723 * \param[out] *min_nid if provided, returns string representation of min NID
1724 * \param[out] *max_nid if provided, returns string representation of max NID
1725 * \retval -EINVAL unsupported LNET range
1726 * \retval -ERANGE non-contiguous LNET range
1728 static int cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
1731 struct nidrange *nr;
1732 struct addrrange *ar;
1733 __u32 tmp_min_ip_addr = 0;
1734 __u32 tmp_max_ip_addr = 0;
1735 __u32 min_ip_addr = 0;
1736 __u32 max_ip_addr = 0;
1737 int nidlist_count = 0;
1740 list_for_each_entry(nr, nidlist, nr_link) {
1741 if (nidlist_count > 0)
1746 max_ip_addr = 0xffffffff;
1750 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1751 rc = cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
1756 if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
1757 min_ip_addr = tmp_min_ip_addr;
1758 if (tmp_max_ip_addr > max_ip_addr)
1759 max_ip_addr = tmp_max_ip_addr;
1765 if (max_nid != NULL)
1766 *max_nid = max_ip_addr;
1767 if (min_nid != NULL)
1768 *min_nid = min_ip_addr;
1774 libcfs_expand_nidrange(struct nidrange *nr, __u32 *addrs, int max_nids)
1776 struct addrrange *ar;
1777 int rc = 0, count = max_nids;
1778 struct netstrfns *nf = nr->nr_netstrfns;
1780 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1781 rc = nf->nf_expand_addrrange(&ar->ar_numaddr_ranges, addrs,
1789 return max_nids - count;
1792 int cfs_expand_nidlist(struct list_head *nidlist, lnet_nid_t *lnet_nidlist,
1795 struct nidrange *nr;
1796 int rc = 0, count = max_nids;
1799 struct netstrfns *nf;
1802 addrs = calloc(max_nids, sizeof(__u32));
1806 list_for_each_entry(nr, nidlist, nr_link) {
1807 rc = libcfs_expand_nidrange(nr, addrs, count);
1814 nf = nr->nr_netstrfns;
1815 net = LNET_MKNET(nf->nf_type, nr->nr_netnum);
1817 for (i = count - 1; i >= count - rc; i--)
1818 lnet_nidlist[j++] = LNET_MKNID(net, addrs[i]);
1824 return max_nids - count;