Whamcloud - gitweb
LU-4423 lnet: Avoid forward declarations in nidstring.c
[fs/lustre-release.git] / libcfs / libcfs / util / nidstrings.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2014, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/libcfs/util/nidstrings.c
37  *
38  * Author: Phil Schwan <phil@clusterfs.com>
39  */
40
41 #define DEBUG_SUBSYSTEM S_LNET
42
43 #include <assert.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdbool.h>
47 #include <stdlib.h>
48 #include <string.h>
49
50 #include <libcfs/util/string.h>
51 #include <lnet/types.h>
52 #include <lnet/nidstr.h>
53 #ifdef HAVE_NETDB_H
54 # include <netdb.h>
55 #endif
56
57 /* max value for numeric network address */
58 #define MAX_NUMERIC_VALUE 0xffffffff
59
60 #define IPSTRING_LENGTH 16
61
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...
65  */
66
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.
72  */
73
74 static char      libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
75 static int       libcfs_nidstring_idx;
76
77 char *
78 libcfs_next_nidstring(void)
79 {
80         char          *str;
81
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;
86
87         return str;
88 }
89
90 static int
91 libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
92 {
93         *addr = 0;
94         return 1;
95 }
96
97 static void
98 libcfs_ip_addr2str(__u32 addr, char *str, size_t size)
99 {
100         snprintf(str, size, "%u.%u.%u.%u",
101                  (addr >> 24) & 0xff, (addr >> 16) & 0xff,
102                  (addr >> 8) & 0xff, addr & 0xff);
103 }
104
105 /* CAVEAT EMPTOR XscanfX
106  * I use "%n" at the end of a sscanf format to detect trailing junk.  However
107  * sscanf may return immediately if it sees the terminating '0' in a string, so
108  * I initialise the %n variable to the expected length.  If sscanf sets it;
109  * fine, if it doesn't, then the scan ended at the end of the string, which is
110  * fine too :) */
111 static int
112 libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
113 {
114         unsigned int    a;
115         unsigned int    b;
116         unsigned int    c;
117         unsigned int    d;
118         int             n = nob; /* XscanfX */
119
120         /* numeric IP? */
121         if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
122             n == nob &&
123             (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
124             (c & ~0xff) == 0 && (d & ~0xff) == 0) {
125                 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
126                 return 1;
127         }
128
129 #ifdef HAVE_GETHOSTBYNAME
130         /* known hostname? */
131         if (('a' <= str[0] && str[0] <= 'z') ||
132             ('A' <= str[0] && str[0] <= 'Z')) {
133                 char *tmp;
134
135                 tmp = calloc(1, nob + 1);
136                 if (tmp != NULL) {
137                         struct hostent *he;
138
139                         memcpy(tmp, str, nob);
140                         tmp[nob] = 0;
141
142                         he = gethostbyname(tmp);
143
144                         free(tmp);
145
146                         if (he != NULL) {
147                                 __u32 ip = *(__u32 *)he->h_addr;
148
149                                 *addr = ntohl(ip);
150                                 return 1;
151                         }
152                 }
153         }
154 #endif
155         return 0;
156 }
157
158 static int
159 libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
160 {
161         int i = 0, j = 0;
162         struct cfs_expr_list *el;
163
164         list_for_each_entry(el, list, el_link) {
165                 assert(j++ < 4);
166                 if (i != 0)
167                         i += snprintf(buffer + i, count - i, ".");
168                 i += cfs_expr_list_print(buffer + i, count - i, el);
169         }
170         return i;
171 }
172
173 static void
174 libcfs_decnum_addr2str(__u32 addr, char *str, size_t size)
175 {
176         snprintf(str, size, "%u", addr);
177 }
178
179 static void
180 libcfs_hexnum_addr2str(__u32 addr, char *str, size_t size)
181 {
182         snprintf(str, size, "0x%x", addr);
183 }
184
185 static int
186 libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
187 {
188         int     n;
189
190         n = nob;
191         if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
192                 return 1;
193
194         n = nob;
195         if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
196                 return 1;
197
198         n = nob;
199         if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
200                 return 1;
201
202         return 0;
203 }
204
205 /**
206  * Nf_parse_addrlist method for networks using numeric addresses.
207  *
208  * Examples of such networks are gm and elan.
209  *
210  * \retval 0 if \a str parsed to numeric address
211  * \retval errno otherwise
212  */
213 static int
214 libcfs_num_parse(char *str, int len, struct list_head *list)
215 {
216         struct cfs_expr_list *el;
217         int     rc;
218
219         rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
220         if (rc == 0)
221                 list_add_tail(&el->el_link, list);
222
223         return rc;
224 }
225
226 static int
227 libcfs_num_addr_range_print(char *buffer, int count, struct list_head *list)
228 {
229         struct cfs_expr_list *el;
230         int i = 0, j = 0;
231
232         list_for_each_entry(el, list, el_link) {
233                 assert(j++ < 1);
234                 i += cfs_expr_list_print(buffer + i, count - i, el);
235         }
236         return i;
237 }
238
239 /*
240  * Nf_match_addr method for networks using numeric addresses
241  *
242  * \retval 1 on match
243  * \retval 0 otherwise
244  */
245 static int
246 libcfs_num_match(__u32 addr, struct list_head *numaddr)
247 {
248         struct cfs_expr_list *el;
249
250         assert(!list_empty(numaddr));
251         el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
252
253         return cfs_expr_list_match(addr, el);
254 }
255
256 static bool cfs_ip_is_contiguous(struct list_head *nidlist);
257 static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
258 static bool cfs_num_is_contiguous(struct list_head *nidlist);
259 static void cfs_num_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
260
261 static struct netstrfns  libcfs_netstrfns[] = {
262         {/* .nf_type      */  LOLND,
263          /* .nf_name      */  "lo",
264          /* .nf_modname   */  "klolnd",
265          /* .nf_addr2str  */  libcfs_decnum_addr2str,
266          /* .nf_str2addr  */  libcfs_lo_str2addr,
267          /* .nf_parse_addr*/  libcfs_num_parse,
268          /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
269          /* .nf_match_addr*/      libcfs_num_match,
270          /* .nf_is_contiguous */  cfs_num_is_contiguous,
271          /* .nf_min_max   */      cfs_num_min_max},
272         {/* .nf_type      */  SOCKLND,
273          /* .nf_name      */  "tcp",
274          /* .nf_modname   */  "ksocklnd",
275          /* .nf_addr2str  */  libcfs_ip_addr2str,
276          /* .nf_str2addr  */  libcfs_ip_str2addr,
277          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
278          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
279          /* .nf_match_addr*/      cfs_ip_addr_match,
280          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
281          /* .nf_min_max   */      cfs_ip_min_max},
282         {/* .nf_type      */  O2IBLND,
283          /* .nf_name      */  "o2ib",
284          /* .nf_modname   */  "ko2iblnd",
285          /* .nf_addr2str  */  libcfs_ip_addr2str,
286          /* .nf_str2addr  */  libcfs_ip_str2addr,
287          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
288          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
289          /* .nf_match_addr*/      cfs_ip_addr_match,
290          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
291          /* .nf_min_max   */      cfs_ip_min_max},
292         {/* .nf_type      */  CIBLND,
293          /* .nf_name      */  "cib",
294          /* .nf_modname   */  "kciblnd",
295          /* .nf_addr2str  */  libcfs_ip_addr2str,
296          /* .nf_str2addr  */  libcfs_ip_str2addr,
297          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
298          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
299          /* .nf_match_addr*/      cfs_ip_addr_match,
300          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
301          /* .nf_min_max   */      cfs_ip_min_max},
302         {/* .nf_type      */  OPENIBLND,
303          /* .nf_name      */  "openib",
304          /* .nf_modname   */  "kopeniblnd",
305          /* .nf_addr2str  */  libcfs_ip_addr2str,
306          /* .nf_str2addr  */  libcfs_ip_str2addr,
307          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
308          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
309          /* .nf_match_addr*/      cfs_ip_addr_match,
310          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
311          /* .nf_min_max   */      cfs_ip_min_max},
312         {/* .nf_type      */  IIBLND,
313          /* .nf_name      */  "iib",
314          /* .nf_modname   */  "kiiblnd",
315          /* .nf_addr2str  */  libcfs_ip_addr2str,
316          /* .nf_str2addr  */  libcfs_ip_str2addr,
317          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
318          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
319          /* .nf_match_addr*/      cfs_ip_addr_match,
320          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
321          /* .nf_min_max   */      cfs_ip_min_max},
322         {/* .nf_type      */  VIBLND,
323          /* .nf_name      */  "vib",
324          /* .nf_modname   */  "kviblnd",
325          /* .nf_addr2str  */  libcfs_ip_addr2str,
326          /* .nf_str2addr  */  libcfs_ip_str2addr,
327          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
328          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
329          /* .nf_match_addr*/      cfs_ip_addr_match,
330          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
331          /* .nf_min_max   */      cfs_ip_min_max},
332         {/* .nf_type      */  RALND,
333          /* .nf_name      */  "ra",
334          /* .nf_modname   */  "kralnd",
335          /* .nf_addr2str  */  libcfs_ip_addr2str,
336          /* .nf_str2addr  */  libcfs_ip_str2addr,
337          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
338          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
339          /* .nf_match_addr*/      cfs_ip_addr_match,
340          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
341          /* .nf_min_max   */      cfs_ip_min_max},
342         {/* .nf_type      */      QSWLND,
343          /* .nf_name      */      "elan",
344          /* .nf_modname   */      "kqswlnd",
345          /* .nf_addr2str  */      libcfs_decnum_addr2str,
346          /* .nf_str2addr  */      libcfs_num_str2addr,
347          /* .nf_parse_addrlist*/  libcfs_num_parse,
348          /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
349          /* .nf_match_addr*/      libcfs_num_match,
350          /* .nf_is_contiguous */  cfs_num_is_contiguous,
351          /* .nf_min_max   */      cfs_num_min_max},
352         {/* .nf_type      */      GMLND,
353          /* .nf_name      */      "gm",
354          /* .nf_modname   */      "kgmlnd",
355          /* .nf_addr2str  */      libcfs_hexnum_addr2str,
356          /* .nf_str2addr  */      libcfs_num_str2addr,
357          /* .nf_parse_addrlist*/  libcfs_num_parse,
358          /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
359          /* .nf_match_addr*/      libcfs_num_match,
360          /* .nf_is_contiguous */  cfs_num_is_contiguous,
361          /* .nf_min_max   */      cfs_num_min_max},
362         {/* .nf_type      */      MXLND,
363          /* .nf_name      */      "mx",
364          /* .nf_modname   */      "kmxlnd",
365          /* .nf_addr2str  */      libcfs_ip_addr2str,
366          /* .nf_str2addr  */      libcfs_ip_str2addr,
367          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
368          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
369          /* .nf_match_addr*/      cfs_ip_addr_match,
370          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
371          /* .nf_min_max   */      cfs_ip_min_max},
372         {/* .nf_type      */      PTLLND,
373          /* .nf_name      */      "ptl",
374          /* .nf_modname   */      "kptllnd",
375          /* .nf_addr2str  */      libcfs_decnum_addr2str,
376          /* .nf_str2addr  */      libcfs_num_str2addr,
377          /* .nf_parse_addrlist*/  libcfs_num_parse,
378          /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
379          /* .nf_match_addr*/      libcfs_num_match,
380          /* .nf_is_contiguous */  cfs_num_is_contiguous,
381          /* .nf_min_max   */      cfs_num_min_max},
382         {/* .nf_type      */      GNILND,
383          /* .nf_name      */      "gni",
384          /* .nf_modname   */      "kgnilnd",
385          /* .nf_addr2str  */      libcfs_decnum_addr2str,
386          /* .nf_str2addr  */      libcfs_num_str2addr,
387          /* .nf_parse_addrlist*/  libcfs_num_parse,
388          /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
389          /* .nf_match_addr*/      libcfs_num_match,
390          /* .nf_is_contiguous */  cfs_num_is_contiguous,
391          /* .nf_min_max   */      cfs_num_min_max},
392         {/* .nf_type      */      GNIIPLND,
393          /* .nf_name      */      "gip",
394          /* .nf_modname   */      "kgnilnd",
395          /* .nf_addr2str  */      libcfs_ip_addr2str,
396          /* .nf_str2addr  */      libcfs_ip_str2addr,
397          /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
398          /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
399          /* .nf_match_addr*/      cfs_ip_addr_match,
400          /* .nf_is_contiguous */  cfs_ip_is_contiguous,
401          /* .nf_min_max   */      cfs_ip_min_max},
402          /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
403         {/* .nf_type      */  -1},
404 };
405
406 static const size_t libcfs_nnetstrfns =
407         sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
408
409 static struct netstrfns *
410 libcfs_lnd2netstrfns(__u32 lnd)
411 {
412         int     i;
413
414         for (i = 0; i < libcfs_nnetstrfns; i++)
415                 if (lnd == libcfs_netstrfns[i].nf_type)
416                         return &libcfs_netstrfns[i];
417
418         return NULL;
419 }
420
421 static struct netstrfns *
422 libcfs_namenum2netstrfns(const char *name)
423 {
424         struct netstrfns *nf;
425         int               i;
426
427         for (i = 0; i < libcfs_nnetstrfns; i++) {
428                 nf = &libcfs_netstrfns[i];
429                 if (nf->nf_type >= 0 &&
430                     !strncmp(name, nf->nf_name, strlen(nf->nf_name)))
431                         return nf;
432         }
433         return NULL;
434 }
435
436 static struct netstrfns *
437 libcfs_name2netstrfns(const char *name)
438 {
439         int    i;
440
441         for (i = 0; i < libcfs_nnetstrfns; i++)
442                 if (libcfs_netstrfns[i].nf_type >= 0 &&
443                     !strcmp(libcfs_netstrfns[i].nf_name, name))
444                         return &libcfs_netstrfns[i];
445
446         return NULL;
447 }
448
449 int
450 libcfs_isknown_lnd(__u32 lnd)
451 {
452         return libcfs_lnd2netstrfns(lnd) != NULL;
453 }
454
455 char *
456 libcfs_lnd2modname(__u32 lnd)
457 {
458         struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
459
460         return (nf == NULL) ? NULL : nf->nf_modname;
461 }
462
463 int
464 libcfs_str2lnd(const char *str)
465 {
466         struct netstrfns *nf = libcfs_name2netstrfns(str);
467
468         if (nf != NULL)
469                 return nf->nf_type;
470
471         return -1;
472 }
473
474 char *
475 libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size)
476 {
477         struct netstrfns *nf;
478
479         nf = libcfs_lnd2netstrfns(lnd);
480         if (nf == NULL)
481                 snprintf(buf, buf_size, "?%u?", lnd);
482         else
483                 snprintf(buf, buf_size, "%s", nf->nf_name);
484
485         return buf;
486 }
487
488 char *
489 libcfs_net2str_r(__u32 net, char *buf, size_t buf_size)
490 {
491         __u32             nnum = LNET_NETNUM(net);
492         __u32             lnd  = LNET_NETTYP(net);
493         struct netstrfns *nf;
494
495         nf = libcfs_lnd2netstrfns(lnd);
496         if (nf == NULL)
497                 snprintf(buf, buf_size, "<%u:%u>", lnd, nnum);
498         else if (nnum == 0)
499                 snprintf(buf, buf_size, "%s", nf->nf_name);
500         else
501                 snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum);
502
503         return buf;
504 }
505
506 char *
507 libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size)
508 {
509         __u32             addr = LNET_NIDADDR(nid);
510         __u32             net  = LNET_NIDNET(nid);
511         __u32             nnum = LNET_NETNUM(net);
512         __u32             lnd  = LNET_NETTYP(net);
513         struct netstrfns *nf;
514
515         if (nid == LNET_NID_ANY) {
516                 strncpy(buf, "<?>", buf_size);
517                 buf[buf_size - 1] = '\0';
518                 return buf;
519         }
520
521         nf = libcfs_lnd2netstrfns(lnd);
522         if (nf == NULL) {
523                 snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum);
524         } else {
525                 size_t addr_len;
526
527                 nf->nf_addr2str(addr, buf, buf_size);
528                 addr_len = strlen(buf);
529                 if (nnum == 0)
530                         snprintf(buf + addr_len, buf_size - addr_len, "@%s",
531                                  nf->nf_name);
532                 else
533                         snprintf(buf + addr_len, buf_size - addr_len, "@%s%u",
534                                  nf->nf_name, nnum);
535         }
536
537         return buf;
538 }
539
540 static struct netstrfns *
541 libcfs_str2net_internal(const char *str, __u32 *net)
542 {
543         struct netstrfns *nf = NULL;
544         int               nob;
545         unsigned int      netnum;
546         int               i;
547
548         for (i = 0; i < libcfs_nnetstrfns; i++) {
549                 nf = &libcfs_netstrfns[i];
550                 if (nf->nf_type >= 0 &&
551                     !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
552                         break;
553         }
554
555         if (i == libcfs_nnetstrfns)
556                 return NULL;
557
558         nob = strlen(nf->nf_name);
559
560         if (strlen(str) == (unsigned int)nob) {
561                 netnum = 0;
562         } else {
563                 if (nf->nf_type == LOLND) /* net number not allowed */
564                         return NULL;
565
566                 str += nob;
567                 i = strlen(str);
568                 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
569                     i != (int)strlen(str))
570                         return NULL;
571         }
572
573         *net = LNET_MKNET(nf->nf_type, netnum);
574         return nf;
575 }
576
577 __u32
578 libcfs_str2net(const char *str)
579 {
580         __u32  net;
581
582         if (libcfs_str2net_internal(str, &net) != NULL)
583                 return net;
584
585         return LNET_NIDNET(LNET_NID_ANY);
586 }
587
588 lnet_nid_t
589 libcfs_str2nid(const char *str)
590 {
591         const char       *sep = strchr(str, '@');
592         struct netstrfns *nf;
593         __u32             net;
594         __u32             addr;
595
596         if (sep != NULL) {
597                 nf = libcfs_str2net_internal(sep + 1, &net);
598                 if (nf == NULL)
599                         return LNET_NID_ANY;
600         } else {
601                 sep = str + strlen(str);
602                 net = LNET_MKNET(SOCKLND, 0);
603                 nf = libcfs_lnd2netstrfns(SOCKLND);
604                 assert(nf != NULL);
605         }
606
607         if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
608                 return LNET_NID_ANY;
609
610         return LNET_MKNID(net, addr);
611 }
612
613 char *
614 libcfs_id2str(lnet_process_id_t id)
615 {
616         char *str = libcfs_next_nidstring();
617
618         if (id.pid == LNET_PID_ANY) {
619                 snprintf(str, LNET_NIDSTR_SIZE,
620                          "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
621                 return str;
622         }
623
624         snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
625                  ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
626                  (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
627         return str;
628 }
629
630 int
631 libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
632 {
633         if (!strcmp(str, "*")) {
634                 *nidp = LNET_NID_ANY;
635                 return 1;
636         }
637
638         *nidp = libcfs_str2nid(str);
639         return *nidp != LNET_NID_ANY;
640 }
641
642 /**
643  * Nid range list syntax.
644  * \verbatim
645  *
646  * <nidlist>         :== <nidrange> [ ' ' <nidrange> ]
647  * <nidrange>        :== <addrrange> '@' <net>
648  * <addrrange>       :== '*' |
649  *                       <ipaddr_range> |
650  *                       <cfs_expr_list>
651  * <ipaddr_range>    :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
652  *                       <cfs_expr_list>
653  * <cfs_expr_list>   :== <number> |
654  *                       <expr_list>
655  * <expr_list>       :== '[' <range_expr> [ ',' <range_expr>] ']'
656  * <range_expr>      :== <number> |
657  *                       <number> '-' <number> |
658  *                       <number> '-' <number> '/' <number>
659  * <net>             :== <netname> | <netname><number>
660  * <netname>         :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" |
661  *                       "vib" | "ra" | "elan" | "mx" | "ptl"
662  * \endverbatim
663  */
664
665 /**
666  * Structure to represent \<nidrange\> token of the syntax.
667  *
668  * One of this is created for each \<net\> parsed.
669  */
670 struct nidrange {
671         /**
672          * Link to list of this structures which is built on nid range
673          * list parsing.
674          */
675         struct list_head nr_link;
676         /**
677          * List head for addrrange::ar_link.
678          */
679         struct list_head nr_addrranges;
680         /**
681          * Flag indicating that *@<net> is found.
682          */
683         int nr_all;
684         /**
685          * Pointer to corresponding element of libcfs_netstrfns.
686          */
687         struct netstrfns *nr_netstrfns;
688         /**
689          * Number of network. E.g. 5 if \<net\> is "elan5".
690          */
691         int nr_netnum;
692 };
693
694 /**
695  * Structure to represent \<addrrange\> token of the syntax.
696  */
697 struct addrrange {
698         /**
699          * Link to nidrange::nr_addrranges.
700          */
701         struct list_head ar_link;
702         /**
703          * List head for cfs_expr_list::el_list.
704          */
705         struct list_head ar_numaddr_ranges;
706 };
707
708 /**
709  * Parses \<addrrange\> token on the syntax.
710  *
711  * Allocates struct addrrange and links to \a nidrange via
712  * (nidrange::nr_addrranges)
713  *
714  * \retval 0 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
715  * \retval -errno otherwise
716  */
717 static int
718 parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
719 {
720         struct addrrange *addrrange;
721
722         if (src->ls_len == 1 && src->ls_str[0] == '*') {
723                 nidrange->nr_all = 1;
724                 return 0;
725         }
726
727         addrrange = calloc(1, sizeof(struct addrrange));
728         if (addrrange == NULL)
729                 return -ENOMEM;
730         list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
731         INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
732
733         return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
734                                                 src->ls_len,
735                                                 &addrrange->ar_numaddr_ranges);
736 }
737
738 /**
739  * Finds or creates struct nidrange.
740  *
741  * Checks if \a src is a valid network name, looks for corresponding
742  * nidrange on the ist of nidranges (\a nidlist), creates new struct
743  * nidrange if it is not found.
744  *
745  * \retval pointer to struct nidrange matching network specified via \a src
746  * \retval NULL if \a src does not match any network
747  */
748 static struct nidrange *
749 add_nidrange(const struct cfs_lstr *src,
750              struct list_head *nidlist)
751 {
752         struct netstrfns *nf;
753         struct nidrange *nr;
754         int endlen;
755         unsigned netnum;
756
757         if (src->ls_len >= LNET_NIDSTR_SIZE)
758                 return NULL;
759
760         nf = libcfs_namenum2netstrfns(src->ls_str);
761         if (nf == NULL)
762                 return NULL;
763         endlen = src->ls_len - strlen(nf->nf_name);
764         if (endlen == 0)
765                 /* network name only, e.g. "elan" or "tcp" */
766                 netnum = 0;
767         else {
768                 /* e.g. "elan25" or "tcp23", refuse to parse if
769                  * network name is not appended with decimal or
770                  * hexadecimal number */
771                 if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
772                                        endlen, &netnum, 0, MAX_NUMERIC_VALUE))
773                         return NULL;
774         }
775
776         list_for_each_entry(nr, nidlist, nr_link) {
777                 if (nr->nr_netstrfns != nf)
778                         continue;
779                 if (nr->nr_netnum != netnum)
780                         continue;
781                 return nr;
782         }
783
784         nr = calloc(1, sizeof(struct nidrange));
785         if (nr == NULL)
786                 return NULL;
787         list_add_tail(&nr->nr_link, nidlist);
788         INIT_LIST_HEAD(&nr->nr_addrranges);
789         nr->nr_netstrfns = nf;
790         nr->nr_all = 0;
791         nr->nr_netnum = netnum;
792
793         return nr;
794 }
795
796 /**
797  * Parses \<nidrange\> token of the syntax.
798  *
799  * \retval 1 if \a src parses to \<addrrange\> '@' \<net\>
800  * \retval 0 otherwise
801  */
802 static int
803 parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
804 {
805         struct cfs_lstr addrrange;
806         struct cfs_lstr net;
807         struct cfs_lstr tmp;
808         struct nidrange *nr;
809
810         tmp = *src;
811         if (cfs_gettok(src, '@', &addrrange) == 0)
812                 goto failed;
813
814         if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
815                 goto failed;
816
817         nr = add_nidrange(&net, nidlist);
818         if (nr == NULL)
819                 goto failed;
820
821         if (parse_addrange(&addrrange, nr) != 0)
822                 goto failed;
823
824         return 1;
825  failed:
826         fprintf(stderr, "can't parse nidrange: \"%.*s\"\n",
827                 tmp.ls_len, tmp.ls_str);
828         return 0;
829 }
830
831 /**
832  * Frees addrrange structures of \a list.
833  *
834  * For each struct addrrange structure found on \a list it frees
835  * cfs_expr_list list attached to it and frees the addrrange itself.
836  *
837  * \retval none
838  */
839 static void
840 free_addrranges(struct list_head *list)
841 {
842         while (!list_empty(list)) {
843                 struct addrrange *ar;
844
845                 ar = list_entry(list->next, struct addrrange, ar_link);
846
847                 cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
848                 list_del(&ar->ar_link);
849                 free(ar);
850         }
851 }
852
853 /**
854  * Frees nidrange strutures of \a list.
855  *
856  * For each struct nidrange structure found on \a list it frees
857  * addrrange list attached to it and frees the nidrange itself.
858  *
859  * \retval none
860  */
861 void
862 cfs_free_nidlist(struct list_head *list)
863 {
864         struct list_head *pos, *next;
865         struct nidrange *nr;
866
867         list_for_each_safe(pos, next, list) {
868                 nr = list_entry(pos, struct nidrange, nr_link);
869                 free_addrranges(&nr->nr_addrranges);
870                 list_del(pos);
871                 free(nr);
872         }
873 }
874
875 /**
876  * Parses nid range list.
877  *
878  * Parses with rigorous syntax and overflow checking \a str into
879  * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of
880  * structures and links that structure to \a nidlist. The resulting
881  * list can be used to match a NID againts set of NIDS defined by \a
882  * str.
883  * \see cfs_match_nid
884  *
885  * \retval 1 on success
886  * \retval 0 otherwise
887  */
888 int
889 cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
890 {
891         struct cfs_lstr src;
892         struct cfs_lstr res;
893         int rc;
894
895         src.ls_str = str;
896         src.ls_len = len;
897         INIT_LIST_HEAD(nidlist);
898         while (src.ls_str) {
899                 rc = cfs_gettok(&src, ' ', &res);
900                 if (rc == 0) {
901                         cfs_free_nidlist(nidlist);
902                         return 0;
903                 }
904                 rc = parse_nidrange(&res, nidlist);
905                 if (rc == 0) {
906                         cfs_free_nidlist(nidlist);
907                         return 0;
908                 }
909         }
910         return 1;
911 }
912
913 /**
914  * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist).
915  *
916  * \see cfs_parse_nidlist()
917  *
918  * \retval 1 on match
919  * \retval 0  otherwises
920  */
921 int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
922 {
923         struct nidrange *nr;
924         struct addrrange *ar;
925
926         list_for_each_entry(nr, nidlist, nr_link) {
927                 if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
928                         continue;
929                 if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
930                         continue;
931                 if (nr->nr_all)
932                         return 1;
933                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
934                         if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
935                                                         &ar->ar_numaddr_ranges))
936                                 return 1;
937         }
938         return 0;
939 }
940
941 /**
942  * Print the network part of the nidrange \a nr into the specified \a buffer.
943  *
944  * \retval number of characters written
945  */
946 static int
947 cfs_print_network(char *buffer, int count, struct nidrange *nr)
948 {
949         struct netstrfns *nf = nr->nr_netstrfns;
950
951         if (nr->nr_netnum == 0)
952                 return snprintf(buffer, count, "@%s", nf->nf_name);
953         else
954                 return snprintf(buffer, count, "@%s%u",
955                                     nf->nf_name, nr->nr_netnum);
956 }
957
958
959 /**
960  * Print a list of addrrange (\a addrranges) into the specified \a buffer.
961  * At max \a count characters can be printed into \a buffer.
962  *
963  * \retval number of characters written
964  */
965 static int
966 cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges,
967                      struct nidrange *nr)
968 {
969         int i = 0;
970         struct addrrange *ar;
971         struct netstrfns *nf = nr->nr_netstrfns;
972
973         list_for_each_entry(ar, addrranges, ar_link) {
974                 if (i != 0)
975                         i += snprintf(buffer + i, count - i, " ");
976                 i += nf->nf_print_addrlist(buffer + i, count - i,
977                                            &ar->ar_numaddr_ranges);
978                 i += cfs_print_network(buffer + i, count - i, nr);
979         }
980         return i;
981 }
982
983 /**
984  * Print a list of nidranges (\a nidlist) into the specified \a buffer.
985  * At max \a count characters can be printed into \a buffer.
986  * Nidranges are separated by a space character.
987  *
988  * \retval number of characters written
989  */
990 int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
991 {
992         int i = 0;
993         struct nidrange *nr;
994
995         if (count <= 0)
996                 return 0;
997
998         list_for_each_entry(nr, nidlist, nr_link) {
999                 if (i != 0)
1000                         i += snprintf(buffer + i, count - i, " ");
1001
1002                 if (nr->nr_all != 0) {
1003                         assert(list_empty(&nr->nr_addrranges));
1004                         i += snprintf(buffer + i, count - i, "*");
1005                         i += cfs_print_network(buffer + i, count - i, nr);
1006                 } else {
1007                         i += cfs_print_addrranges(buffer + i, count - i,
1008                                                   &nr->nr_addrranges, nr);
1009                 }
1010         }
1011         return i;
1012 }
1013
1014 /**
1015  * Determines minimum and maximum addresses for a single
1016  * numeric address range
1017  *
1018  * \param       ar
1019  * \param       min_nid
1020  * \param       max_nid
1021  */
1022 static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1023                               __u32 *max_nid)
1024 {
1025         struct cfs_expr_list    *el;
1026         struct cfs_range_expr   *re;
1027         __u32                   tmp_ip_addr = 0;
1028         unsigned int            min_ip[4] = {0};
1029         unsigned int            max_ip[4] = {0};
1030         int                     re_count = 0;
1031
1032         list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
1033                 list_for_each_entry(re, &el->el_exprs, re_link) {
1034                         min_ip[re_count] = re->re_lo;
1035                         max_ip[re_count] = re->re_hi;
1036                         re_count++;
1037                 }
1038         }
1039
1040         tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) |
1041                        (min_ip[2] << 8) | min_ip[3]);
1042
1043         if (min_nid != NULL)
1044                 *min_nid = tmp_ip_addr;
1045
1046         tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) |
1047                        (max_ip[2] << 8) | max_ip[3]);
1048
1049         if (max_nid != NULL)
1050                 *max_nid = tmp_ip_addr;
1051 }
1052
1053 /**
1054  * Determines minimum and maximum addresses for a single
1055  * numeric address range
1056  *
1057  * \param       ar
1058  * \param       min_nid
1059  * \param       max_nid
1060  */
1061 static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
1062                                __u32 *max_nid)
1063 {
1064         struct cfs_expr_list    *el;
1065         struct cfs_range_expr   *re;
1066         unsigned int            min_addr = 0;
1067         unsigned int            max_addr = 0;
1068
1069         list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
1070                 list_for_each_entry(re, &el->el_exprs, re_link) {
1071                         if (re->re_lo < min_addr || min_addr == 0)
1072                                 min_addr = re->re_lo;
1073                         if (re->re_hi > max_addr)
1074                                 max_addr = re->re_hi;
1075                 }
1076         }
1077
1078         if (min_nid != NULL)
1079                 *min_nid = min_addr;
1080         if (max_nid != NULL)
1081                 *max_nid = max_addr;
1082 }
1083
1084 /**
1085  * Determines whether an expression list in an nidrange contains exactly
1086  * one contiguous address range. Calls the correct netstrfns for the LND
1087  *
1088  * \param       *nidlist
1089  *
1090  * \retval      true if contiguous
1091  * \retval      false if not contiguous
1092  */
1093 bool cfs_nidrange_is_contiguous(struct list_head *nidlist)
1094 {
1095         struct nidrange         *nr;
1096         struct netstrfns        *nf = NULL;
1097         char                    *lndname = NULL;
1098         int                     netnum = -1;
1099
1100         list_for_each_entry(nr, nidlist, nr_link) {
1101                 nf = nr->nr_netstrfns;
1102                 if (lndname == NULL)
1103                         lndname = nf->nf_name;
1104                 if (netnum == -1)
1105                         netnum = nr->nr_netnum;
1106
1107                 if (strcmp(lndname, nf->nf_name) != 0 ||
1108                     netnum != nr->nr_netnum)
1109                         return false;
1110         }
1111
1112         if (nf == NULL)
1113                 return false;
1114
1115         if (!nf->nf_is_contiguous(nidlist))
1116                 return false;
1117
1118         return true;
1119 }
1120
1121 /**
1122  * Determines whether an expression list in an num nidrange contains exactly
1123  * one contiguous address range.
1124  *
1125  * \param       *nidlist
1126  *
1127  * \retval      true if contiguous
1128  * \retval      false if not contiguous
1129  */
1130 static bool cfs_num_is_contiguous(struct list_head *nidlist)
1131 {
1132         struct nidrange         *nr;
1133         struct addrrange        *ar;
1134         struct cfs_expr_list    *el;
1135         struct cfs_range_expr   *re;
1136         int                     last_hi = 0;
1137         __u32                   last_end_nid = 0;
1138         __u32                   current_start_nid = 0;
1139         __u32                   current_end_nid = 0;
1140
1141         list_for_each_entry(nr, nidlist, nr_link) {
1142                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1143                         cfs_num_ar_min_max(ar, &current_start_nid,
1144                                            &current_end_nid);
1145                         if (last_end_nid != 0 &&
1146                             (current_start_nid - last_end_nid != 1))
1147                                         return false;
1148                         last_end_nid = current_end_nid;
1149                         list_for_each_entry(el, &ar->ar_numaddr_ranges,
1150                                             el_link) {
1151                                 list_for_each_entry(re, &el->el_exprs,
1152                                                     re_link) {
1153                                         if (re->re_stride > 1)
1154                                                 return false;
1155                                         else if (last_hi != 0 &&
1156                                                  re->re_hi - last_hi != 1)
1157                                                 return false;
1158                                         last_hi = re->re_hi;
1159                                 }
1160                         }
1161                 }
1162         }
1163
1164         return true;
1165 }
1166
1167 /**
1168  * Determines whether an expression list in an ip nidrange contains exactly
1169  * one contiguous address range.
1170  *
1171  * \param       *nidlist
1172  *
1173  * \retval      true if contiguous
1174  * \retval      false if not contiguous
1175  */
1176 static bool cfs_ip_is_contiguous(struct list_head *nidlist)
1177 {
1178         struct nidrange         *nr;
1179         struct addrrange        *ar;
1180         struct cfs_expr_list    *el;
1181         struct cfs_range_expr   *re;
1182         int                     expr_count;
1183         int                     last_hi = 255;
1184         int                     last_diff = 0;
1185         __u32                   last_end_nid = 0;
1186         __u32                   current_start_nid = 0;
1187         __u32                   current_end_nid = 0;
1188
1189         list_for_each_entry(nr, nidlist, nr_link) {
1190                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1191                         last_hi = 255;
1192                         last_diff = 0;
1193                         cfs_ip_ar_min_max(ar, &current_start_nid,
1194                                           &current_end_nid);
1195                         if (last_end_nid != 0 &&
1196                             (current_start_nid - last_end_nid != 1))
1197                                         return false;
1198                         last_end_nid = current_end_nid;
1199                         list_for_each_entry(el,
1200                                             &ar->ar_numaddr_ranges,
1201                                             el_link) {
1202                                 expr_count = 0;
1203                                 list_for_each_entry(re, &el->el_exprs,
1204                                                     re_link) {
1205                                         expr_count++;
1206                                         if (re->re_stride > 1 ||
1207                                             (last_diff > 0 && last_hi != 255) ||
1208                                             (last_diff > 0 && last_hi == 255 &&
1209                                              re->re_lo > 0))
1210                                                 return false;
1211                                         last_hi = re->re_hi;
1212                                         last_diff = re->re_hi - re->re_lo;
1213                                 }
1214                         }
1215                 }
1216         }
1217
1218         return true;
1219 }
1220
1221 /**
1222  * Takes a linked list of nidrange expressions, determines the minimum
1223  * and maximum nid and creates appropriate nid structures
1224  *
1225  * \param       *nidlist
1226  * \param       *min_nid
1227  * \param       *max_nid
1228  */
1229 void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
1230                                char *max_nid, size_t nidstr_length)
1231 {
1232         struct nidrange         *nr;
1233         struct netstrfns        *nf = NULL;
1234         int                     netnum = -1;
1235         __u32                   min_addr;
1236         __u32                   max_addr;
1237         char                    *lndname = NULL;
1238         char                    min_addr_str[IPSTRING_LENGTH];
1239         char                    max_addr_str[IPSTRING_LENGTH];
1240
1241         list_for_each_entry(nr, nidlist, nr_link) {
1242                 nf = nr->nr_netstrfns;
1243                 lndname = nf->nf_name;
1244                 if (netnum == -1)
1245                         netnum = nr->nr_netnum;
1246
1247                 nf->nf_min_max(nidlist, &min_addr, &max_addr);
1248         }
1249         nf->nf_addr2str(min_addr, min_addr_str, sizeof(min_addr_str));
1250         nf->nf_addr2str(max_addr, max_addr_str, sizeof(max_addr_str));
1251
1252         snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
1253                  netnum);
1254         snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
1255                  netnum);
1256 }
1257
1258 /**
1259  * Determines the min and max NID values for num LNDs
1260  *
1261  * \param       *nidlist
1262  * \param       *min_nid
1263  * \param       *max_nid
1264  */
1265 static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
1266                             __u32 *max_nid)
1267 {
1268         struct nidrange         *nr;
1269         struct addrrange        *ar;
1270         unsigned int            tmp_min_addr = 0;
1271         unsigned int            tmp_max_addr = 0;
1272         unsigned int            min_addr = 0;
1273         unsigned int            max_addr = 0;
1274
1275         list_for_each_entry(nr, nidlist, nr_link) {
1276                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1277                         cfs_num_ar_min_max(ar, &tmp_min_addr,
1278                                            &tmp_max_addr);
1279                         if (tmp_min_addr < min_addr || min_addr == 0)
1280                                 min_addr = tmp_min_addr;
1281                         if (tmp_max_addr > max_addr)
1282                                 max_addr = tmp_min_addr;
1283                 }
1284         }
1285         *max_nid = max_addr;
1286         *min_nid = min_addr;
1287 }
1288
1289 /**
1290  * Takes an nidlist and determines the minimum and maximum
1291  * ip addresses.
1292  *
1293  * \param       *nidlist
1294  * \param       *min_nid
1295  * \param       *max_nid
1296  */
1297 static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
1298                            __u32 *max_nid)
1299 {
1300         struct nidrange         *nr;
1301         struct addrrange        *ar;
1302         __u32                   tmp_min_ip_addr = 0;
1303         __u32                   tmp_max_ip_addr = 0;
1304         __u32                   min_ip_addr = 0;
1305         __u32                   max_ip_addr = 0;
1306
1307         list_for_each_entry(nr, nidlist, nr_link) {
1308                 list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
1309                         cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
1310                                           &tmp_max_ip_addr);
1311                         if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
1312                                 min_ip_addr = tmp_min_ip_addr;
1313                         if (tmp_max_ip_addr > max_ip_addr)
1314                                 max_ip_addr = tmp_max_ip_addr;
1315                 }
1316         }
1317
1318         if (min_nid != NULL)
1319                 *min_nid = min_ip_addr;
1320         if (max_nid != NULL)
1321                 *max_nid = max_ip_addr;
1322 }