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
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
47
48
49
50
51
52
53
54
55
56
57
58static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE];
59static int libcfs_nidstring_idx;
60
61static spinlock_t libcfs_nidstring_lock;
62
63void libcfs_init_nidstrings(void)
64{
65 spin_lock_init(&libcfs_nidstring_lock);
66}
67
68static char *
69libcfs_next_nidstring(void)
70{
71 char *str;
72 unsigned long flags;
73
74 spin_lock_irqsave(&libcfs_nidstring_lock, flags);
75
76 str = libcfs_nidstrings[libcfs_nidstring_idx++];
77 if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings))
78 libcfs_nidstring_idx = 0;
79
80 spin_unlock_irqrestore(&libcfs_nidstring_lock, flags);
81 return str;
82}
83
84static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr)
85{
86 *addr = 0;
87 return 1;
88}
89
90static void libcfs_ip_addr2str(__u32 addr, char *str)
91{
92 snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u",
93 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
94 (addr >> 8) & 0xff, addr & 0xff);
95}
96
97static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
98{
99 unsigned int a;
100 unsigned int b;
101 unsigned int c;
102 unsigned int d;
103 int n = nob;
104
105
106 if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
107 n == nob &&
108 (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
109 (c & ~0xff) == 0 && (d & ~0xff) == 0) {
110 *addr = ((a<<24)|(b<<16)|(c<<8)|d);
111 return 1;
112 }
113
114 return 0;
115}
116
117static void libcfs_decnum_addr2str(__u32 addr, char *str)
118{
119 snprintf(str, LNET_NIDSTR_SIZE, "%u", addr);
120}
121
122static void libcfs_hexnum_addr2str(__u32 addr, char *str)
123{
124 snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr);
125}
126
127static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr)
128{
129 int n;
130
131 n = nob;
132 if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob)
133 return 1;
134
135 n = nob;
136 if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob)
137 return 1;
138
139 n = nob;
140 if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob)
141 return 1;
142
143 return 0;
144}
145
146
147
148
149
150
151
152
153
154static int
155libcfs_num_parse(char *str, int len, struct list_head *list)
156{
157 struct cfs_expr_list *el;
158 int rc;
159
160 rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
161 if (rc == 0)
162 list_add_tail(&el->el_link, list);
163
164 return rc;
165}
166
167
168
169
170
171
172
173static int
174libcfs_num_match(__u32 addr, struct list_head *numaddr)
175{
176 struct cfs_expr_list *el;
177
178 LASSERT(!list_empty(numaddr));
179 el = list_entry(numaddr->next, struct cfs_expr_list, el_link);
180
181 return cfs_expr_list_match(addr, el);
182}
183
184struct netstrfns {
185 int nf_type;
186 char *nf_name;
187 char *nf_modname;
188 void (*nf_addr2str)(__u32 addr, char *str);
189 int (*nf_str2addr)(const char *str, int nob, __u32 *addr);
190 int (*nf_parse_addrlist)(char *str, int len,
191 struct list_head *list);
192 int (*nf_match_addr)(__u32 addr, struct list_head *list);
193};
194
195static struct netstrfns libcfs_netstrfns[] = {
196 { LOLND,
197 "lo",
198 "klolnd",
199 libcfs_decnum_addr2str,
200 libcfs_lo_str2addr,
201 libcfs_num_parse,
202 libcfs_num_match},
203 { SOCKLND,
204 "tcp",
205 "ksocklnd",
206 libcfs_ip_addr2str,
207 libcfs_ip_str2addr,
208 cfs_ip_addr_parse,
209 cfs_ip_addr_match},
210 { O2IBLND,
211 "o2ib",
212 "ko2iblnd",
213 libcfs_ip_addr2str,
214 libcfs_ip_str2addr,
215 cfs_ip_addr_parse,
216 cfs_ip_addr_match},
217 { CIBLND,
218 "cib",
219 "kciblnd",
220 libcfs_ip_addr2str,
221 libcfs_ip_str2addr,
222 cfs_ip_addr_parse,
223 cfs_ip_addr_match},
224 { OPENIBLND,
225 "openib",
226 "kopeniblnd",
227 libcfs_ip_addr2str,
228 libcfs_ip_str2addr,
229 cfs_ip_addr_parse,
230 cfs_ip_addr_match},
231 { IIBLND,
232 "iib",
233 "kiiblnd",
234 libcfs_ip_addr2str,
235 libcfs_ip_str2addr,
236 cfs_ip_addr_parse,
237 cfs_ip_addr_match},
238 { VIBLND,
239 "vib",
240 "kviblnd",
241 libcfs_ip_addr2str,
242 libcfs_ip_str2addr,
243 cfs_ip_addr_parse,
244 cfs_ip_addr_match},
245 { RALND,
246 "ra",
247 "kralnd",
248 libcfs_ip_addr2str,
249 libcfs_ip_str2addr,
250 cfs_ip_addr_parse,
251 cfs_ip_addr_match},
252 { QSWLND,
253 "elan",
254 "kqswlnd",
255 libcfs_decnum_addr2str,
256 libcfs_num_str2addr,
257 libcfs_num_parse,
258 libcfs_num_match},
259 { GMLND,
260 "gm",
261 "kgmlnd",
262 libcfs_hexnum_addr2str,
263 libcfs_num_str2addr,
264 libcfs_num_parse,
265 libcfs_num_match},
266 { MXLND,
267 "mx",
268 "kmxlnd",
269 libcfs_ip_addr2str,
270 libcfs_ip_str2addr,
271 cfs_ip_addr_parse,
272 cfs_ip_addr_match},
273 { PTLLND,
274 "ptl",
275 "kptllnd",
276 libcfs_decnum_addr2str,
277 libcfs_num_str2addr,
278 libcfs_num_parse,
279 libcfs_num_match},
280 { GNILND,
281 "gni",
282 "kgnilnd",
283 libcfs_decnum_addr2str,
284 libcfs_num_str2addr,
285 libcfs_num_parse,
286 libcfs_num_match},
287
288 { -1},
289};
290
291static const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns);
292
293
294
295
296
297
298
299
300static struct netstrfns *
301libcfs_lnd2netstrfns(int lnd)
302{
303 int i;
304
305 if (lnd >= 0)
306 for (i = 0; i < libcfs_nnetstrfns; i++)
307 if (lnd == libcfs_netstrfns[i].nf_type)
308 return &libcfs_netstrfns[i];
309
310 return NULL;
311}
312
313static struct netstrfns *
314libcfs_namenum2netstrfns(const char *name)
315{
316 struct netstrfns *nf;
317 int i;
318
319 for (i = 0; i < libcfs_nnetstrfns; i++) {
320 nf = &libcfs_netstrfns[i];
321 if (nf->nf_type >= 0 &&
322 !strncmp(name, nf->nf_name, strlen(nf->nf_name)))
323 return nf;
324 }
325 return NULL;
326}
327
328static struct netstrfns *
329libcfs_name2netstrfns(const char *name)
330{
331 int i;
332
333 for (i = 0; i < libcfs_nnetstrfns; i++)
334 if (libcfs_netstrfns[i].nf_type >= 0 &&
335 !strcmp(libcfs_netstrfns[i].nf_name, name))
336 return &libcfs_netstrfns[i];
337
338 return NULL;
339}
340
341int
342libcfs_isknown_lnd(int type)
343{
344 return libcfs_lnd2netstrfns(type) != NULL;
345}
346EXPORT_SYMBOL(libcfs_isknown_lnd);
347
348char *
349libcfs_lnd2modname(int lnd)
350{
351 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
352
353 return (nf == NULL) ? NULL : nf->nf_modname;
354}
355EXPORT_SYMBOL(libcfs_lnd2modname);
356
357char *
358libcfs_lnd2str(int lnd)
359{
360 char *str;
361 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
362
363 if (nf != NULL)
364 return nf->nf_name;
365
366 str = libcfs_next_nidstring();
367 snprintf(str, LNET_NIDSTR_SIZE, "?%d?", lnd);
368 return str;
369}
370EXPORT_SYMBOL(libcfs_lnd2str);
371
372int
373libcfs_str2lnd(const char *str)
374{
375 struct netstrfns *nf = libcfs_name2netstrfns(str);
376
377 if (nf != NULL)
378 return nf->nf_type;
379
380 return -1;
381}
382EXPORT_SYMBOL(libcfs_str2lnd);
383
384char *
385libcfs_net2str(__u32 net)
386{
387 int lnd = LNET_NETTYP(net);
388 int num = LNET_NETNUM(net);
389 struct netstrfns *nf = libcfs_lnd2netstrfns(lnd);
390 char *str = libcfs_next_nidstring();
391
392 if (nf == NULL)
393 snprintf(str, LNET_NIDSTR_SIZE, "<%d:%d>", lnd, num);
394 else if (num == 0)
395 snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name);
396 else
397 snprintf(str, LNET_NIDSTR_SIZE, "%s%d", nf->nf_name, num);
398
399 return str;
400}
401EXPORT_SYMBOL(libcfs_net2str);
402
403char *
404libcfs_nid2str(lnet_nid_t nid)
405{
406 __u32 addr = LNET_NIDADDR(nid);
407 __u32 net = LNET_NIDNET(nid);
408 int lnd = LNET_NETTYP(net);
409 int nnum = LNET_NETNUM(net);
410 struct netstrfns *nf;
411 char *str;
412 int nob;
413
414 if (nid == LNET_NID_ANY)
415 return "<?>";
416
417 nf = libcfs_lnd2netstrfns(lnd);
418 str = libcfs_next_nidstring();
419
420 if (nf == NULL)
421 snprintf(str, LNET_NIDSTR_SIZE, "%x@<%d:%d>", addr, lnd, nnum);
422 else {
423 nf->nf_addr2str(addr, str);
424 nob = strlen(str);
425 if (nnum == 0)
426 snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s",
427 nf->nf_name);
428 else
429 snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%d",
430 nf->nf_name, nnum);
431 }
432
433 return str;
434}
435EXPORT_SYMBOL(libcfs_nid2str);
436
437static struct netstrfns *
438libcfs_str2net_internal(const char *str, __u32 *net)
439{
440 struct netstrfns *uninitialized_var(nf);
441 int nob;
442 unsigned int netnum;
443 int i;
444
445 for (i = 0; i < libcfs_nnetstrfns; i++) {
446 nf = &libcfs_netstrfns[i];
447 if (nf->nf_type >= 0 &&
448 !strncmp(str, nf->nf_name, strlen(nf->nf_name)))
449 break;
450 }
451
452 if (i == libcfs_nnetstrfns)
453 return NULL;
454
455 nob = strlen(nf->nf_name);
456
457 if (strlen(str) == (unsigned int)nob) {
458 netnum = 0;
459 } else {
460 if (nf->nf_type == LOLND)
461 return NULL;
462
463 str += nob;
464 i = strlen(str);
465 if (sscanf(str, "%u%n", &netnum, &i) < 1 ||
466 i != (int)strlen(str))
467 return NULL;
468 }
469
470 *net = LNET_MKNET(nf->nf_type, netnum);
471 return nf;
472}
473
474__u32
475libcfs_str2net(const char *str)
476{
477 __u32 net;
478
479 if (libcfs_str2net_internal(str, &net) != NULL)
480 return net;
481
482 return LNET_NIDNET(LNET_NID_ANY);
483}
484EXPORT_SYMBOL(libcfs_str2net);
485
486lnet_nid_t
487libcfs_str2nid(const char *str)
488{
489 const char *sep = strchr(str, '@');
490 struct netstrfns *nf;
491 __u32 net;
492 __u32 addr;
493
494 if (sep != NULL) {
495 nf = libcfs_str2net_internal(sep + 1, &net);
496 if (nf == NULL)
497 return LNET_NID_ANY;
498 } else {
499 sep = str + strlen(str);
500 net = LNET_MKNET(SOCKLND, 0);
501 nf = libcfs_lnd2netstrfns(SOCKLND);
502 LASSERT(nf != NULL);
503 }
504
505 if (!nf->nf_str2addr(str, (int)(sep - str), &addr))
506 return LNET_NID_ANY;
507
508 return LNET_MKNID(net, addr);
509}
510EXPORT_SYMBOL(libcfs_str2nid);
511
512char *
513libcfs_id2str(lnet_process_id_t id)
514{
515 char *str = libcfs_next_nidstring();
516
517 if (id.pid == LNET_PID_ANY) {
518 snprintf(str, LNET_NIDSTR_SIZE,
519 "LNET_PID_ANY-%s", libcfs_nid2str(id.nid));
520 return str;
521 }
522
523 snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s",
524 ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "",
525 (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid));
526 return str;
527}
528EXPORT_SYMBOL(libcfs_id2str);
529
530int
531libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
532{
533 if (!strcmp(str, "*")) {
534 *nidp = LNET_NID_ANY;
535 return 1;
536 }
537
538 *nidp = libcfs_str2nid(str);
539 return *nidp != LNET_NID_ANY;
540}
541EXPORT_SYMBOL(libcfs_str2anynid);
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571struct nidrange {
572
573
574
575
576 struct list_head nr_link;
577
578
579
580 struct list_head nr_addrranges;
581
582
583
584 int nr_all;
585
586
587
588 struct netstrfns *nr_netstrfns;
589
590
591
592 int nr_netnum;
593};
594
595
596
597
598struct addrrange {
599
600
601
602 struct list_head ar_link;
603
604
605
606 struct list_head ar_numaddr_ranges;
607};
608
609
610
611
612
613
614
615
616
617
618static int
619parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
620{
621 struct addrrange *addrrange;
622
623 if (src->ls_len == 1 && src->ls_str[0] == '*') {
624 nidrange->nr_all = 1;
625 return 1;
626 }
627
628 LIBCFS_ALLOC(addrrange, sizeof(struct addrrange));
629 if (addrrange == NULL)
630 return 0;
631 list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges);
632 INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges);
633
634 return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str,
635 src->ls_len,
636 &addrrange->ar_numaddr_ranges);
637}
638
639
640
641
642
643
644
645
646
647
648
649static struct nidrange *
650add_nidrange(const struct cfs_lstr *src,
651 struct list_head *nidlist)
652{
653 struct netstrfns *nf;
654 struct nidrange *nr;
655 int endlen;
656 unsigned netnum;
657
658 if (src->ls_len >= LNET_NIDSTR_SIZE)
659 return NULL;
660
661 nf = libcfs_namenum2netstrfns(src->ls_str);
662 if (nf == NULL)
663 return NULL;
664 endlen = src->ls_len - strlen(nf->nf_name);
665 if (endlen == 0)
666
667 netnum = 0;
668 else {
669
670
671
672 if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
673 endlen, &netnum, 0, MAX_NUMERIC_VALUE))
674 return NULL;
675 }
676
677 list_for_each_entry(nr, nidlist, nr_link) {
678 if (nr->nr_netstrfns != nf)
679 continue;
680 if (nr->nr_netnum != netnum)
681 continue;
682 return nr;
683 }
684
685 LIBCFS_ALLOC(nr, sizeof(struct nidrange));
686 if (nr == NULL)
687 return NULL;
688 list_add_tail(&nr->nr_link, nidlist);
689 INIT_LIST_HEAD(&nr->nr_addrranges);
690 nr->nr_netstrfns = nf;
691 nr->nr_all = 0;
692 nr->nr_netnum = netnum;
693
694 return nr;
695}
696
697
698
699
700
701
702
703static int
704parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist)
705{
706 struct cfs_lstr addrrange;
707 struct cfs_lstr net;
708 struct cfs_lstr tmp;
709 struct nidrange *nr;
710
711 tmp = *src;
712 if (cfs_gettok(src, '@', &addrrange) == 0)
713 goto failed;
714
715 if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
716 goto failed;
717
718 nr = add_nidrange(&net, nidlist);
719 if (nr == NULL)
720 goto failed;
721
722 if (parse_addrange(&addrrange, nr) != 0)
723 goto failed;
724
725 return 1;
726 failed:
727 CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str);
728 return 0;
729}
730
731
732
733
734
735
736
737
738
739static void
740free_addrranges(struct list_head *list)
741{
742 while (!list_empty(list)) {
743 struct addrrange *ar;
744
745 ar = list_entry(list->next, struct addrrange, ar_link);
746
747 cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
748 list_del(&ar->ar_link);
749 LIBCFS_FREE(ar, sizeof(struct addrrange));
750 }
751}
752
753
754
755
756
757
758
759
760
761void
762cfs_free_nidlist(struct list_head *list)
763{
764 struct list_head *pos, *next;
765 struct nidrange *nr;
766
767 list_for_each_safe(pos, next, list) {
768 nr = list_entry(pos, struct nidrange, nr_link);
769 free_addrranges(&nr->nr_addrranges);
770 list_del(pos);
771 LIBCFS_FREE(nr, sizeof(struct nidrange));
772 }
773}
774EXPORT_SYMBOL(cfs_free_nidlist);
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789int
790cfs_parse_nidlist(char *str, int len, struct list_head *nidlist)
791{
792 struct cfs_lstr src;
793 struct cfs_lstr res;
794 int rc;
795
796 src.ls_str = str;
797 src.ls_len = len;
798 INIT_LIST_HEAD(nidlist);
799 while (src.ls_str) {
800 rc = cfs_gettok(&src, ' ', &res);
801 if (rc == 0) {
802 cfs_free_nidlist(nidlist);
803 return 0;
804 }
805 rc = parse_nidrange(&res, nidlist);
806 if (rc == 0) {
807 cfs_free_nidlist(nidlist);
808 return 0;
809 }
810 }
811 return 1;
812}
813EXPORT_SYMBOL(cfs_parse_nidlist);
814
815
816
817
818
819
820
821
822
823int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist)
824{
825 struct nidrange *nr;
826 struct addrrange *ar;
827
828 list_for_each_entry(nr, nidlist, nr_link) {
829 if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid)))
830 continue;
831 if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid)))
832 continue;
833 if (nr->nr_all)
834 return 1;
835 list_for_each_entry(ar, &nr->nr_addrranges, ar_link)
836 if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid),
837 &ar->ar_numaddr_ranges))
838 return 1;
839 }
840 return 0;
841}
842EXPORT_SYMBOL(cfs_match_nid);
843