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