blob: 480cc9c6caabdadadc61706f34ed8a4ea17e2abe [file] [log] [blame]
Peng Taod7e09d02013-05-02 16:46:55 +08001/*
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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
Andreas Dilger1dc563a2015-11-08 18:09:37 -050030 * Copyright (c) 2012, 2015, Intel Corporation.
Peng Taod7e09d02013-05-02 16:46:55 +080031 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
35 */
36
37#define DEBUG_SUBSYSTEM S_LNET
Greg Kroah-Hartman9fdaf8c2014-07-11 20:51:16 -070038#include "../../include/linux/lnet/lib-lnet.h"
Peng Taod7e09d02013-05-02 16:46:55 +080039
James Simmonsddbc66a2016-02-12 12:05:59 -050040struct lnet_text_buf { /* tmp struct for parsing routes */
Mike Shuey7e7ab092015-05-19 10:14:32 -040041 struct list_head ltb_list; /* stash on lists */
42 int ltb_size; /* allocated size */
43 char ltb_text[0]; /* text buffer */
Rafaƫl Bocquete416a892015-04-02 17:12:34 +020044};
Peng Taod7e09d02013-05-02 16:46:55 +080045
Rashika Kheriaad0a75b2013-10-26 00:24:03 +053046static int lnet_tbnob; /* track text buf allocation */
James Simmons51078e22016-02-12 12:06:04 -050047#define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */
48#define LNET_SINGLE_TEXTBUF_NOB (4 << 10)
Peng Taod7e09d02013-05-02 16:46:55 +080049
Benedict Boerger714340d2014-08-08 18:26:22 +020050static void
Peng Taod7e09d02013-05-02 16:46:55 +080051lnet_syntax(char *name, char *str, int offset, int width)
52{
53 static char dots[LNET_SINGLE_TEXTBUF_NOB];
54 static char dashes[LNET_SINGLE_TEXTBUF_NOB];
55
56 memset(dots, '.', sizeof(dots));
James Simmons51078e22016-02-12 12:06:04 -050057 dots[sizeof(dots) - 1] = 0;
Peng Taod7e09d02013-05-02 16:46:55 +080058 memset(dashes, '-', sizeof(dashes));
James Simmons51078e22016-02-12 12:06:04 -050059 dashes[sizeof(dashes) - 1] = 0;
Peng Taod7e09d02013-05-02 16:46:55 +080060
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);
65}
66
Benedict Boerger714340d2014-08-08 18:26:22 +020067static int
Rashika Kheria24edbe42013-10-26 00:21:24 +053068lnet_issep(char c)
Peng Taod7e09d02013-05-02 16:46:55 +080069{
70 switch (c) {
71 case '\n':
72 case '\r':
73 case ';':
74 return 1;
75 default:
76 return 0;
77 }
78}
79
Amir Shehata6c9e5a52016-02-15 10:25:54 -050080int
Peng Taod7e09d02013-05-02 16:46:55 +080081lnet_net_unique(__u32 net, struct list_head *nilist)
82{
Mike Shuey7e7ab092015-05-19 10:14:32 -040083 struct list_head *tmp;
84 lnet_ni_t *ni;
Peng Taod7e09d02013-05-02 16:46:55 +080085
Rashika Kheria24edbe42013-10-26 00:21:24 +053086 list_for_each(tmp, nilist) {
Peng Taod7e09d02013-05-02 16:46:55 +080087 ni = list_entry(tmp, lnet_ni_t, ni_list);
88
89 if (LNET_NIDNET(ni->ni_nid) == net)
90 return 0;
91 }
92
93 return 1;
94}
95
96void
97lnet_ni_free(struct lnet_ni *ni)
98{
Amir Shehata21602c72016-02-15 10:25:52 -050099 int i;
100
James Simmons06ace262016-02-12 12:06:08 -0500101 if (ni->ni_refs)
Peng Taod7e09d02013-05-02 16:46:55 +0800102 cfs_percpt_free(ni->ni_refs);
103
James Simmons06ace262016-02-12 12:06:08 -0500104 if (ni->ni_tx_queues)
Peng Taod7e09d02013-05-02 16:46:55 +0800105 cfs_percpt_free(ni->ni_tx_queues);
106
James Simmons06ace262016-02-12 12:06:08 -0500107 if (ni->ni_cpts)
Peng Taod7e09d02013-05-02 16:46:55 +0800108 cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
109
Amir Shehata243a9412016-05-06 21:30:24 -0400110 if (ni->ni_lnd_tunables)
111 LIBCFS_FREE(ni->ni_lnd_tunables, sizeof(*ni->ni_lnd_tunables));
112
Amir Shehata21602c72016-02-15 10:25:52 -0500113 for (i = 0; i < LNET_MAX_INTERFACES && ni->ni_interfaces[i]; i++) {
114 LIBCFS_FREE(ni->ni_interfaces[i],
115 strlen(ni->ni_interfaces[i]) + 1);
116 }
Peng Taod7e09d02013-05-02 16:46:55 +0800117 LIBCFS_FREE(ni, sizeof(*ni));
118}
119
Amir Shehata9c26b892016-02-22 17:29:08 -0500120lnet_ni_t *
Peng Taod7e09d02013-05-02 16:46:55 +0800121lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist)
122{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400123 struct lnet_tx_queue *tq;
124 struct lnet_ni *ni;
125 int rc;
126 int i;
Peng Taod7e09d02013-05-02 16:46:55 +0800127
128 if (!lnet_net_unique(net, nilist)) {
129 LCONSOLE_ERROR_MSG(0x111, "Duplicate network specified: %s\n",
130 libcfs_net2str(net));
131 return NULL;
132 }
133
134 LIBCFS_ALLOC(ni, sizeof(*ni));
James Simmons06ace262016-02-12 12:06:08 -0500135 if (!ni) {
Peng Taod7e09d02013-05-02 16:46:55 +0800136 CERROR("Out of memory creating network %s\n",
137 libcfs_net2str(net));
138 return NULL;
139 }
140
141 spin_lock_init(&ni->ni_lock);
142 INIT_LIST_HEAD(&ni->ni_cptlist);
143 ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(),
144 sizeof(*ni->ni_refs[0]));
James Simmons06ace262016-02-12 12:06:08 -0500145 if (!ni->ni_refs)
Peng Taod7e09d02013-05-02 16:46:55 +0800146 goto failed;
147
148 ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(),
149 sizeof(*ni->ni_tx_queues[0]));
James Simmons06ace262016-02-12 12:06:08 -0500150 if (!ni->ni_tx_queues)
Peng Taod7e09d02013-05-02 16:46:55 +0800151 goto failed;
152
153 cfs_percpt_for_each(tq, i, ni->ni_tx_queues)
154 INIT_LIST_HEAD(&tq->tq_delayed);
155
James Simmons06ace262016-02-12 12:06:08 -0500156 if (!el) {
Peng Taod7e09d02013-05-02 16:46:55 +0800157 ni->ni_cpts = NULL;
158 ni->ni_ncpts = LNET_CPT_NUMBER;
159 } else {
160 rc = cfs_expr_list_values(el, LNET_CPT_NUMBER, &ni->ni_cpts);
161 if (rc <= 0) {
162 CERROR("Failed to set CPTs for NI %s: %d\n",
163 libcfs_net2str(net), rc);
164 goto failed;
165 }
166
167 LASSERT(rc <= LNET_CPT_NUMBER);
168 if (rc == LNET_CPT_NUMBER) {
169 LIBCFS_FREE(ni->ni_cpts, rc * sizeof(ni->ni_cpts[0]));
170 ni->ni_cpts = NULL;
171 }
172
173 ni->ni_ncpts = rc;
174 }
175
176 /* LND will fill in the address part of the NID */
177 ni->ni_nid = LNET_MKNID(net, 0);
Arnd Bergmannec0067d2015-09-27 16:45:22 -0400178 ni->ni_last_alive = ktime_get_real_seconds();
Peng Taod7e09d02013-05-02 16:46:55 +0800179 list_add_tail(&ni->ni_list, nilist);
180 return ni;
181 failed:
182 lnet_ni_free(ni);
183 return NULL;
184}
185
186int
187lnet_parse_networks(struct list_head *nilist, char *networks)
188{
189 struct cfs_expr_list *el = NULL;
Amir Shehata8766cd122016-02-22 17:29:04 -0500190 int tokensize;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400191 char *tokens;
192 char *str;
193 char *tmp;
194 struct lnet_ni *ni;
195 __u32 net;
196 int nnets = 0;
Amir Shehata9c26b892016-02-22 17:29:08 -0500197 struct list_head *temp_node;
Peng Taod7e09d02013-05-02 16:46:55 +0800198
Amir Shehata8766cd122016-02-22 17:29:04 -0500199 if (!networks) {
200 CERROR("networks string is undefined\n");
201 return -EINVAL;
202 }
203
Peng Taod7e09d02013-05-02 16:46:55 +0800204 if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) {
205 /* _WAY_ conservative */
Rashika Kheriae46b3a02013-10-26 00:22:54 +0530206 LCONSOLE_ERROR_MSG(0x112,
207 "Can't parse networks: string too long\n");
Peng Taod7e09d02013-05-02 16:46:55 +0800208 return -EINVAL;
209 }
210
Amir Shehata8766cd122016-02-22 17:29:04 -0500211 tokensize = strlen(networks) + 1;
212
Peng Taod7e09d02013-05-02 16:46:55 +0800213 LIBCFS_ALLOC(tokens, tokensize);
James Simmons06ace262016-02-12 12:06:08 -0500214 if (!tokens) {
Peng Taod7e09d02013-05-02 16:46:55 +0800215 CERROR("Can't allocate net tokens\n");
216 return -ENOMEM;
217 }
218
Rashika Kheria24edbe42013-10-26 00:21:24 +0530219 memcpy(tokens, networks, tokensize);
James Simmonsd3d3d372016-02-12 12:06:05 -0500220 tmp = tokens;
221 str = tokens;
Peng Taod7e09d02013-05-02 16:46:55 +0800222
James Simmons5fd88332016-02-12 12:06:09 -0500223 while (str && *str) {
Mike Shuey7e7ab092015-05-19 10:14:32 -0400224 char *comma = strchr(str, ',');
225 char *bracket = strchr(str, '(');
226 char *square = strchr(str, '[');
227 char *iface;
228 int niface;
229 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800230
Sushuruth Sadagopan587cb022016-01-18 02:09:23 -0500231 /*
232 * NB we don't check interface conflicts here; it's the LNDs
233 * responsibility (if it cares at all)
234 */
James Simmons06ace262016-02-12 12:06:08 -0500235 if (square && (!comma || square < comma)) {
Sushuruth Sadagopan587cb022016-01-18 02:09:23 -0500236 /*
237 * i.e: o2ib0(ib0)[1,2], number between square
238 * brackets are CPTs this NI needs to be bond
239 */
James Simmons06ace262016-02-12 12:06:08 -0500240 if (bracket && bracket > square) {
Peng Taod7e09d02013-05-02 16:46:55 +0800241 tmp = square;
242 goto failed_syntax;
243 }
244
245 tmp = strchr(square, ']');
James Simmons06ace262016-02-12 12:06:08 -0500246 if (!tmp) {
Peng Taod7e09d02013-05-02 16:46:55 +0800247 tmp = square;
248 goto failed_syntax;
249 }
250
251 rc = cfs_expr_list_parse(square, tmp - square + 1,
252 0, LNET_CPT_NUMBER - 1, &el);
James Simmons5fd88332016-02-12 12:06:09 -0500253 if (rc) {
Peng Taod7e09d02013-05-02 16:46:55 +0800254 tmp = square;
255 goto failed_syntax;
256 }
257
258 while (square <= tmp)
259 *square++ = ' ';
260 }
261
James Simmons06ace262016-02-12 12:06:08 -0500262 if (!bracket || (comma && comma < bracket)) {
Peng Taod7e09d02013-05-02 16:46:55 +0800263 /* no interface list specified */
264
James Simmons06ace262016-02-12 12:06:08 -0500265 if (comma)
Peng Taod7e09d02013-05-02 16:46:55 +0800266 *comma++ = 0;
267 net = libcfs_str2net(cfs_trimwhite(str));
268
269 if (net == LNET_NIDNET(LNET_NID_ANY)) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +0530270 LCONSOLE_ERROR_MSG(0x113,
271 "Unrecognised network type\n");
Peng Taod7e09d02013-05-02 16:46:55 +0800272 tmp = str;
273 goto failed_syntax;
274 }
275
276 if (LNET_NETTYP(net) != LOLND && /* LO is implicit */
James Simmons06ace262016-02-12 12:06:08 -0500277 !lnet_ni_alloc(net, el, nilist))
Peng Taod7e09d02013-05-02 16:46:55 +0800278 goto failed;
279
James Simmons06ace262016-02-12 12:06:08 -0500280 if (el) {
Peng Taod7e09d02013-05-02 16:46:55 +0800281 cfs_expr_list_free(el);
282 el = NULL;
283 }
284
285 str = comma;
286 continue;
287 }
288
289 *bracket = 0;
290 net = libcfs_str2net(cfs_trimwhite(str));
291 if (net == LNET_NIDNET(LNET_NID_ANY)) {
292 tmp = str;
293 goto failed_syntax;
294 }
295
Peng Taod7e09d02013-05-02 16:46:55 +0800296 ni = lnet_ni_alloc(net, el, nilist);
James Simmons06ace262016-02-12 12:06:08 -0500297 if (!ni)
Peng Taod7e09d02013-05-02 16:46:55 +0800298 goto failed;
299
James Simmons06ace262016-02-12 12:06:08 -0500300 if (el) {
Peng Taod7e09d02013-05-02 16:46:55 +0800301 cfs_expr_list_free(el);
302 el = NULL;
303 }
304
305 niface = 0;
306 iface = bracket + 1;
307
308 bracket = strchr(iface, ')');
James Simmons06ace262016-02-12 12:06:08 -0500309 if (!bracket) {
Peng Taod7e09d02013-05-02 16:46:55 +0800310 tmp = iface;
311 goto failed_syntax;
312 }
313
314 *bracket = 0;
315 do {
316 comma = strchr(iface, ',');
James Simmons06ace262016-02-12 12:06:08 -0500317 if (comma)
Peng Taod7e09d02013-05-02 16:46:55 +0800318 *comma++ = 0;
319
320 iface = cfs_trimwhite(iface);
James Simmons5fd88332016-02-12 12:06:09 -0500321 if (!*iface) {
Peng Taod7e09d02013-05-02 16:46:55 +0800322 tmp = iface;
323 goto failed_syntax;
324 }
325
326 if (niface == LNET_MAX_INTERFACES) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +0530327 LCONSOLE_ERROR_MSG(0x115,
328 "Too many interfaces for net %s\n",
Peng Taod7e09d02013-05-02 16:46:55 +0800329 libcfs_net2str(net));
330 goto failed;
331 }
332
Amir Shehata21602c72016-02-15 10:25:52 -0500333 /*
334 * Allocate a separate piece of memory and copy
335 * into it the string, so we don't have
336 * a depencency on the tokens string. This way we
337 * can free the tokens at the end of the function.
338 * The newly allocated ni_interfaces[] can be
339 * freed when freeing the NI
340 */
341 LIBCFS_ALLOC(ni->ni_interfaces[niface],
342 strlen(iface) + 1);
343 if (!ni->ni_interfaces[niface]) {
344 CERROR("Can't allocate net interface name\n");
345 goto failed;
346 }
347 strncpy(ni->ni_interfaces[niface], iface,
348 strlen(iface));
349 niface++;
Peng Taod7e09d02013-05-02 16:46:55 +0800350 iface = comma;
James Simmons06ace262016-02-12 12:06:08 -0500351 } while (iface);
Peng Taod7e09d02013-05-02 16:46:55 +0800352
353 str = bracket + 1;
354 comma = strchr(bracket + 1, ',');
James Simmons06ace262016-02-12 12:06:08 -0500355 if (comma) {
Peng Taod7e09d02013-05-02 16:46:55 +0800356 *comma = 0;
357 str = cfs_trimwhite(str);
James Simmons5fd88332016-02-12 12:06:09 -0500358 if (*str) {
Peng Taod7e09d02013-05-02 16:46:55 +0800359 tmp = str;
360 goto failed_syntax;
361 }
362 str = comma + 1;
363 continue;
364 }
365
366 str = cfs_trimwhite(str);
James Simmons5fd88332016-02-12 12:06:09 -0500367 if (*str) {
Peng Taod7e09d02013-05-02 16:46:55 +0800368 tmp = str;
369 goto failed_syntax;
370 }
371 }
372
Amir Shehata9c26b892016-02-22 17:29:08 -0500373 list_for_each(temp_node, nilist)
374 nnets++;
Amir Shehata21602c72016-02-15 10:25:52 -0500375
376 LIBCFS_FREE(tokens, tokensize);
Amir Shehata9c26b892016-02-22 17:29:08 -0500377 return nnets;
Peng Taod7e09d02013-05-02 16:46:55 +0800378
379 failed_syntax:
380 lnet_syntax("networks", networks, (int)(tmp - tokens), strlen(tmp));
381 failed:
382 while (!list_empty(nilist)) {
383 ni = list_entry(nilist->next, lnet_ni_t, ni_list);
384
385 list_del(&ni->ni_list);
386 lnet_ni_free(ni);
387 }
388
James Simmons06ace262016-02-12 12:06:08 -0500389 if (el)
Peng Taod7e09d02013-05-02 16:46:55 +0800390 cfs_expr_list_free(el);
391
392 LIBCFS_FREE(tokens, tokensize);
Peng Taod7e09d02013-05-02 16:46:55 +0800393
394 return -EINVAL;
395}
396
James Simmonsddbc66a2016-02-12 12:05:59 -0500397static struct lnet_text_buf *
Rashika Kheria24edbe42013-10-26 00:21:24 +0530398lnet_new_text_buf(int str_len)
Peng Taod7e09d02013-05-02 16:46:55 +0800399{
James Simmonsddbc66a2016-02-12 12:05:59 -0500400 struct lnet_text_buf *ltb;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400401 int nob;
Peng Taod7e09d02013-05-02 16:46:55 +0800402
403 /* NB allocate space for the terminating 0 */
James Simmonsddbc66a2016-02-12 12:05:59 -0500404 nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]);
Peng Taod7e09d02013-05-02 16:46:55 +0800405 if (nob > LNET_SINGLE_TEXTBUF_NOB) {
406 /* _way_ conservative for "route net gateway..." */
407 CERROR("text buffer too big\n");
408 return NULL;
409 }
410
411 if (lnet_tbnob + nob > LNET_MAX_TEXTBUF_NOB) {
412 CERROR("Too many text buffers\n");
413 return NULL;
414 }
415
416 LIBCFS_ALLOC(ltb, nob);
James Simmons06ace262016-02-12 12:06:08 -0500417 if (!ltb)
Peng Taod7e09d02013-05-02 16:46:55 +0800418 return NULL;
419
420 ltb->ltb_size = nob;
421 ltb->ltb_text[0] = 0;
422 lnet_tbnob += nob;
423 return ltb;
424}
425
Benedict Boerger714340d2014-08-08 18:26:22 +0200426static void
James Simmonsddbc66a2016-02-12 12:05:59 -0500427lnet_free_text_buf(struct lnet_text_buf *ltb)
Peng Taod7e09d02013-05-02 16:46:55 +0800428{
429 lnet_tbnob -= ltb->ltb_size;
430 LIBCFS_FREE(ltb, ltb->ltb_size);
431}
432
Benedict Boerger714340d2014-08-08 18:26:22 +0200433static void
Peng Taod7e09d02013-05-02 16:46:55 +0800434lnet_free_text_bufs(struct list_head *tbs)
435{
James Simmonsddbc66a2016-02-12 12:05:59 -0500436 struct lnet_text_buf *ltb;
Peng Taod7e09d02013-05-02 16:46:55 +0800437
438 while (!list_empty(tbs)) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500439 ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800440
441 list_del(&ltb->ltb_list);
442 lnet_free_text_buf(ltb);
443 }
444}
445
Benedict Boerger714340d2014-08-08 18:26:22 +0200446static int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530447lnet_str2tbs_sep(struct list_head *tbs, char *str)
Peng Taod7e09d02013-05-02 16:46:55 +0800448{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400449 struct list_head pending;
450 char *sep;
451 int nob;
452 int i;
James Simmonsddbc66a2016-02-12 12:05:59 -0500453 struct lnet_text_buf *ltb;
Peng Taod7e09d02013-05-02 16:46:55 +0800454
455 INIT_LIST_HEAD(&pending);
456
457 /* Split 'str' into separate commands */
458 for (;;) {
459 /* skip leading whitespace */
Peng Taoe525a682014-03-05 21:27:18 +0800460 while (isspace(*str))
Peng Taod7e09d02013-05-02 16:46:55 +0800461 str++;
462
463 /* scan for separator or comment */
James Simmons5fd88332016-02-12 12:06:09 -0500464 for (sep = str; *sep; sep++)
Peng Taod7e09d02013-05-02 16:46:55 +0800465 if (lnet_issep(*sep) || *sep == '#')
466 break;
467
468 nob = (int)(sep - str);
469 if (nob > 0) {
470 ltb = lnet_new_text_buf(nob);
James Simmons06ace262016-02-12 12:06:08 -0500471 if (!ltb) {
Peng Taod7e09d02013-05-02 16:46:55 +0800472 lnet_free_text_bufs(&pending);
James Simmons58cb2ad2016-03-02 17:01:47 -0500473 return -ENOMEM;
Peng Taod7e09d02013-05-02 16:46:55 +0800474 }
475
476 for (i = 0; i < nob; i++)
Peng Taoe525a682014-03-05 21:27:18 +0800477 if (isspace(str[i]))
Peng Taod7e09d02013-05-02 16:46:55 +0800478 ltb->ltb_text[i] = ' ';
479 else
480 ltb->ltb_text[i] = str[i];
481
482 ltb->ltb_text[nob] = 0;
483
484 list_add_tail(&ltb->ltb_list, &pending);
485 }
486
487 if (*sep == '#') {
488 /* scan for separator */
489 do {
490 sep++;
James Simmons5fd88332016-02-12 12:06:09 -0500491 } while (*sep && !lnet_issep(*sep));
Peng Taod7e09d02013-05-02 16:46:55 +0800492 }
493
James Simmons5fd88332016-02-12 12:06:09 -0500494 if (!*sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800495 break;
496
497 str = sep + 1;
498 }
499
500 list_splice(&pending, tbs->prev);
501 return 0;
502}
503
Benedict Boerger714340d2014-08-08 18:26:22 +0200504static int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530505lnet_expand1tb(struct list_head *list,
Peng Taod7e09d02013-05-02 16:46:55 +0800506 char *str, char *sep1, char *sep2,
507 char *item, int itemlen)
508{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400509 int len1 = (int)(sep1 - str);
510 int len2 = strlen(sep2 + 1);
James Simmonsddbc66a2016-02-12 12:05:59 -0500511 struct lnet_text_buf *ltb;
Peng Taod7e09d02013-05-02 16:46:55 +0800512
Rashika Kheria24edbe42013-10-26 00:21:24 +0530513 LASSERT(*sep1 == '[');
514 LASSERT(*sep2 == ']');
Peng Taod7e09d02013-05-02 16:46:55 +0800515
516 ltb = lnet_new_text_buf(len1 + itemlen + len2);
James Simmons06ace262016-02-12 12:06:08 -0500517 if (!ltb)
Peng Taod7e09d02013-05-02 16:46:55 +0800518 return -ENOMEM;
519
520 memcpy(ltb->ltb_text, str, len1);
521 memcpy(&ltb->ltb_text[len1], item, itemlen);
James Simmons51078e22016-02-12 12:06:04 -0500522 memcpy(&ltb->ltb_text[len1 + itemlen], sep2 + 1, len2);
Peng Taod7e09d02013-05-02 16:46:55 +0800523 ltb->ltb_text[len1 + itemlen + len2] = 0;
524
525 list_add_tail(&ltb->ltb_list, list);
526 return 0;
527}
528
Benedict Boerger714340d2014-08-08 18:26:22 +0200529static int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530530lnet_str2tbs_expand(struct list_head *tbs, char *str)
Peng Taod7e09d02013-05-02 16:46:55 +0800531{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400532 char num[16];
533 struct list_head pending;
534 char *sep;
535 char *sep2;
536 char *parsed;
537 char *enditem;
538 int lo;
539 int hi;
540 int stride;
541 int i;
542 int nob;
543 int scanned;
Peng Taod7e09d02013-05-02 16:46:55 +0800544
545 INIT_LIST_HEAD(&pending);
546
547 sep = strchr(str, '[');
James Simmons06ace262016-02-12 12:06:08 -0500548 if (!sep) /* nothing to expand */
Peng Taod7e09d02013-05-02 16:46:55 +0800549 return 0;
550
551 sep2 = strchr(sep, ']');
James Simmons06ace262016-02-12 12:06:08 -0500552 if (!sep2)
Peng Taod7e09d02013-05-02 16:46:55 +0800553 goto failed;
554
555 for (parsed = sep; parsed < sep2; parsed = enditem) {
Peng Taod7e09d02013-05-02 16:46:55 +0800556 enditem = ++parsed;
557 while (enditem < sep2 && *enditem != ',')
558 enditem++;
559
560 if (enditem == parsed) /* no empty items */
561 goto failed;
562
Rafaƫl Bocquet3a338e22015-04-02 17:12:33 +0200563 if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi,
564 &stride, &scanned) < 3) {
Peng Taod7e09d02013-05-02 16:46:55 +0800565 if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) {
Peng Taod7e09d02013-05-02 16:46:55 +0800566 /* simple string enumeration */
James Simmonsc314c312016-02-12 12:06:01 -0500567 if (lnet_expand1tb(&pending, str, sep, sep2,
568 parsed,
James Simmons5fd88332016-02-12 12:06:09 -0500569 (int)(enditem - parsed))) {
Peng Taod7e09d02013-05-02 16:46:55 +0800570 goto failed;
Rafaƫl Bocquet3a338e22015-04-02 17:12:33 +0200571 }
Peng Taod7e09d02013-05-02 16:46:55 +0800572 continue;
573 }
574
575 stride = 1;
576 }
577
578 /* range expansion */
579
580 if (enditem != parsed + scanned) /* no trailing junk */
581 goto failed;
582
583 if (hi < 0 || lo < 0 || stride < 0 || hi < lo ||
James Simmons5fd88332016-02-12 12:06:09 -0500584 (hi - lo) % stride)
Peng Taod7e09d02013-05-02 16:46:55 +0800585 goto failed;
586
587 for (i = lo; i <= hi; i += stride) {
Peng Taod7e09d02013-05-02 16:46:55 +0800588 snprintf(num, sizeof(num), "%d", i);
589 nob = strlen(num);
590 if (nob + 1 == sizeof(num))
591 goto failed;
592
593 if (lnet_expand1tb(&pending, str, sep, sep2,
James Simmons5fd88332016-02-12 12:06:09 -0500594 num, nob))
Peng Taod7e09d02013-05-02 16:46:55 +0800595 goto failed;
596 }
597 }
598
599 list_splice(&pending, tbs->prev);
600 return 1;
601
602 failed:
603 lnet_free_text_bufs(&pending);
James Simmons58cb2ad2016-03-02 17:01:47 -0500604 return -EINVAL;
Peng Taod7e09d02013-05-02 16:46:55 +0800605}
606
Benedict Boerger714340d2014-08-08 18:26:22 +0200607static int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530608lnet_parse_hops(char *str, unsigned int *hops)
Peng Taod7e09d02013-05-02 16:46:55 +0800609{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400610 int len = strlen(str);
611 int nob = len;
Peng Taod7e09d02013-05-02 16:46:55 +0800612
613 return (sscanf(str, "%u%n", hops, &nob) >= 1 &&
614 nob == len &&
615 *hops > 0 && *hops < 256);
616}
617
Doug Ouchareke75fb872013-12-09 22:56:54 +0800618#define LNET_PRIORITY_SEPARATOR (':')
619
Benedict Boerger714340d2014-08-08 18:26:22 +0200620static int
Doug Ouchareke75fb872013-12-09 22:56:54 +0800621lnet_parse_priority(char *str, unsigned int *priority, char **token)
622{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400623 int nob;
Doug Ouchareke75fb872013-12-09 22:56:54 +0800624 char *sep;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400625 int len;
Doug Ouchareke75fb872013-12-09 22:56:54 +0800626
627 sep = strchr(str, LNET_PRIORITY_SEPARATOR);
James Simmons06ace262016-02-12 12:06:08 -0500628 if (!sep) {
Doug Ouchareke75fb872013-12-09 22:56:54 +0800629 *priority = 0;
630 return 0;
631 }
632 len = strlen(sep + 1);
633
James Simmons51078e22016-02-12 12:06:04 -0500634 if ((sscanf((sep + 1), "%u%n", priority, &nob) < 1) || (len != nob)) {
Sushuruth Sadagopan587cb022016-01-18 02:09:23 -0500635 /*
636 * Update the caller's token pointer so it treats the found
637 * priority as the token to report in the error message.
638 */
Doug Ouchareke75fb872013-12-09 22:56:54 +0800639 *token += sep - str + 1;
James Simmons58cb2ad2016-03-02 17:01:47 -0500640 return -EINVAL;
Doug Ouchareke75fb872013-12-09 22:56:54 +0800641 }
642
643 CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob);
644
645 /*
646 * Change priority separator to \0 to be able to parse NID
647 */
648 *sep = '\0';
649 return 0;
650}
Peng Taod7e09d02013-05-02 16:46:55 +0800651
Benedict Boerger714340d2014-08-08 18:26:22 +0200652static int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530653lnet_parse_route(char *str, int *im_a_router)
Peng Taod7e09d02013-05-02 16:46:55 +0800654{
655 /* static scratch buffer OK (single threaded) */
Mike Shuey7e7ab092015-05-19 10:14:32 -0400656 static char cmd[LNET_SINGLE_TEXTBUF_NOB];
Peng Taod7e09d02013-05-02 16:46:55 +0800657
Mike Shuey7e7ab092015-05-19 10:14:32 -0400658 struct list_head nets;
659 struct list_head gateways;
660 struct list_head *tmp1;
661 struct list_head *tmp2;
662 __u32 net;
663 lnet_nid_t nid;
James Simmonsddbc66a2016-02-12 12:05:59 -0500664 struct lnet_text_buf *ltb;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400665 int rc;
666 char *sep;
667 char *token = str;
668 int ntokens = 0;
669 int myrc = -1;
Amir Shehatab9bbb612016-03-02 17:01:46 -0500670 __u32 hops;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400671 int got_hops = 0;
672 unsigned int priority = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800673
674 INIT_LIST_HEAD(&gateways);
675 INIT_LIST_HEAD(&nets);
676
677 /* save a copy of the string for error messages */
Dmitry Eremin9563fe82015-11-04 13:40:00 -0500678 strncpy(cmd, str, sizeof(cmd));
679 cmd[sizeof(cmd) - 1] = '\0';
Peng Taod7e09d02013-05-02 16:46:55 +0800680
681 sep = str;
682 for (;;) {
683 /* scan for token start */
Peng Taoe525a682014-03-05 21:27:18 +0800684 while (isspace(*sep))
Peng Taod7e09d02013-05-02 16:46:55 +0800685 sep++;
James Simmons5fd88332016-02-12 12:06:09 -0500686 if (!*sep) {
Peng Taod7e09d02013-05-02 16:46:55 +0800687 if (ntokens < (got_hops ? 3 : 2))
688 goto token_error;
689 break;
690 }
691
692 ntokens++;
693 token = sep++;
694
695 /* scan for token end */
James Simmons5fd88332016-02-12 12:06:09 -0500696 while (*sep && !isspace(*sep))
Peng Taod7e09d02013-05-02 16:46:55 +0800697 sep++;
James Simmons5fd88332016-02-12 12:06:09 -0500698 if (*sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800699 *sep++ = 0;
700
701 if (ntokens == 1) {
702 tmp2 = &nets; /* expanding nets */
703 } else if (ntokens == 2 &&
704 lnet_parse_hops(token, &hops)) {
705 got_hops = 1; /* got a hop count */
706 continue;
707 } else {
708 tmp2 = &gateways; /* expanding gateways */
709 }
710
711 ltb = lnet_new_text_buf(strlen(token));
James Simmons06ace262016-02-12 12:06:08 -0500712 if (!ltb)
Peng Taod7e09d02013-05-02 16:46:55 +0800713 goto out;
714
715 strcpy(ltb->ltb_text, token);
716 tmp1 = &ltb->ltb_list;
717 list_add_tail(tmp1, tmp2);
718
719 while (tmp1 != tmp2) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500720 ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800721
722 rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text);
723 if (rc < 0)
724 goto token_error;
725
726 tmp1 = tmp1->next;
727
728 if (rc > 0) { /* expanded! */
729 list_del(&ltb->ltb_list);
730 lnet_free_text_buf(ltb);
731 continue;
732 }
733
734 if (ntokens == 1) {
735 net = libcfs_str2net(ltb->ltb_text);
736 if (net == LNET_NIDNET(LNET_NID_ANY) ||
737 LNET_NETTYP(net) == LOLND)
738 goto token_error;
739 } else {
Doug Ouchareke75fb872013-12-09 22:56:54 +0800740 rc = lnet_parse_priority(ltb->ltb_text,
741 &priority, &token);
742 if (rc < 0)
743 goto token_error;
744
Peng Taod7e09d02013-05-02 16:46:55 +0800745 nid = libcfs_str2nid(ltb->ltb_text);
746 if (nid == LNET_NID_ANY ||
747 LNET_NETTYP(LNET_NIDNET(nid)) == LOLND)
748 goto token_error;
749 }
750 }
751 }
752
Amir Shehatab9bbb612016-03-02 17:01:46 -0500753 /**
754 * if there are no hops set then we want to flag this value as
755 * unset since hops is an optional parameter
756 */
Peng Taod7e09d02013-05-02 16:46:55 +0800757 if (!got_hops)
Amir Shehatab9bbb612016-03-02 17:01:46 -0500758 hops = LNET_UNDEFINED_HOPS;
Peng Taod7e09d02013-05-02 16:46:55 +0800759
Rashika Kheria24edbe42013-10-26 00:21:24 +0530760 LASSERT(!list_empty(&nets));
761 LASSERT(!list_empty(&gateways));
Peng Taod7e09d02013-05-02 16:46:55 +0800762
Rashika Kheria24edbe42013-10-26 00:21:24 +0530763 list_for_each(tmp1, &nets) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500764 ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800765 net = libcfs_str2net(ltb->ltb_text);
Rashika Kheria24edbe42013-10-26 00:21:24 +0530766 LASSERT(net != LNET_NIDNET(LNET_NID_ANY));
Peng Taod7e09d02013-05-02 16:46:55 +0800767
Rashika Kheria24edbe42013-10-26 00:21:24 +0530768 list_for_each(tmp2, &gateways) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500769 ltb = list_entry(tmp2, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800770 nid = libcfs_str2nid(ltb->ltb_text);
Rashika Kheria24edbe42013-10-26 00:21:24 +0530771 LASSERT(nid != LNET_NID_ANY);
Peng Taod7e09d02013-05-02 16:46:55 +0800772
773 if (lnet_islocalnid(nid)) {
774 *im_a_router = 1;
775 continue;
776 }
777
Doug Ouchareke75fb872013-12-09 22:56:54 +0800778 rc = lnet_add_route(net, hops, nid, priority);
Amir Shehatabe8240a2016-02-22 17:29:09 -0500779 if (rc && rc != -EEXIST && rc != -EHOSTUNREACH) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +0530780 CERROR("Can't create route to %s via %s\n",
Peng Taod7e09d02013-05-02 16:46:55 +0800781 libcfs_net2str(net),
782 libcfs_nid2str(nid));
783 goto out;
784 }
785 }
786 }
787
788 myrc = 0;
789 goto out;
790
791 token_error:
792 lnet_syntax("routes", cmd, (int)(token - str), strlen(token));
793 out:
794 lnet_free_text_bufs(&nets);
795 lnet_free_text_bufs(&gateways);
796 return myrc;
797}
798
Benedict Boerger714340d2014-08-08 18:26:22 +0200799static int
Peng Taod7e09d02013-05-02 16:46:55 +0800800lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router)
801{
James Simmonsddbc66a2016-02-12 12:05:59 -0500802 struct lnet_text_buf *ltb;
Peng Taod7e09d02013-05-02 16:46:55 +0800803
804 while (!list_empty(tbs)) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500805 ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800806
807 if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) {
808 lnet_free_text_bufs(tbs);
809 return -EINVAL;
810 }
811
812 list_del(&ltb->ltb_list);
813 lnet_free_text_buf(ltb);
814 }
815
816 return 0;
817}
818
819int
Rashika Kheria24edbe42013-10-26 00:21:24 +0530820lnet_parse_routes(char *routes, int *im_a_router)
Peng Taod7e09d02013-05-02 16:46:55 +0800821{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400822 struct list_head tbs;
823 int rc = 0;
Peng Taod7e09d02013-05-02 16:46:55 +0800824
825 *im_a_router = 0;
826
827 INIT_LIST_HEAD(&tbs);
828
829 if (lnet_str2tbs_sep(&tbs, routes) < 0) {
830 CERROR("Error parsing routes\n");
831 rc = -EINVAL;
832 } else {
833 rc = lnet_parse_route_tbs(&tbs, im_a_router);
834 }
835
James Simmons5fd88332016-02-12 12:06:09 -0500836 LASSERT(!lnet_tbnob);
Peng Taod7e09d02013-05-02 16:46:55 +0800837 return rc;
838}
839
Benedict Boerger714340d2014-08-08 18:26:22 +0200840static int
Peng Taod7e09d02013-05-02 16:46:55 +0800841lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip)
842{
Rashika Kheria24edbe42013-10-26 00:21:24 +0530843 LIST_HEAD(list);
Mike Shuey7e7ab092015-05-19 10:14:32 -0400844 int rc;
845 int i;
Peng Taod7e09d02013-05-02 16:46:55 +0800846
847 rc = cfs_ip_addr_parse(token, len, &list);
James Simmons5fd88332016-02-12 12:06:09 -0500848 if (rc)
Peng Taod7e09d02013-05-02 16:46:55 +0800849 return rc;
850
851 for (rc = i = 0; !rc && i < nip; i++)
852 rc = cfs_ip_addr_match(ipaddrs[i], &list);
853
James Simmonsa620ec62015-10-21 21:52:42 -0400854 cfs_expr_list_free_list(&list);
Peng Taod7e09d02013-05-02 16:46:55 +0800855
856 return rc;
857}
858
Benedict Boerger714340d2014-08-08 18:26:22 +0200859static int
Peng Taod7e09d02013-05-02 16:46:55 +0800860lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip)
861{
862 static char tokens[LNET_SINGLE_TEXTBUF_NOB];
863
Mike Shuey7e7ab092015-05-19 10:14:32 -0400864 int matched = 0;
865 int ntokens = 0;
866 int len;
Peng Taod7e09d02013-05-02 16:46:55 +0800867 char *net = NULL;
868 char *sep;
869 char *token;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400870 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +0800871
Rashika Kheria24edbe42013-10-26 00:21:24 +0530872 LASSERT(strlen(net_entry) < sizeof(tokens));
Peng Taod7e09d02013-05-02 16:46:55 +0800873
874 /* work on a copy of the string */
875 strcpy(tokens, net_entry);
876 sep = tokens;
877 for (;;) {
878 /* scan for token start */
Peng Taoe525a682014-03-05 21:27:18 +0800879 while (isspace(*sep))
Peng Taod7e09d02013-05-02 16:46:55 +0800880 sep++;
James Simmons5fd88332016-02-12 12:06:09 -0500881 if (!*sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800882 break;
883
884 token = sep++;
885
886 /* scan for token end */
James Simmons5fd88332016-02-12 12:06:09 -0500887 while (*sep && !isspace(*sep))
Peng Taod7e09d02013-05-02 16:46:55 +0800888 sep++;
James Simmons5fd88332016-02-12 12:06:09 -0500889 if (*sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800890 *sep++ = 0;
891
James Simmons5fd88332016-02-12 12:06:09 -0500892 if (!ntokens++) {
Peng Taod7e09d02013-05-02 16:46:55 +0800893 net = token;
894 continue;
895 }
896
897 len = strlen(token);
898
899 rc = lnet_match_network_token(token, len, ipaddrs, nip);
900 if (rc < 0) {
901 lnet_syntax("ip2nets", net_entry,
902 (int)(token - tokens), len);
903 return rc;
904 }
905
James Simmons5fd88332016-02-12 12:06:09 -0500906 if (rc)
907 matched |= 1;
Peng Taod7e09d02013-05-02 16:46:55 +0800908 }
909
910 if (!matched)
911 return 0;
912
913 strcpy(net_entry, net); /* replace with matched net */
914 return 1;
915}
916
Benedict Boerger714340d2014-08-08 18:26:22 +0200917static __u32
Peng Taod7e09d02013-05-02 16:46:55 +0800918lnet_netspec2net(char *netspec)
919{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400920 char *bracket = strchr(netspec, '(');
921 __u32 net;
Peng Taod7e09d02013-05-02 16:46:55 +0800922
James Simmons06ace262016-02-12 12:06:08 -0500923 if (bracket)
Peng Taod7e09d02013-05-02 16:46:55 +0800924 *bracket = 0;
925
926 net = libcfs_str2net(netspec);
927
James Simmons06ace262016-02-12 12:06:08 -0500928 if (bracket)
Peng Taod7e09d02013-05-02 16:46:55 +0800929 *bracket = '(';
930
931 return net;
932}
933
Benedict Boerger714340d2014-08-08 18:26:22 +0200934static int
Peng Taod7e09d02013-05-02 16:46:55 +0800935lnet_splitnets(char *source, struct list_head *nets)
936{
Mike Shuey7e7ab092015-05-19 10:14:32 -0400937 int offset = 0;
938 int offset2;
939 int len;
James Simmonsddbc66a2016-02-12 12:05:59 -0500940 struct lnet_text_buf *tb;
941 struct lnet_text_buf *tb2;
Mike Shuey7e7ab092015-05-19 10:14:32 -0400942 struct list_head *t;
943 char *sep;
944 char *bracket;
945 __u32 net;
Peng Taod7e09d02013-05-02 16:46:55 +0800946
Rashika Kheria24edbe42013-10-26 00:21:24 +0530947 LASSERT(!list_empty(nets));
948 LASSERT(nets->next == nets->prev); /* single entry */
Peng Taod7e09d02013-05-02 16:46:55 +0800949
James Simmonsddbc66a2016-02-12 12:05:59 -0500950 tb = list_entry(nets->next, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800951
952 for (;;) {
953 sep = strchr(tb->ltb_text, ',');
954 bracket = strchr(tb->ltb_text, '(');
955
James Simmons06ace262016-02-12 12:06:08 -0500956 if (sep && bracket && bracket < sep) {
Peng Taod7e09d02013-05-02 16:46:55 +0800957 /* netspec lists interfaces... */
958
959 offset2 = offset + (int)(bracket - tb->ltb_text);
960 len = strlen(bracket);
961
962 bracket = strchr(bracket + 1, ')');
963
James Simmons06ace262016-02-12 12:06:08 -0500964 if (!bracket ||
James Simmons5fd88332016-02-12 12:06:09 -0500965 !(bracket[1] == ',' || !bracket[1])) {
Peng Taod7e09d02013-05-02 16:46:55 +0800966 lnet_syntax("ip2nets", source, offset2, len);
967 return -EINVAL;
968 }
969
James Simmons5fd88332016-02-12 12:06:09 -0500970 sep = !bracket[1] ? NULL : bracket + 1;
Peng Taod7e09d02013-05-02 16:46:55 +0800971 }
972
James Simmons06ace262016-02-12 12:06:08 -0500973 if (sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800974 *sep++ = 0;
975
976 net = lnet_netspec2net(tb->ltb_text);
977 if (net == LNET_NIDNET(LNET_NID_ANY)) {
978 lnet_syntax("ip2nets", source, offset,
979 strlen(tb->ltb_text));
980 return -EINVAL;
981 }
982
983 list_for_each(t, nets) {
James Simmonsddbc66a2016-02-12 12:05:59 -0500984 tb2 = list_entry(t, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +0800985
986 if (tb2 == tb)
987 continue;
988
989 if (net == lnet_netspec2net(tb2->ltb_text)) {
990 /* duplicate network */
991 lnet_syntax("ip2nets", source, offset,
992 strlen(tb->ltb_text));
993 return -EINVAL;
994 }
995 }
996
James Simmons06ace262016-02-12 12:06:08 -0500997 if (!sep)
Peng Taod7e09d02013-05-02 16:46:55 +0800998 return 0;
999
1000 offset += (int)(sep - tb->ltb_text);
Dmitry Eremin9563fe82015-11-04 13:40:00 -05001001 len = strlen(sep);
1002 tb2 = lnet_new_text_buf(len);
James Simmons06ace262016-02-12 12:06:08 -05001003 if (!tb2)
Peng Taod7e09d02013-05-02 16:46:55 +08001004 return -ENOMEM;
1005
Dmitry Eremin9563fe82015-11-04 13:40:00 -05001006 strncpy(tb2->ltb_text, sep, len);
1007 tb2->ltb_text[len] = '\0';
Peng Taod7e09d02013-05-02 16:46:55 +08001008 list_add_tail(&tb2->ltb_list, nets);
1009
1010 tb = tb2;
1011 }
1012}
1013
Benedict Boerger714340d2014-08-08 18:26:22 +02001014static int
Rashika Kheria24edbe42013-10-26 00:21:24 +05301015lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
Peng Taod7e09d02013-05-02 16:46:55 +08001016{
Mike Shuey7e7ab092015-05-19 10:14:32 -04001017 static char networks[LNET_SINGLE_TEXTBUF_NOB];
1018 static char source[LNET_SINGLE_TEXTBUF_NOB];
Peng Taod7e09d02013-05-02 16:46:55 +08001019
Mike Shuey7e7ab092015-05-19 10:14:32 -04001020 struct list_head raw_entries;
1021 struct list_head matched_nets;
1022 struct list_head current_nets;
1023 struct list_head *t;
1024 struct list_head *t2;
James Simmonsddbc66a2016-02-12 12:05:59 -05001025 struct lnet_text_buf *tb;
Bhaktipriya Shridharcb734cf2016-03-12 01:33:03 +05301026 struct lnet_text_buf *temp;
James Simmonsddbc66a2016-02-12 12:05:59 -05001027 struct lnet_text_buf *tb2;
Mike Shuey7e7ab092015-05-19 10:14:32 -04001028 __u32 net1;
1029 __u32 net2;
1030 int len;
1031 int count;
1032 int dup;
1033 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +08001034
1035 INIT_LIST_HEAD(&raw_entries);
1036 if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) {
1037 CERROR("Error parsing ip2nets\n");
James Simmons5fd88332016-02-12 12:06:09 -05001038 LASSERT(!lnet_tbnob);
Peng Taod7e09d02013-05-02 16:46:55 +08001039 return -EINVAL;
1040 }
1041
1042 INIT_LIST_HEAD(&matched_nets);
1043 INIT_LIST_HEAD(&current_nets);
1044 networks[0] = 0;
1045 count = 0;
1046 len = 0;
1047 rc = 0;
1048
Bhaktipriya Shridharcb734cf2016-03-12 01:33:03 +05301049 list_for_each_entry_safe(tb, temp, &raw_entries, ltb_list) {
Dmitry Eremin9563fe82015-11-04 13:40:00 -05001050 strncpy(source, tb->ltb_text, sizeof(source));
James Simmons51078e22016-02-12 12:06:04 -05001051 source[sizeof(source) - 1] = '\0';
Peng Taod7e09d02013-05-02 16:46:55 +08001052
1053 /* replace ltb_text with the network(s) add on match */
1054 rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip);
1055 if (rc < 0)
1056 break;
1057
1058 list_del(&tb->ltb_list);
1059
James Simmons5fd88332016-02-12 12:06:09 -05001060 if (!rc) { /* no match */
Peng Taod7e09d02013-05-02 16:46:55 +08001061 lnet_free_text_buf(tb);
1062 continue;
1063 }
1064
1065 /* split into separate networks */
1066 INIT_LIST_HEAD(&current_nets);
1067 list_add(&tb->ltb_list, &current_nets);
1068 rc = lnet_splitnets(source, &current_nets);
1069 if (rc < 0)
1070 break;
1071
1072 dup = 0;
Rashika Kheria24edbe42013-10-26 00:21:24 +05301073 list_for_each(t, &current_nets) {
James Simmonsddbc66a2016-02-12 12:05:59 -05001074 tb = list_entry(t, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +08001075 net1 = lnet_netspec2net(tb->ltb_text);
Rashika Kheria24edbe42013-10-26 00:21:24 +05301076 LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY));
Peng Taod7e09d02013-05-02 16:46:55 +08001077
1078 list_for_each(t2, &matched_nets) {
James Simmonsddbc66a2016-02-12 12:05:59 -05001079 tb2 = list_entry(t2, struct lnet_text_buf,
1080 ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +08001081 net2 = lnet_netspec2net(tb2->ltb_text);
Rashika Kheria24edbe42013-10-26 00:21:24 +05301082 LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY));
Peng Taod7e09d02013-05-02 16:46:55 +08001083
1084 if (net1 == net2) {
1085 dup = 1;
1086 break;
1087 }
1088 }
1089
1090 if (dup)
1091 break;
1092 }
1093
1094 if (dup) {
1095 lnet_free_text_bufs(&current_nets);
1096 continue;
1097 }
1098
1099 list_for_each_safe(t, t2, &current_nets) {
James Simmonsddbc66a2016-02-12 12:05:59 -05001100 tb = list_entry(t, struct lnet_text_buf, ltb_list);
Peng Taod7e09d02013-05-02 16:46:55 +08001101
1102 list_del(&tb->ltb_list);
1103 list_add_tail(&tb->ltb_list, &matched_nets);
1104
1105 len += snprintf(networks + len, sizeof(networks) - len,
James Simmons5fd88332016-02-12 12:06:09 -05001106 "%s%s", !len ? "" : ",",
Peng Taod7e09d02013-05-02 16:46:55 +08001107 tb->ltb_text);
1108
1109 if (len >= sizeof(networks)) {
1110 CERROR("Too many matched networks\n");
1111 rc = -E2BIG;
1112 goto out;
1113 }
1114 }
1115
1116 count++;
1117 }
1118
1119 out:
1120 lnet_free_text_bufs(&raw_entries);
1121 lnet_free_text_bufs(&matched_nets);
1122 lnet_free_text_bufs(&current_nets);
James Simmons5fd88332016-02-12 12:06:09 -05001123 LASSERT(!lnet_tbnob);
Peng Taod7e09d02013-05-02 16:46:55 +08001124
1125 if (rc < 0)
1126 return rc;
1127
1128 *networksp = networks;
1129 return count;
1130}
1131
Benedict Boerger714340d2014-08-08 18:26:22 +02001132static int
Rashika Kheria24edbe42013-10-26 00:21:24 +05301133lnet_ipaddr_enumerate(__u32 **ipaddrsp)
Peng Taod7e09d02013-05-02 16:46:55 +08001134{
Mike Shuey7e7ab092015-05-19 10:14:32 -04001135 int up;
1136 __u32 netmask;
1137 __u32 *ipaddrs;
1138 __u32 *ipaddrs2;
1139 int nip;
1140 char **ifnames;
James Simmons1ad6a732015-06-08 22:27:10 -04001141 int nif = lnet_ipif_enumerate(&ifnames);
Mike Shuey7e7ab092015-05-19 10:14:32 -04001142 int i;
1143 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +08001144
1145 if (nif <= 0)
1146 return nif;
1147
1148 LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs));
James Simmons06ace262016-02-12 12:06:08 -05001149 if (!ipaddrs) {
Peng Taod7e09d02013-05-02 16:46:55 +08001150 CERROR("Can't allocate ipaddrs[%d]\n", nif);
James Simmons1ad6a732015-06-08 22:27:10 -04001151 lnet_ipif_free_enumeration(ifnames, nif);
Peng Taod7e09d02013-05-02 16:46:55 +08001152 return -ENOMEM;
1153 }
1154
1155 for (i = nip = 0; i < nif; i++) {
1156 if (!strcmp(ifnames[i], "lo"))
1157 continue;
1158
James Simmons1ad6a732015-06-08 22:27:10 -04001159 rc = lnet_ipif_query(ifnames[i], &up, &ipaddrs[nip], &netmask);
James Simmons5fd88332016-02-12 12:06:09 -05001160 if (rc) {
Peng Taod7e09d02013-05-02 16:46:55 +08001161 CWARN("Can't query interface %s: %d\n",
1162 ifnames[i], rc);
1163 continue;
1164 }
1165
1166 if (!up) {
1167 CWARN("Ignoring interface %s: it's down\n",
1168 ifnames[i]);
1169 continue;
1170 }
1171
1172 nip++;
1173 }
1174
James Simmons1ad6a732015-06-08 22:27:10 -04001175 lnet_ipif_free_enumeration(ifnames, nif);
Peng Taod7e09d02013-05-02 16:46:55 +08001176
1177 if (nip == nif) {
1178 *ipaddrsp = ipaddrs;
1179 } else {
1180 if (nip > 0) {
1181 LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2));
James Simmons06ace262016-02-12 12:06:08 -05001182 if (!ipaddrs2) {
Peng Taod7e09d02013-05-02 16:46:55 +08001183 CERROR("Can't allocate ipaddrs[%d]\n", nip);
1184 nip = -ENOMEM;
1185 } else {
1186 memcpy(ipaddrs2, ipaddrs,
1187 nip * sizeof(*ipaddrs));
1188 *ipaddrsp = ipaddrs2;
1189 rc = nip;
1190 }
1191 }
Shivani Bhardwajcfa38112015-10-29 12:28:31 +05301192 LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
Peng Taod7e09d02013-05-02 16:46:55 +08001193 }
1194 return nip;
1195}
1196
1197int
Rashika Kheria24edbe42013-10-26 00:21:24 +05301198lnet_parse_ip2nets(char **networksp, char *ip2nets)
Peng Taod7e09d02013-05-02 16:46:55 +08001199{
Mike Shuey7e7ab092015-05-19 10:14:32 -04001200 __u32 *ipaddrs = NULL;
1201 int nip = lnet_ipaddr_enumerate(&ipaddrs);
1202 int rc;
Peng Taod7e09d02013-05-02 16:46:55 +08001203
1204 if (nip < 0) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +05301205 LCONSOLE_ERROR_MSG(0x117,
1206 "Error %d enumerating local IP interfaces for ip2nets to match\n",
1207 nip);
Peng Taod7e09d02013-05-02 16:46:55 +08001208 return nip;
1209 }
1210
James Simmons5fd88332016-02-12 12:06:09 -05001211 if (!nip) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +05301212 LCONSOLE_ERROR_MSG(0x118,
1213 "No local IP interfaces for ip2nets to match\n");
Peng Taod7e09d02013-05-02 16:46:55 +08001214 return -ENOENT;
1215 }
1216
1217 rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip);
Shivani Bhardwajcfa38112015-10-29 12:28:31 +05301218 LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs));
Peng Taod7e09d02013-05-02 16:46:55 +08001219
1220 if (rc < 0) {
1221 LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc);
1222 return rc;
1223 }
1224
James Simmons5fd88332016-02-12 12:06:09 -05001225 if (!rc) {
Rashika Kheriae46b3a02013-10-26 00:22:54 +05301226 LCONSOLE_ERROR_MSG(0x11a,
1227 "ip2nets does not match any local IP interfaces\n");
Peng Taod7e09d02013-05-02 16:46:55 +08001228 return -ENOENT;
1229 }
1230
1231 return 0;
1232}