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