4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
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
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2012, 2015, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LNET
38 #include "../../include/linux/lnet/lib-lnet.h"
40 struct lnet_text_buf
{ /* tmp struct for parsing routes */
41 struct list_head ltb_list
; /* stash on lists */
42 int ltb_size
; /* allocated size */
43 char ltb_text
[0]; /* text buffer */
46 static int lnet_tbnob
; /* track text buf allocation */
47 #define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */
48 #define LNET_SINGLE_TEXTBUF_NOB (4 << 10)
51 lnet_syntax(char *name
, char *str
, int offset
, int width
)
53 static char dots
[LNET_SINGLE_TEXTBUF_NOB
];
54 static char dashes
[LNET_SINGLE_TEXTBUF_NOB
];
56 memset(dots
, '.', sizeof(dots
));
57 dots
[sizeof(dots
) - 1] = 0;
58 memset(dashes
, '-', sizeof(dashes
));
59 dashes
[sizeof(dashes
) - 1] = 0;
61 LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name
, str
);
62 LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n",
63 (int)strlen(name
), dots
, offset
, dots
,
64 (width
< 1) ? 0 : width
- 1, dashes
);
81 lnet_net_unique(__u32 net
, struct list_head
*nilist
)
83 struct list_head
*tmp
;
86 list_for_each(tmp
, nilist
) {
87 ni
= list_entry(tmp
, lnet_ni_t
, ni_list
);
89 if (LNET_NIDNET(ni
->ni_nid
) == net
)
97 lnet_ni_free(struct lnet_ni
*ni
)
102 cfs_percpt_free(ni
->ni_refs
);
104 if (ni
->ni_tx_queues
)
105 cfs_percpt_free(ni
->ni_tx_queues
);
108 cfs_expr_list_values_free(ni
->ni_cpts
, ni
->ni_ncpts
);
110 for (i
= 0; i
< LNET_MAX_INTERFACES
&& ni
->ni_interfaces
[i
]; i
++) {
111 LIBCFS_FREE(ni
->ni_interfaces
[i
],
112 strlen(ni
->ni_interfaces
[i
]) + 1);
114 LIBCFS_FREE(ni
, sizeof(*ni
));
118 lnet_ni_alloc(__u32 net
, struct cfs_expr_list
*el
, struct list_head
*nilist
)
120 struct lnet_tx_queue
*tq
;
125 if (!lnet_net_unique(net
, nilist
)) {
126 LCONSOLE_ERROR_MSG(0x111, "Duplicate network specified: %s\n",
127 libcfs_net2str(net
));
131 LIBCFS_ALLOC(ni
, sizeof(*ni
));
133 CERROR("Out of memory creating network %s\n",
134 libcfs_net2str(net
));
138 spin_lock_init(&ni
->ni_lock
);
139 INIT_LIST_HEAD(&ni
->ni_cptlist
);
140 ni
->ni_refs
= cfs_percpt_alloc(lnet_cpt_table(),
141 sizeof(*ni
->ni_refs
[0]));
145 ni
->ni_tx_queues
= cfs_percpt_alloc(lnet_cpt_table(),
146 sizeof(*ni
->ni_tx_queues
[0]));
147 if (!ni
->ni_tx_queues
)
150 cfs_percpt_for_each(tq
, i
, ni
->ni_tx_queues
)
151 INIT_LIST_HEAD(&tq
->tq_delayed
);
155 ni
->ni_ncpts
= LNET_CPT_NUMBER
;
157 rc
= cfs_expr_list_values(el
, LNET_CPT_NUMBER
, &ni
->ni_cpts
);
159 CERROR("Failed to set CPTs for NI %s: %d\n",
160 libcfs_net2str(net
), rc
);
164 LASSERT(rc
<= LNET_CPT_NUMBER
);
165 if (rc
== LNET_CPT_NUMBER
) {
166 LIBCFS_FREE(ni
->ni_cpts
, rc
* sizeof(ni
->ni_cpts
[0]));
173 /* LND will fill in the address part of the NID */
174 ni
->ni_nid
= LNET_MKNID(net
, 0);
175 ni
->ni_last_alive
= ktime_get_real_seconds();
176 list_add_tail(&ni
->ni_list
, nilist
);
184 lnet_parse_networks(struct list_head
*nilist
, char *networks
)
186 struct cfs_expr_list
*el
= NULL
;
194 struct list_head
*temp_node
;
197 CERROR("networks string is undefined\n");
201 if (strlen(networks
) > LNET_SINGLE_TEXTBUF_NOB
) {
202 /* _WAY_ conservative */
203 LCONSOLE_ERROR_MSG(0x112,
204 "Can't parse networks: string too long\n");
208 tokensize
= strlen(networks
) + 1;
210 LIBCFS_ALLOC(tokens
, tokensize
);
212 CERROR("Can't allocate net tokens\n");
216 memcpy(tokens
, networks
, tokensize
);
220 while (str
&& *str
) {
221 char *comma
= strchr(str
, ',');
222 char *bracket
= strchr(str
, '(');
223 char *square
= strchr(str
, '[');
229 * NB we don't check interface conflicts here; it's the LNDs
230 * responsibility (if it cares at all)
232 if (square
&& (!comma
|| square
< comma
)) {
234 * i.e: o2ib0(ib0)[1,2], number between square
235 * brackets are CPTs this NI needs to be bond
237 if (bracket
&& bracket
> square
) {
242 tmp
= strchr(square
, ']');
248 rc
= cfs_expr_list_parse(square
, tmp
- square
+ 1,
249 0, LNET_CPT_NUMBER
- 1, &el
);
255 while (square
<= tmp
)
259 if (!bracket
|| (comma
&& comma
< bracket
)) {
260 /* no interface list specified */
264 net
= libcfs_str2net(cfs_trimwhite(str
));
266 if (net
== LNET_NIDNET(LNET_NID_ANY
)) {
267 LCONSOLE_ERROR_MSG(0x113,
268 "Unrecognised network type\n");
273 if (LNET_NETTYP(net
) != LOLND
&& /* LO is implicit */
274 !lnet_ni_alloc(net
, el
, nilist
))
278 cfs_expr_list_free(el
);
287 net
= libcfs_str2net(cfs_trimwhite(str
));
288 if (net
== LNET_NIDNET(LNET_NID_ANY
)) {
293 ni
= lnet_ni_alloc(net
, el
, nilist
);
298 cfs_expr_list_free(el
);
305 bracket
= strchr(iface
, ')');
313 comma
= strchr(iface
, ',');
317 iface
= cfs_trimwhite(iface
);
323 if (niface
== LNET_MAX_INTERFACES
) {
324 LCONSOLE_ERROR_MSG(0x115,
325 "Too many interfaces for net %s\n",
326 libcfs_net2str(net
));
331 * Allocate a separate piece of memory and copy
332 * into it the string, so we don't have
333 * a depencency on the tokens string. This way we
334 * can free the tokens at the end of the function.
335 * The newly allocated ni_interfaces[] can be
336 * freed when freeing the NI
338 LIBCFS_ALLOC(ni
->ni_interfaces
[niface
],
340 if (!ni
->ni_interfaces
[niface
]) {
341 CERROR("Can't allocate net interface name\n");
344 strncpy(ni
->ni_interfaces
[niface
], iface
,
351 comma
= strchr(bracket
+ 1, ',');
354 str
= cfs_trimwhite(str
);
363 str
= cfs_trimwhite(str
);
370 list_for_each(temp_node
, nilist
)
373 LIBCFS_FREE(tokens
, tokensize
);
377 lnet_syntax("networks", networks
, (int)(tmp
- tokens
), strlen(tmp
));
379 while (!list_empty(nilist
)) {
380 ni
= list_entry(nilist
->next
, lnet_ni_t
, ni_list
);
382 list_del(&ni
->ni_list
);
387 cfs_expr_list_free(el
);
389 LIBCFS_FREE(tokens
, tokensize
);
394 static struct lnet_text_buf
*
395 lnet_new_text_buf(int str_len
)
397 struct lnet_text_buf
*ltb
;
400 /* NB allocate space for the terminating 0 */
401 nob
= offsetof(struct lnet_text_buf
, ltb_text
[str_len
+ 1]);
402 if (nob
> LNET_SINGLE_TEXTBUF_NOB
) {
403 /* _way_ conservative for "route net gateway..." */
404 CERROR("text buffer too big\n");
408 if (lnet_tbnob
+ nob
> LNET_MAX_TEXTBUF_NOB
) {
409 CERROR("Too many text buffers\n");
413 LIBCFS_ALLOC(ltb
, nob
);
418 ltb
->ltb_text
[0] = 0;
424 lnet_free_text_buf(struct lnet_text_buf
*ltb
)
426 lnet_tbnob
-= ltb
->ltb_size
;
427 LIBCFS_FREE(ltb
, ltb
->ltb_size
);
431 lnet_free_text_bufs(struct list_head
*tbs
)
433 struct lnet_text_buf
*ltb
;
435 while (!list_empty(tbs
)) {
436 ltb
= list_entry(tbs
->next
, struct lnet_text_buf
, ltb_list
);
438 list_del(<b
->ltb_list
);
439 lnet_free_text_buf(ltb
);
444 lnet_str2tbs_sep(struct list_head
*tbs
, char *str
)
446 struct list_head pending
;
450 struct lnet_text_buf
*ltb
;
452 INIT_LIST_HEAD(&pending
);
454 /* Split 'str' into separate commands */
456 /* skip leading whitespace */
457 while (isspace(*str
))
460 /* scan for separator or comment */
461 for (sep
= str
; *sep
; sep
++)
462 if (lnet_issep(*sep
) || *sep
== '#')
465 nob
= (int)(sep
- str
);
467 ltb
= lnet_new_text_buf(nob
);
469 lnet_free_text_bufs(&pending
);
473 for (i
= 0; i
< nob
; i
++)
475 ltb
->ltb_text
[i
] = ' ';
477 ltb
->ltb_text
[i
] = str
[i
];
479 ltb
->ltb_text
[nob
] = 0;
481 list_add_tail(<b
->ltb_list
, &pending
);
485 /* scan for separator */
488 } while (*sep
&& !lnet_issep(*sep
));
497 list_splice(&pending
, tbs
->prev
);
502 lnet_expand1tb(struct list_head
*list
,
503 char *str
, char *sep1
, char *sep2
,
504 char *item
, int itemlen
)
506 int len1
= (int)(sep1
- str
);
507 int len2
= strlen(sep2
+ 1);
508 struct lnet_text_buf
*ltb
;
510 LASSERT(*sep1
== '[');
511 LASSERT(*sep2
== ']');
513 ltb
= lnet_new_text_buf(len1
+ itemlen
+ len2
);
517 memcpy(ltb
->ltb_text
, str
, len1
);
518 memcpy(<b
->ltb_text
[len1
], item
, itemlen
);
519 memcpy(<b
->ltb_text
[len1
+ itemlen
], sep2
+ 1, len2
);
520 ltb
->ltb_text
[len1
+ itemlen
+ len2
] = 0;
522 list_add_tail(<b
->ltb_list
, list
);
527 lnet_str2tbs_expand(struct list_head
*tbs
, char *str
)
530 struct list_head pending
;
542 INIT_LIST_HEAD(&pending
);
544 sep
= strchr(str
, '[');
545 if (!sep
) /* nothing to expand */
548 sep2
= strchr(sep
, ']');
552 for (parsed
= sep
; parsed
< sep2
; parsed
= enditem
) {
554 while (enditem
< sep2
&& *enditem
!= ',')
557 if (enditem
== parsed
) /* no empty items */
560 if (sscanf(parsed
, "%d-%d/%d%n", &lo
, &hi
,
561 &stride
, &scanned
) < 3) {
562 if (sscanf(parsed
, "%d-%d%n", &lo
, &hi
, &scanned
) < 2) {
563 /* simple string enumeration */
564 if (lnet_expand1tb(&pending
, str
, sep
, sep2
,
566 (int)(enditem
- parsed
))) {
575 /* range expansion */
577 if (enditem
!= parsed
+ scanned
) /* no trailing junk */
580 if (hi
< 0 || lo
< 0 || stride
< 0 || hi
< lo
||
584 for (i
= lo
; i
<= hi
; i
+= stride
) {
585 snprintf(num
, sizeof(num
), "%d", i
);
587 if (nob
+ 1 == sizeof(num
))
590 if (lnet_expand1tb(&pending
, str
, sep
, sep2
,
596 list_splice(&pending
, tbs
->prev
);
600 lnet_free_text_bufs(&pending
);
605 lnet_parse_hops(char *str
, unsigned int *hops
)
607 int len
= strlen(str
);
610 return (sscanf(str
, "%u%n", hops
, &nob
) >= 1 &&
612 *hops
> 0 && *hops
< 256);
615 #define LNET_PRIORITY_SEPARATOR (':')
618 lnet_parse_priority(char *str
, unsigned int *priority
, char **token
)
624 sep
= strchr(str
, LNET_PRIORITY_SEPARATOR
);
629 len
= strlen(sep
+ 1);
631 if ((sscanf((sep
+ 1), "%u%n", priority
, &nob
) < 1) || (len
!= nob
)) {
633 * Update the caller's token pointer so it treats the found
634 * priority as the token to report in the error message.
636 *token
+= sep
- str
+ 1;
640 CDEBUG(D_NET
, "gateway %s, priority %d, nob %d\n", str
, *priority
, nob
);
643 * Change priority separator to \0 to be able to parse NID
650 lnet_parse_route(char *str
, int *im_a_router
)
652 /* static scratch buffer OK (single threaded) */
653 static char cmd
[LNET_SINGLE_TEXTBUF_NOB
];
655 struct list_head nets
;
656 struct list_head gateways
;
657 struct list_head
*tmp1
;
658 struct list_head
*tmp2
;
661 struct lnet_text_buf
*ltb
;
669 unsigned int priority
= 0;
671 INIT_LIST_HEAD(&gateways
);
672 INIT_LIST_HEAD(&nets
);
674 /* save a copy of the string for error messages */
675 strncpy(cmd
, str
, sizeof(cmd
));
676 cmd
[sizeof(cmd
) - 1] = '\0';
680 /* scan for token start */
681 while (isspace(*sep
))
684 if (ntokens
< (got_hops
? 3 : 2))
692 /* scan for token end */
693 while (*sep
&& !isspace(*sep
))
699 tmp2
= &nets
; /* expanding nets */
700 } else if (ntokens
== 2 &&
701 lnet_parse_hops(token
, &hops
)) {
702 got_hops
= 1; /* got a hop count */
705 tmp2
= &gateways
; /* expanding gateways */
708 ltb
= lnet_new_text_buf(strlen(token
));
712 strcpy(ltb
->ltb_text
, token
);
713 tmp1
= <b
->ltb_list
;
714 list_add_tail(tmp1
, tmp2
);
716 while (tmp1
!= tmp2
) {
717 ltb
= list_entry(tmp1
, struct lnet_text_buf
, ltb_list
);
719 rc
= lnet_str2tbs_expand(tmp1
->next
, ltb
->ltb_text
);
725 if (rc
> 0) { /* expanded! */
726 list_del(<b
->ltb_list
);
727 lnet_free_text_buf(ltb
);
732 net
= libcfs_str2net(ltb
->ltb_text
);
733 if (net
== LNET_NIDNET(LNET_NID_ANY
) ||
734 LNET_NETTYP(net
) == LOLND
)
737 rc
= lnet_parse_priority(ltb
->ltb_text
,
742 nid
= libcfs_str2nid(ltb
->ltb_text
);
743 if (nid
== LNET_NID_ANY
||
744 LNET_NETTYP(LNET_NIDNET(nid
)) == LOLND
)
751 * if there are no hops set then we want to flag this value as
752 * unset since hops is an optional parameter
755 hops
= LNET_UNDEFINED_HOPS
;
757 LASSERT(!list_empty(&nets
));
758 LASSERT(!list_empty(&gateways
));
760 list_for_each(tmp1
, &nets
) {
761 ltb
= list_entry(tmp1
, struct lnet_text_buf
, ltb_list
);
762 net
= libcfs_str2net(ltb
->ltb_text
);
763 LASSERT(net
!= LNET_NIDNET(LNET_NID_ANY
));
765 list_for_each(tmp2
, &gateways
) {
766 ltb
= list_entry(tmp2
, struct lnet_text_buf
, ltb_list
);
767 nid
= libcfs_str2nid(ltb
->ltb_text
);
768 LASSERT(nid
!= LNET_NID_ANY
);
770 if (lnet_islocalnid(nid
)) {
775 rc
= lnet_add_route(net
, hops
, nid
, priority
);
776 if (rc
&& rc
!= -EEXIST
&& rc
!= -EHOSTUNREACH
) {
777 CERROR("Can't create route to %s via %s\n",
779 libcfs_nid2str(nid
));
789 lnet_syntax("routes", cmd
, (int)(token
- str
), strlen(token
));
791 lnet_free_text_bufs(&nets
);
792 lnet_free_text_bufs(&gateways
);
797 lnet_parse_route_tbs(struct list_head
*tbs
, int *im_a_router
)
799 struct lnet_text_buf
*ltb
;
801 while (!list_empty(tbs
)) {
802 ltb
= list_entry(tbs
->next
, struct lnet_text_buf
, ltb_list
);
804 if (lnet_parse_route(ltb
->ltb_text
, im_a_router
) < 0) {
805 lnet_free_text_bufs(tbs
);
809 list_del(<b
->ltb_list
);
810 lnet_free_text_buf(ltb
);
817 lnet_parse_routes(char *routes
, int *im_a_router
)
819 struct list_head tbs
;
824 INIT_LIST_HEAD(&tbs
);
826 if (lnet_str2tbs_sep(&tbs
, routes
) < 0) {
827 CERROR("Error parsing routes\n");
830 rc
= lnet_parse_route_tbs(&tbs
, im_a_router
);
833 LASSERT(!lnet_tbnob
);
838 lnet_match_network_token(char *token
, int len
, __u32
*ipaddrs
, int nip
)
844 rc
= cfs_ip_addr_parse(token
, len
, &list
);
848 for (rc
= i
= 0; !rc
&& i
< nip
; i
++)
849 rc
= cfs_ip_addr_match(ipaddrs
[i
], &list
);
851 cfs_expr_list_free_list(&list
);
857 lnet_match_network_tokens(char *net_entry
, __u32
*ipaddrs
, int nip
)
859 static char tokens
[LNET_SINGLE_TEXTBUF_NOB
];
869 LASSERT(strlen(net_entry
) < sizeof(tokens
));
871 /* work on a copy of the string */
872 strcpy(tokens
, net_entry
);
875 /* scan for token start */
876 while (isspace(*sep
))
883 /* scan for token end */
884 while (*sep
&& !isspace(*sep
))
896 rc
= lnet_match_network_token(token
, len
, ipaddrs
, nip
);
898 lnet_syntax("ip2nets", net_entry
,
899 (int)(token
- tokens
), len
);
910 strcpy(net_entry
, net
); /* replace with matched net */
915 lnet_netspec2net(char *netspec
)
917 char *bracket
= strchr(netspec
, '(');
923 net
= libcfs_str2net(netspec
);
932 lnet_splitnets(char *source
, struct list_head
*nets
)
937 struct lnet_text_buf
*tb
;
938 struct lnet_text_buf
*tb2
;
944 LASSERT(!list_empty(nets
));
945 LASSERT(nets
->next
== nets
->prev
); /* single entry */
947 tb
= list_entry(nets
->next
, struct lnet_text_buf
, ltb_list
);
950 sep
= strchr(tb
->ltb_text
, ',');
951 bracket
= strchr(tb
->ltb_text
, '(');
953 if (sep
&& bracket
&& bracket
< sep
) {
954 /* netspec lists interfaces... */
956 offset2
= offset
+ (int)(bracket
- tb
->ltb_text
);
957 len
= strlen(bracket
);
959 bracket
= strchr(bracket
+ 1, ')');
962 !(bracket
[1] == ',' || !bracket
[1])) {
963 lnet_syntax("ip2nets", source
, offset2
, len
);
967 sep
= !bracket
[1] ? NULL
: bracket
+ 1;
973 net
= lnet_netspec2net(tb
->ltb_text
);
974 if (net
== LNET_NIDNET(LNET_NID_ANY
)) {
975 lnet_syntax("ip2nets", source
, offset
,
976 strlen(tb
->ltb_text
));
980 list_for_each(t
, nets
) {
981 tb2
= list_entry(t
, struct lnet_text_buf
, ltb_list
);
986 if (net
== lnet_netspec2net(tb2
->ltb_text
)) {
987 /* duplicate network */
988 lnet_syntax("ip2nets", source
, offset
,
989 strlen(tb
->ltb_text
));
997 offset
+= (int)(sep
- tb
->ltb_text
);
999 tb2
= lnet_new_text_buf(len
);
1003 strncpy(tb2
->ltb_text
, sep
, len
);
1004 tb2
->ltb_text
[len
] = '\0';
1005 list_add_tail(&tb2
->ltb_list
, nets
);
1012 lnet_match_networks(char **networksp
, char *ip2nets
, __u32
*ipaddrs
, int nip
)
1014 static char networks
[LNET_SINGLE_TEXTBUF_NOB
];
1015 static char source
[LNET_SINGLE_TEXTBUF_NOB
];
1017 struct list_head raw_entries
;
1018 struct list_head matched_nets
;
1019 struct list_head current_nets
;
1020 struct list_head
*t
;
1021 struct list_head
*t2
;
1022 struct lnet_text_buf
*tb
;
1023 struct lnet_text_buf
*tb2
;
1031 INIT_LIST_HEAD(&raw_entries
);
1032 if (lnet_str2tbs_sep(&raw_entries
, ip2nets
) < 0) {
1033 CERROR("Error parsing ip2nets\n");
1034 LASSERT(!lnet_tbnob
);
1038 INIT_LIST_HEAD(&matched_nets
);
1039 INIT_LIST_HEAD(¤t_nets
);
1045 while (!list_empty(&raw_entries
)) {
1046 tb
= list_entry(raw_entries
.next
, struct lnet_text_buf
,
1048 strncpy(source
, tb
->ltb_text
, sizeof(source
));
1049 source
[sizeof(source
) - 1] = '\0';
1051 /* replace ltb_text with the network(s) add on match */
1052 rc
= lnet_match_network_tokens(tb
->ltb_text
, ipaddrs
, nip
);
1056 list_del(&tb
->ltb_list
);
1058 if (!rc
) { /* no match */
1059 lnet_free_text_buf(tb
);
1063 /* split into separate networks */
1064 INIT_LIST_HEAD(¤t_nets
);
1065 list_add(&tb
->ltb_list
, ¤t_nets
);
1066 rc
= lnet_splitnets(source
, ¤t_nets
);
1071 list_for_each(t
, ¤t_nets
) {
1072 tb
= list_entry(t
, struct lnet_text_buf
, ltb_list
);
1073 net1
= lnet_netspec2net(tb
->ltb_text
);
1074 LASSERT(net1
!= LNET_NIDNET(LNET_NID_ANY
));
1076 list_for_each(t2
, &matched_nets
) {
1077 tb2
= list_entry(t2
, struct lnet_text_buf
,
1079 net2
= lnet_netspec2net(tb2
->ltb_text
);
1080 LASSERT(net2
!= LNET_NIDNET(LNET_NID_ANY
));
1093 lnet_free_text_bufs(¤t_nets
);
1097 list_for_each_safe(t
, t2
, ¤t_nets
) {
1098 tb
= list_entry(t
, struct lnet_text_buf
, ltb_list
);
1100 list_del(&tb
->ltb_list
);
1101 list_add_tail(&tb
->ltb_list
, &matched_nets
);
1103 len
+= snprintf(networks
+ len
, sizeof(networks
) - len
,
1104 "%s%s", !len
? "" : ",",
1107 if (len
>= sizeof(networks
)) {
1108 CERROR("Too many matched networks\n");
1118 lnet_free_text_bufs(&raw_entries
);
1119 lnet_free_text_bufs(&matched_nets
);
1120 lnet_free_text_bufs(¤t_nets
);
1121 LASSERT(!lnet_tbnob
);
1126 *networksp
= networks
;
1131 lnet_ipaddr_enumerate(__u32
**ipaddrsp
)
1139 int nif
= lnet_ipif_enumerate(&ifnames
);
1146 LIBCFS_ALLOC(ipaddrs
, nif
* sizeof(*ipaddrs
));
1148 CERROR("Can't allocate ipaddrs[%d]\n", nif
);
1149 lnet_ipif_free_enumeration(ifnames
, nif
);
1153 for (i
= nip
= 0; i
< nif
; i
++) {
1154 if (!strcmp(ifnames
[i
], "lo"))
1157 rc
= lnet_ipif_query(ifnames
[i
], &up
, &ipaddrs
[nip
], &netmask
);
1159 CWARN("Can't query interface %s: %d\n",
1165 CWARN("Ignoring interface %s: it's down\n",
1173 lnet_ipif_free_enumeration(ifnames
, nif
);
1176 *ipaddrsp
= ipaddrs
;
1179 LIBCFS_ALLOC(ipaddrs2
, nip
* sizeof(*ipaddrs2
));
1181 CERROR("Can't allocate ipaddrs[%d]\n", nip
);
1184 memcpy(ipaddrs2
, ipaddrs
,
1185 nip
* sizeof(*ipaddrs
));
1186 *ipaddrsp
= ipaddrs2
;
1190 LIBCFS_FREE(ipaddrs
, nip
* sizeof(*ipaddrs
));
1196 lnet_parse_ip2nets(char **networksp
, char *ip2nets
)
1198 __u32
*ipaddrs
= NULL
;
1199 int nip
= lnet_ipaddr_enumerate(&ipaddrs
);
1203 LCONSOLE_ERROR_MSG(0x117,
1204 "Error %d enumerating local IP interfaces for ip2nets to match\n",
1210 LCONSOLE_ERROR_MSG(0x118,
1211 "No local IP interfaces for ip2nets to match\n");
1215 rc
= lnet_match_networks(networksp
, ip2nets
, ipaddrs
, nip
);
1216 LIBCFS_FREE(ipaddrs
, nip
* sizeof(*ipaddrs
));
1219 LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc
);
1224 LCONSOLE_ERROR_MSG(0x11a,
1225 "ip2nets does not match any local IP interfaces\n");
This page took 0.126135 seconds and 5 git commands to generate.