Whamcloud - gitweb
08609e3d9423808eb2d442f2c539afea6e0c09e1
[fs/lustre-release.git] / lnet / lnet / config.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31
32 #define DEBUG_SUBSYSTEM S_LNET
33
34 #include <linux/ctype.h>
35 #include <linux/inetdevice.h>
36 #include <linux/nsproxy.h>
37 #include <net/net_namespace.h>
38 #include <lnet/lib-lnet.h>
39 #include <net/addrconf.h>
40
41 /* tmp struct for parsing routes */
42 struct lnet_text_buf {
43         struct list_head        ltb_list;       /* stash on lists */
44         int                     ltb_size;       /* allocated size */
45         char                    ltb_text[0];    /* text buffer */
46 };
47
48 static int lnet_tbnob = 0;                      /* track text buf allocation */
49 #define LNET_MAX_TEXTBUF_NOB     (64<<10)       /* bound allocation */
50 #define LNET_SINGLE_TEXTBUF_NOB  (4<<10)
51
52 #define SPACESTR " \t\v\r\n"
53 #define DELIMITERS ":()[]"
54
55 static void
56 lnet_syntax(const char *name, const char *str, int offset, int width)
57 {
58         static char dots[LNET_SINGLE_TEXTBUF_NOB];
59         static char dashes[LNET_SINGLE_TEXTBUF_NOB];
60
61         memset(dots, '.', sizeof(dots));
62         dots[sizeof(dots)-1] = 0;
63         memset(dashes, '-', sizeof(dashes));
64         dashes[sizeof(dashes)-1] = 0;
65
66         LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str);
67         LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n",
68                            (int)strlen(name), dots, offset, dots,
69                             (width < 1) ? 0 : width - 1, dashes);
70 }
71
72 static int
73 lnet_issep (char c)
74 {
75         switch (c) {
76         case '\n':
77         case '\r':
78         case ';':
79                 return 1;
80         default:
81                 return 0;
82         }
83 }
84
85 bool
86 lnet_net_unique(__u32 net_id, struct list_head *netlist,
87                 struct lnet_net **net)
88 {
89         struct lnet_net  *net_l;
90
91         if (!netlist)
92                 return true;
93
94         list_for_each_entry(net_l, netlist, net_list) {
95                 if (net_l->net_id == net_id) {
96                         if (net != NULL)
97                                 *net = net_l;
98                         return false;
99                 }
100         }
101
102         return true;
103 }
104
105 /* check that the NI is unique within the list of NIs already added to
106  * a network */
107 bool
108 lnet_ni_unique_net(struct list_head *nilist, char *iface)
109 {
110         struct list_head *tmp;
111         struct lnet_ni *ni;
112
113         list_for_each(tmp, nilist) {
114                 ni = list_entry(tmp, struct lnet_ni, ni_netlist);
115
116                 if (ni->ni_interface != NULL &&
117                     strncmp(ni->ni_interface, iface, strlen(iface)) == 0)
118                         return false;
119         }
120
121         return true;
122 }
123 static bool
124 in_array(__u32 *array, __u32 size, __u32 value)
125 {
126         int i;
127
128         for (i = 0; i < size; i++) {
129                 if (array[i] == value)
130                         return false;
131         }
132
133         return true;
134 }
135
136 static int
137 lnet_net_append_cpts(__u32 *cpts, __u32 ncpts, struct lnet_net *net)
138 {
139         __u32 *added_cpts = NULL;
140         int i, j = 0, rc = 0;
141
142         /*
143          * no need to go futher since a subset of the NIs already exist on
144          * all CPTs
145          */
146         if (net->net_ncpts == LNET_CPT_NUMBER)
147                 return 0;
148
149         if (cpts == NULL) {
150                 /* there is an NI which will exist on all CPTs */
151                 if (net->net_cpts != NULL)
152                         CFS_FREE_PTR_ARRAY(net->net_cpts, net->net_ncpts);
153                 net->net_cpts = NULL;
154                 net->net_ncpts = LNET_CPT_NUMBER;
155                 return 0;
156         }
157
158         if (net->net_cpts == NULL) {
159                 CFS_ALLOC_PTR_ARRAY(net->net_cpts, ncpts);
160                 if (net->net_cpts == NULL)
161                         return -ENOMEM;
162                 memcpy(net->net_cpts, cpts, ncpts * sizeof(*net->net_cpts));
163                 net->net_ncpts = ncpts;
164                 return 0;
165         }
166
167         CFS_ALLOC_PTR_ARRAY(added_cpts, LNET_CPT_NUMBER);
168         if (added_cpts == NULL)
169                 return -ENOMEM;
170
171         for (i = 0; i < ncpts; i++) {
172                 if (!in_array(net->net_cpts, net->net_ncpts, cpts[i])) {
173                         added_cpts[j] = cpts[i];
174                         j++;
175                 }
176         }
177
178         /* append the new cpts if any to the list of cpts in the net */
179         if (j > 0) {
180                 __u32 *array = NULL, *loc;
181                 __u32 total_entries = j + net->net_ncpts;
182
183                 CFS_ALLOC_PTR_ARRAY(array, total_entries);
184                 if (array == NULL) {
185                         rc = -ENOMEM;
186                         goto failed;
187                 }
188
189                 memcpy(array, net->net_cpts,
190                        net->net_ncpts * sizeof(*net->net_cpts));
191                 loc = array + net->net_ncpts;
192                 memcpy(loc, added_cpts, j * sizeof(*net->net_cpts));
193
194                 CFS_FREE_PTR_ARRAY(net->net_cpts, net->net_ncpts);
195                 net->net_ncpts = total_entries;
196                 net->net_cpts = array;
197         }
198
199 failed:
200         CFS_FREE_PTR_ARRAY(added_cpts, LNET_CPT_NUMBER);
201
202         return rc;
203 }
204
205 static void
206 lnet_net_remove_cpts(__u32 *cpts, __u32 ncpts, struct lnet_net *net)
207 {
208         struct lnet_ni *ni;
209         int rc;
210
211         /*
212          * Operation Assumption:
213          *      This function is called after an NI has been removed from
214          *      its parent net.
215          *
216          * if we're removing an NI which exists on all CPTs then
217          * we have to check if any of the other NIs on this net also
218          * exists on all CPTs. If none, then we need to build our Net CPT
219          * list based on the remaining NIs.
220          *
221          * If the NI being removed exist on a subset of the CPTs then we
222          * alo rebuild the Net CPT list based on the remaining NIs, which
223          * should resutl in the expected Net CPT list.
224          */
225
226         /*
227          * sometimes this function can be called due to some failure
228          * creating an NI, before any of the cpts are allocated, so check
229          * for that case and don't do anything
230          */
231         if (ncpts == 0)
232                 return;
233
234         if (ncpts == LNET_CPT_NUMBER) {
235                 /*
236                  * first iteration through the NI list in the net to see
237                  * if any of the NIs exist on all the CPTs. If one is
238                  * found then our job is done.
239                  */
240                 list_for_each_entry(ni, &net->net_ni_list, ni_netlist) {
241                         if (ni->ni_ncpts == LNET_CPT_NUMBER)
242                                 return;
243                 }
244         }
245
246         /*
247          * Rebuild the Net CPT list again, thereby only including only the
248          * CPTs which the remaining NIs are associated with.
249          */
250         if (net->net_cpts != NULL) {
251                 CFS_FREE_PTR_ARRAY(net->net_cpts, net->net_ncpts);
252                 net->net_cpts = NULL;
253         }
254
255         list_for_each_entry(ni, &net->net_ni_list, ni_netlist) {
256                 rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts,
257                                           net);
258                 if (rc != 0) {
259                         CERROR("Out of Memory\n");
260                         /*
261                          * do our best to keep on going. Delete
262                          * the net cpts and set it to NULL. This
263                          * way we can keep on going but less
264                          * efficiently, since memory accesses might be
265                          * accross CPT lines.
266                          */
267                         if (net->net_cpts != NULL) {
268                                 CFS_FREE_PTR_ARRAY(net->net_cpts,
269                                                    net->net_ncpts);
270                                 net->net_cpts = NULL;
271                                 net->net_ncpts = LNET_CPT_NUMBER;
272                         }
273                         return;
274                 }
275         }
276 }
277
278 void
279 lnet_ni_free(struct lnet_ni *ni)
280 {
281         lnet_net_remove_cpts(ni->ni_cpts, ni->ni_ncpts, ni->ni_net);
282
283         if (ni->ni_refs != NULL)
284                 cfs_percpt_free(ni->ni_refs);
285
286         if (ni->ni_tx_queues != NULL)
287                 cfs_percpt_free(ni->ni_tx_queues);
288
289         if (ni->ni_cpts != NULL)
290                 cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts);
291
292         if (ni->ni_interface != NULL) {
293                 LIBCFS_FREE(ni->ni_interface,
294                             strlen(ni->ni_interface) + 1);
295         }
296
297         /* release reference to net namespace */
298         if (ni->ni_net_ns != NULL)
299                 put_net(ni->ni_net_ns);
300
301         LIBCFS_FREE(ni, sizeof(*ni));
302 }
303
304 void
305 lnet_net_free(struct lnet_net *net)
306 {
307         struct list_head *tmp, *tmp2;
308         struct lnet_ni *ni;
309
310         LASSERT(list_empty(&net->net_ni_zombie));
311
312         /*
313          * delete any nis that haven't been added yet. This could happen
314          * if there is a failure on net startup
315          */
316         list_for_each_safe(tmp, tmp2, &net->net_ni_added) {
317                 ni = list_entry(tmp, struct lnet_ni, ni_netlist);
318                 list_del_init(&ni->ni_netlist);
319                 lnet_ni_free(ni);
320         }
321
322         /* delete any nis which have been started. */
323         list_for_each_safe(tmp, tmp2, &net->net_ni_list) {
324                 ni = list_entry(tmp, struct lnet_ni, ni_netlist);
325                 list_del_init(&ni->ni_netlist);
326                 lnet_ni_free(ni);
327         }
328
329         if (net->net_cpts != NULL)
330                 CFS_FREE_PTR_ARRAY(net->net_cpts, net->net_ncpts);
331
332         LIBCFS_FREE(net, sizeof(*net));
333 }
334
335 struct lnet_net *
336 lnet_net_alloc(__u32 net_id, struct list_head *net_list)
337 {
338         struct lnet_net         *net;
339
340         if (!lnet_net_unique(net_id, net_list, &net)) {
341                 CDEBUG(D_NET, "Returning duplicate net %p %s\n", net,
342                        libcfs_net2str(net->net_id));
343                 return net;
344         }
345
346         LIBCFS_ALLOC(net, sizeof(*net));
347         if (net == NULL) {
348                 CERROR("Out of memory creating network %s\n",
349                        libcfs_net2str(net_id));
350                 return NULL;
351         }
352
353         INIT_LIST_HEAD(&net->net_list);
354         INIT_LIST_HEAD(&net->net_ni_list);
355         INIT_LIST_HEAD(&net->net_ni_added);
356         INIT_LIST_HEAD(&net->net_ni_zombie);
357         INIT_LIST_HEAD(&net->net_rtr_pref_nids);
358         spin_lock_init(&net->net_lock);
359
360         net->net_id = net_id;
361         net->net_last_alive = ktime_get_seconds();
362
363         net->net_sel_priority = LNET_MAX_SELECTION_PRIORITY;
364
365         /* initialize global paramters to undefiend */
366         net->net_tunables.lct_peer_timeout = -1;
367         net->net_tunables.lct_max_tx_credits = -1;
368         net->net_tunables.lct_peer_tx_credits = -1;
369         net->net_tunables.lct_peer_rtr_credits = -1;
370
371         if (net_list)
372                 list_add_tail(&net->net_list, net_list);
373
374         return net;
375 }
376
377 int lnet_ni_add_interface(struct lnet_ni *ni, char *iface)
378 {
379         size_t iface_len = strlen(iface) + 1;
380
381         if (ni == NULL)
382                 return -ENOMEM;
383
384         if (ni->ni_interface != NULL) {
385                 LCONSOLE_ERROR_MSG(0x115, "%s: interface %s already set for net %s: rc = %d\n",
386                                    iface, ni->ni_interface,
387                                    libcfs_net2str(LNET_NID_NET(&ni->ni_nid)),
388                                    -EINVAL);
389                 return -EINVAL;
390         }
391
392         /* Allocate memory for the interface, so the code parsing input into
393          * tokens and adding interfaces can free the input safely.
394          * ni->ni_interface is freed in lnet_ni_free().
395          */
396         LIBCFS_ALLOC(ni->ni_interface, iface_len);
397
398         if (ni->ni_interface == NULL) {
399                 CERROR("%s: cannot allocate net interface name: rc = %d\n",
400                         iface, -ENOMEM);
401                 return -ENOMEM;
402         }
403
404         strscpy(ni->ni_interface, iface, iface_len);
405
406         return 0;
407 }
408 EXPORT_SYMBOL(lnet_ni_add_interface);
409
410 static struct lnet_ni *
411 lnet_ni_alloc_common(struct lnet_net *net, char *iface)
412 {
413         struct lnet_tx_queue    *tq;
414         struct lnet_ni          *ni;
415         int                     i;
416
417         if (iface != NULL)
418                 /* make sure that this NI is unique in the net it's
419                  * being added to */
420                 if (!lnet_ni_unique_net(&net->net_ni_added, iface))
421                         return NULL;
422
423         LIBCFS_ALLOC(ni, sizeof(*ni));
424         if (ni == NULL) {
425                 CERROR("Out of memory creating network interface %s%s\n",
426                        libcfs_net2str(net->net_id),
427                        (iface != NULL) ? iface : "");
428                 return NULL;
429         }
430
431         spin_lock_init(&ni->ni_lock);
432         INIT_LIST_HEAD(&ni->ni_netlist);
433         INIT_LIST_HEAD(&ni->ni_recovery);
434         LNetInvalidateMDHandle(&ni->ni_ping_mdh);
435         ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(),
436                                        sizeof(*ni->ni_refs[0]));
437         if (ni->ni_refs == NULL)
438                 goto failed;
439
440         ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(),
441                                             sizeof(*ni->ni_tx_queues[0]));
442         if (ni->ni_tx_queues == NULL)
443                 goto failed;
444
445         cfs_percpt_for_each(tq, i, ni->ni_tx_queues)
446                 INIT_LIST_HEAD(&tq->tq_delayed);
447
448         ni->ni_net = net;
449         /* LND will fill in the address part of the NID */
450         ni->ni_nid.nid_type = LNET_NETTYP(net->net_id);
451         ni->ni_nid.nid_num = cpu_to_be16(LNET_NETNUM(net->net_id));
452
453         /* Store net namespace in which current ni is being created */
454         if (current->nsproxy && current->nsproxy->net_ns)
455                 ni->ni_net_ns = get_net(current->nsproxy->net_ns);
456         else
457                 ni->ni_net_ns = get_net(&init_net);
458
459         ni->ni_state = LNET_NI_STATE_INIT;
460         ni->ni_sel_priority = LNET_MAX_SELECTION_PRIORITY;
461         list_add_tail(&ni->ni_netlist, &net->net_ni_added);
462
463         /*
464          * if an interface name is provided then make sure to add in that
465          * interface name in NI
466          */
467         if (iface)
468                 if (lnet_ni_add_interface(ni, iface) != 0)
469                         goto failed;
470
471         return ni;
472 failed:
473         lnet_ni_free(ni);
474         return NULL;
475 }
476
477 /* allocate and add to the provided network */
478 struct lnet_ni *
479 lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface)
480 {
481         struct lnet_ni          *ni;
482         int                     rc;
483
484         ni = lnet_ni_alloc_common(net, iface);
485         if (!ni)
486                 return NULL;
487
488         if (!el) {
489                 ni->ni_cpts  = NULL;
490                 ni->ni_ncpts = LNET_CPT_NUMBER;
491         } else {
492                 rc = cfs_expr_list_values(el, LNET_CPT_NUMBER, &ni->ni_cpts);
493                 if (rc <= 0) {
494                         CERROR("Failed to set CPTs for NI %s(%s): %d\n",
495                                libcfs_net2str(net->net_id),
496                                (iface != NULL) ? iface : "", rc);
497                         goto failed;
498                 }
499
500                 LASSERT(rc <= LNET_CPT_NUMBER);
501                 if (rc == LNET_CPT_NUMBER) {
502                         CFS_FREE_PTR_ARRAY(ni->ni_cpts, rc);
503                         ni->ni_cpts = NULL;
504                 }
505
506                 ni->ni_ncpts = rc;
507         }
508
509         rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net);
510         if (rc != 0)
511                 goto failed;
512
513         return ni;
514 failed:
515         lnet_ni_free(ni);
516         return NULL;
517 }
518
519 struct lnet_ni *
520 lnet_ni_alloc_w_cpt_array(struct lnet_net *net, __u32 *cpts, __u32 ncpts,
521                           char *iface)
522 {
523         struct lnet_ni          *ni;
524         int                     rc;
525
526         ni = lnet_ni_alloc_common(net, iface);
527         if (!ni)
528                 return NULL;
529
530         if (ncpts == 0) {
531                 ni->ni_cpts  = NULL;
532                 ni->ni_ncpts = LNET_CPT_NUMBER;
533         } else {
534                 size_t array_size = ncpts * sizeof(ni->ni_cpts[0]);
535
536                 CFS_ALLOC_PTR_ARRAY(ni->ni_cpts, ncpts);
537                 if (ni->ni_cpts == NULL)
538                         goto failed;
539                 memcpy(ni->ni_cpts, cpts, array_size);
540                 ni->ni_ncpts = ncpts;
541         }
542
543         rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net);
544         if (rc != 0)
545                 goto failed;
546
547         return ni;
548 failed:
549         lnet_ni_free(ni);
550         return NULL;
551 }
552
553 /*
554  * Parse the networks string and create the matching set of NIs on the
555  * nilist.
556  */
557 int
558 lnet_parse_networks(struct list_head *netlist, const char *networks)
559 {
560         struct cfs_expr_list *net_el = NULL;
561         struct cfs_expr_list *ni_el = NULL;
562         int             tokensize;
563         char            *tokens;
564         char            *str;
565         struct lnet_net *net;
566         struct lnet_ni  *ni = NULL;
567         __u32           net_id;
568         int             nnets = 0;
569
570         if (networks == NULL) {
571                 CERROR("networks string is undefined\n");
572                 return -EINVAL;
573         }
574
575         if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) {
576                 /* _WAY_ conservative */
577                 LCONSOLE_ERROR_MSG(0x112, "Can't parse networks: string too "
578                                    "long\n");
579                 return -EINVAL;
580         }
581
582         tokensize = strlen(networks) + 1;
583
584         LIBCFS_ALLOC(tokens, tokensize);
585         if (tokens == NULL) {
586                 CERROR("Can't allocate net tokens\n");
587                 return -ENOMEM;
588         }
589
590         memcpy(tokens, networks, tokensize);
591         str = tokens;
592
593         /*
594          * Main parser loop.
595          *
596          * NB we don't check interface conflicts here; it's the LNDs
597          * responsibility (if it cares at all)
598          */
599         do {
600                 char *nistr;
601                 char *elstr;
602                 char *name;
603                 int rc;
604
605                 /*
606                  * Parse a network string into its components.
607                  *
608                  * <name>{"("...")"}{"["<el>"]"}
609                  */
610
611                 /* Network name (mandatory) */
612                 while (isspace(*str))
613                         *str++ = '\0';
614                 if (!*str)
615                         break;
616                 name = str;
617                 str += strcspn(str, SPACESTR ":()[],");
618                 while (isspace(*str))
619                         *str++ = '\0';
620
621                 /* Interface list (optional) */
622                 if (*str == '(') {
623                         *str++ = '\0';
624                         nistr = str;
625                         str += strcspn(str, ")");
626                         if (*str != ')') {
627                                 str = nistr;
628                                 goto failed_syntax;
629                         }
630                         do {
631                                 *str++ = '\0';
632                         } while (isspace(*str));
633                 } else {
634                         nistr = NULL;
635                 }
636
637                 /* CPT expression (optional) */
638                 if (*str == '[') {
639                         elstr = str;
640                         str += strcspn(str, "]");
641                         if (*str != ']') {
642                                 str = elstr;
643                                 goto failed_syntax;
644                         }
645                         rc = cfs_expr_list_parse(elstr, str - elstr + 1,
646                                                 0, LNET_CPT_NUMBER - 1,
647                                                 &net_el);
648                         if (rc != 0) {
649                                 str = elstr;
650                                 goto failed_syntax;
651                         }
652                         *elstr = '\0';
653                         do {
654                                 *str++ = '\0';
655                         } while (isspace(*str));
656                 }
657
658                 /* Bad delimiters */
659                 if (*str && (strchr(DELIMITERS, *str) != NULL))
660                         goto failed_syntax;
661
662                 /* go to the next net if it exits */
663                 str += strcspn(str, ",");
664                 if (*str == ',')
665                         *str++ = '\0';
666
667                 /*
668                  * At this point the name is properly terminated.
669                  */
670                 net_id = libcfs_str2net(name);
671                 if (net_id == LNET_NET_ANY) {
672                         LCONSOLE_ERROR_MSG(0x113,
673                                         "Unrecognised network type\n");
674                         str = name;
675                         goto failed_syntax;
676                 }
677
678                 if (LNET_NETTYP(net_id) == LOLND) {
679                         /* Loopback is implicit, and there can be only one. */
680                         if (net_el) {
681                                 cfs_expr_list_free(net_el);
682                                 net_el = NULL;
683                         }
684                         /* Should we error out instead? */
685                         continue;
686                 }
687
688                 /*
689                  * All network paramaters are now known.
690                  */
691                 nnets++;
692
693                 /* always allocate a net, since we will eventually add an
694                  * interface to it, or we will fail, in which case we'll
695                  * just delete it */
696                 net = lnet_net_alloc(net_id, netlist);
697                 if (IS_ERR_OR_NULL(net))
698                         goto failed;
699
700                 if (!nistr) {
701                         /*
702                          * No interface list was specified, allocate a
703                          * ni using the defaults.
704                          */
705                         ni = lnet_ni_alloc(net, net_el, NULL);
706                         if (IS_ERR_OR_NULL(ni))
707                                 goto failed;
708
709                         if (!nistr) {
710                                 if (net_el) {
711                                         cfs_expr_list_free(net_el);
712                                         net_el = NULL;
713                                 }
714                                 continue;
715                         }
716                 }
717
718                 do {
719                         elstr = NULL;
720
721                         /* Interface name (mandatory) */
722                         while (isspace(*nistr))
723                                 *nistr++ = '\0';
724                         name = nistr;
725                         nistr += strcspn(nistr, SPACESTR "[],");
726                         while (isspace(*nistr))
727                                 *nistr++ = '\0';
728
729                         /* CPT expression (optional) */
730                         if (*nistr == '[') {
731                                 elstr = nistr;
732                                 nistr += strcspn(nistr, "]");
733                                 if (*nistr != ']') {
734                                         str = elstr;
735                                         goto failed_syntax;
736                                 }
737                                 rc = cfs_expr_list_parse(elstr,
738                                                         nistr - elstr + 1,
739                                                         0, LNET_CPT_NUMBER - 1,
740                                                         &ni_el);
741                                 if (rc != 0) {
742                                         str = elstr;
743                                         goto failed_syntax;
744                                 }
745                                 *elstr = '\0';
746                                 do {
747                                         *nistr++ = '\0';
748                                 } while (isspace(*nistr));
749                         } else {
750                                 ni_el = net_el;
751                         }
752
753                         /*
754                          * End of single interface specificaton,
755                          * advance to the start of the next one, if
756                          * any.
757                          */
758                         if (*nistr == ',') {
759                                 do {
760                                         *nistr++ = '\0';
761                                 } while (isspace(*nistr));
762                                 if (!*nistr) {
763                                         str = nistr;
764                                         goto failed_syntax;
765                                 }
766                         } else if (*nistr) {
767                                 str = nistr;
768                                 goto failed_syntax;
769                         }
770
771                         /*
772                          * At this point the name is properly terminated.
773                          */
774                         if (!*name) {
775                                 str = name;
776                                 goto failed_syntax;
777                         }
778
779                         ni = lnet_ni_alloc(net, ni_el, name);
780                         if (IS_ERR_OR_NULL(ni))
781                                 goto failed;
782
783                         if (ni_el) {
784                                 if (ni_el != net_el) {
785                                         cfs_expr_list_free(ni_el);
786                                         ni_el = NULL;
787                                 }
788                         }
789                 } while (*nistr);
790
791                 if (net_el) {
792                         cfs_expr_list_free(net_el);
793                         net_el = NULL;
794                 }
795         } while (*str);
796
797         LIBCFS_FREE(tokens, tokensize);
798         return nnets;
799
800  failed_syntax:
801         lnet_syntax("networks", networks, (int)(str - tokens), strlen(str));
802  failed:
803         /* free the net list and all the nis on each net */
804         while ((net = list_first_entry_or_null(netlist,
805                                                struct lnet_net,
806                                                net_list)) != NULL) {
807                 list_del_init(&net->net_list);
808                 lnet_net_free(net);
809         }
810
811         if (ni_el && ni_el != net_el)
812                 cfs_expr_list_free(ni_el);
813         if (net_el)
814                 cfs_expr_list_free(net_el);
815
816         LIBCFS_FREE(tokens, tokensize);
817
818         return -EINVAL;
819 }
820
821 static struct lnet_text_buf *lnet_new_text_buf(int str_len)
822 {
823         struct lnet_text_buf *ltb;
824         int nob;
825
826         /* NB allocate space for the terminating 0 */
827         nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]);
828         if (nob > LNET_SINGLE_TEXTBUF_NOB) {
829                 /* _way_ conservative for "route net gateway..." */
830                 CERROR("text buffer too big\n");
831                 return NULL;
832         }
833
834         if (lnet_tbnob + nob > LNET_MAX_TEXTBUF_NOB) {
835                 CERROR("Too many text buffers\n");
836                 return NULL;
837         }
838
839         LIBCFS_ALLOC(ltb, nob);
840         if (ltb == NULL)
841                 return NULL;
842
843         ltb->ltb_size = nob;
844         ltb->ltb_text[0] = 0;
845         lnet_tbnob += nob;
846         return ltb;
847 }
848
849 static void
850 lnet_free_text_buf(struct lnet_text_buf *ltb)
851 {
852         lnet_tbnob -= ltb->ltb_size;
853         LIBCFS_FREE(ltb, ltb->ltb_size);
854 }
855
856 static void
857 lnet_free_text_bufs(struct list_head *tbs)
858 {
859         struct lnet_text_buf  *ltb;
860
861         while ((ltb = list_first_entry_or_null(tbs, struct lnet_text_buf,
862                                                ltb_list)) != NULL) {
863                 list_del(&ltb->ltb_list);
864                 lnet_free_text_buf(ltb);
865         }
866 }
867
868 static int
869 lnet_str2tbs_sep(struct list_head *tbs, const char *str)
870 {
871         LIST_HEAD(pending);
872         const char *sep;
873         int nob;
874         int i;
875         struct lnet_text_buf *ltb;
876
877         /* Split 'str' into separate commands */
878         for (;;) {
879                 /* skip leading whitespace */
880                 while (isspace(*str))
881                         str++;
882
883                 /* scan for separator or comment */
884                 for (sep = str; *sep != 0; sep++)
885                         if (lnet_issep(*sep) || *sep == '#')
886                                 break;
887
888                 nob = (int)(sep - str);
889                 if (nob > 0) {
890                         ltb = lnet_new_text_buf(nob);
891                         if (ltb == NULL) {
892                                 lnet_free_text_bufs(&pending);
893                                 return -ENOMEM;
894                         }
895
896                         for (i = 0; i < nob; i++)
897                                 if (isspace(str[i]))
898                                         ltb->ltb_text[i] = ' ';
899                                 else
900                                         ltb->ltb_text[i] = str[i];
901
902                         ltb->ltb_text[nob] = 0;
903
904                         list_add_tail(&ltb->ltb_list, &pending);
905                 }
906
907                 if (*sep == '#') {
908                         /* scan for separator */
909                         do {
910                                 sep++;
911                         } while (*sep != 0 && !lnet_issep(*sep));
912                 }
913
914                 if (*sep == 0)
915                         break;
916
917                 str = sep + 1;
918         }
919
920         list_splice(&pending, tbs->prev);
921         return 0;
922 }
923
924 static int
925 lnet_expand1tb(struct list_head *list,
926                char *str, char *sep1, char *sep2,
927                char *item, int itemlen)
928 {
929         int              len1 = (int)(sep1 - str);
930         int              len2 = strlen(sep2 + 1);
931         struct lnet_text_buf *ltb;
932
933         LASSERT (*sep1 == '[');
934         LASSERT (*sep2 == ']');
935
936         ltb = lnet_new_text_buf(len1 + itemlen + len2);
937         if (ltb == NULL)
938                 return -ENOMEM;
939
940         memcpy(ltb->ltb_text, str, len1);
941         memcpy(&ltb->ltb_text[len1], item, itemlen);
942         memcpy(&ltb->ltb_text[len1+itemlen], sep2 + 1, len2);
943         ltb->ltb_text[len1 + itemlen + len2] = 0;
944
945         list_add_tail(&ltb->ltb_list, list);
946         return 0;
947 }
948
949 static int
950 lnet_str2tbs_expand(struct list_head *tbs, char *str)
951 {
952         char              num[16];
953         LIST_HEAD(pending);
954         char             *sep;
955         char             *sep2;
956         char             *parsed;
957         char             *enditem;
958         int               lo;
959         int               hi;
960         int               stride;
961         int               i;
962         int               nob;
963         int               scanned;
964
965         sep = strchr(str, '[');
966         if (sep == NULL)                        /* nothing to expand */
967                 return 0;
968
969         sep2 = strchr(sep, ']');
970         if (sep2 == NULL)
971                 goto failed;
972
973         for (parsed = sep; parsed < sep2; parsed = enditem) {
974
975                 enditem = ++parsed;
976                 while (enditem < sep2 && *enditem != ',')
977                         enditem++;
978
979                 if (enditem == parsed)          /* no empty items */
980                         goto failed;
981
982                 if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, &stride, &scanned) < 3) {
983
984                         if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) {
985
986                                 /* simple string enumeration */
987                                 if (lnet_expand1tb(&pending, str, sep, sep2,
988                                                    parsed, (int)(enditem - parsed)) != 0)
989                                         goto failed;
990
991                                 continue;
992                         }
993
994                         stride = 1;
995                 }
996
997                 /* range expansion */
998
999                 if (enditem != parsed + scanned) /* no trailing junk */
1000                         goto failed;
1001
1002                 if (hi < 0 || lo < 0 || stride < 0 || hi < lo ||
1003                     (hi - lo) % stride != 0)
1004                         goto failed;
1005
1006                 for (i = lo; i <= hi; i += stride) {
1007
1008                         snprintf(num, sizeof(num), "%d", i);
1009                         nob = strlen(num);
1010                         if (nob + 1 == sizeof(num))
1011                                 goto failed;
1012
1013                         if (lnet_expand1tb(&pending, str, sep, sep2,
1014                                            num, nob) != 0)
1015                                 goto failed;
1016                 }
1017         }
1018
1019         list_splice(&pending, tbs->prev);
1020         return 1;
1021
1022  failed:
1023         lnet_free_text_bufs(&pending);
1024         return -EINVAL;
1025 }
1026
1027 static int
1028 lnet_parse_hops (char *str, unsigned int *hops)
1029 {
1030         int     len = strlen(str);
1031         int     nob = len;
1032
1033         return (sscanf(str, "%u%n", hops, &nob) >= 1 &&
1034                 nob == len &&
1035                 *hops > 0 && *hops < 256);
1036 }
1037
1038 #define LNET_PRIORITY_SEPARATOR (':')
1039
1040 static int
1041 lnet_parse_priority(char *str, unsigned int *priority, char **token)
1042 {
1043         int   nob;
1044         char *sep;
1045         int   len;
1046
1047         sep = strchr(str, LNET_PRIORITY_SEPARATOR);
1048         if (sep == NULL) {
1049                 *priority = 0;
1050                 return 0;
1051         }
1052         len = strlen(sep + 1);
1053
1054         if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) {
1055                 /* Update the caller's token pointer so it treats the found
1056                    priority as the token to report in the error message. */
1057                 *token += sep - str + 1;
1058                 return -EINVAL;
1059         }
1060
1061         CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob);
1062
1063         /*
1064          * Change priority separator to \0 to be able to parse NID
1065          */
1066         *sep = '\0';
1067         return 0;
1068 }
1069
1070 static int
1071 lnet_parse_route(char *str, int *im_a_router)
1072 {
1073         /* static scratch buffer OK (single threaded) */
1074         static char cmd[LNET_SINGLE_TEXTBUF_NOB];
1075
1076         LIST_HEAD(nets);
1077         LIST_HEAD(gateways);
1078         struct list_head *tmp1;
1079         struct list_head *tmp2;
1080         __u32 net;
1081         struct lnet_nid nid;
1082         struct lnet_text_buf *ltb = NULL;
1083         struct lnet_text_buf *ltb1, *ltb2;
1084         int rc;
1085         char *sep;
1086         char *token = str;
1087         int ntokens = 0;
1088         int myrc = -1;
1089         __u32 hops;
1090         int got_hops = 0;
1091         unsigned int priority = 0;
1092
1093         /* save a copy of the string for error messages */
1094         strncpy(cmd, str, sizeof(cmd));
1095         cmd[sizeof(cmd) - 1] = '\0';
1096
1097         sep = str;
1098         for (;;) {
1099                 /* scan for token start */
1100                 while (isspace(*sep))
1101                         sep++;
1102                 if (*sep == 0) {
1103                         if (ntokens < (got_hops ? 3 : 2))
1104                                 goto token_error;
1105                         break;
1106                 }
1107
1108                 ntokens++;
1109                 token = sep++;
1110
1111                 /* scan for token end */
1112                 while (*sep != 0 && !isspace(*sep))
1113                         sep++;
1114                 if (*sep != 0)
1115                         *sep++ = 0;
1116
1117                 if (ntokens == 1) {
1118                         tmp2 = &nets;           /* expanding nets */
1119                 } else if (ntokens == 2 &&
1120                            lnet_parse_hops(token, &hops)) {
1121                         got_hops = 1;           /* got a hop count */
1122                         continue;
1123                 } else {
1124                         tmp2 = &gateways;       /* expanding gateways */
1125                 }
1126
1127                 ltb = lnet_new_text_buf(strlen(token));
1128                 if (ltb == NULL)
1129                         goto out;
1130
1131                 strcpy(ltb->ltb_text, token);
1132                 tmp1 = &ltb->ltb_list;
1133                 list_add_tail(tmp1, tmp2);
1134
1135                 while (tmp1 != tmp2) {
1136                         ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list);
1137
1138                         rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text);
1139                         if (rc < 0)
1140                                 goto token_error;
1141
1142                         tmp1 = tmp1->next;
1143
1144                         if (rc > 0) {           /* expanded! */
1145                                 list_del(&ltb->ltb_list);
1146                                 lnet_free_text_buf(ltb);
1147                                 continue;
1148                         }
1149
1150                         if (ntokens == 1) {
1151                                 net = libcfs_str2net(ltb->ltb_text);
1152                                 if (net == LNET_NET_ANY ||
1153                                     LNET_NETTYP(net) == LOLND)
1154                                         goto token_error;
1155                         } else {
1156                                 rc = lnet_parse_priority(ltb->ltb_text,
1157                                                          &priority, &token);
1158                                 if (rc < 0)
1159                                         goto token_error;
1160
1161                                 if (libcfs_strnid(&nid, ltb->ltb_text) != 0 ||
1162                                     nid_is_lo0(&nid))
1163                                         goto token_error;
1164                         }
1165                 }
1166         }
1167
1168         /* if there are no hops set then we want to flag this value as
1169          * unset since hops is an optional parameter */
1170         if (!got_hops)
1171                 hops = LNET_UNDEFINED_HOPS;
1172
1173         LASSERT(!list_empty(&nets));
1174         LASSERT(!list_empty(&gateways));
1175
1176         list_for_each_entry(ltb1, &nets, ltb_list) {
1177                 net = libcfs_str2net(ltb1->ltb_text);
1178                 LASSERT(net != LNET_NET_ANY);
1179
1180                 list_for_each_entry(ltb2, &gateways, ltb_list) {
1181                         LASSERT(libcfs_strnid(&nid, ltb2->ltb_text) == 0);
1182
1183                         if (lnet_islocalnid(&nid)) {
1184                                 *im_a_router = 1;
1185                                 continue;
1186                         }
1187
1188                         rc = lnet_add_route(net, hops, &nid, priority, 1);
1189                         if (rc != 0 && rc != -EEXIST && rc != -EHOSTUNREACH) {
1190                                 CERROR("Can't create route "
1191                                        "to %s via %s\n",
1192                                        libcfs_net2str(net),
1193                                        libcfs_nidstr(&nid));
1194                                 goto out;
1195                         }
1196                 }
1197         }
1198
1199         myrc = 0;
1200         goto out;
1201
1202 token_error:
1203         lnet_syntax("routes", cmd, (int)(token - str), strlen(token));
1204 out:
1205         lnet_free_text_bufs(&nets);
1206         lnet_free_text_bufs(&gateways);
1207         return myrc;
1208 }
1209
1210 static int
1211 lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router)
1212 {
1213         struct lnet_text_buf *ltb;
1214
1215         while ((ltb = list_first_entry_or_null(tbs, struct lnet_text_buf,
1216                                                ltb_list)) != NULL) {
1217                 if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) {
1218                         lnet_free_text_bufs(tbs);
1219                         return -EINVAL;
1220                 }
1221
1222                 list_del(&ltb->ltb_list);
1223                 lnet_free_text_buf(ltb);
1224         }
1225
1226         return 0;
1227 }
1228
1229 int
1230 lnet_parse_routes(const char *routes, int *im_a_router)
1231 {
1232         LIST_HEAD(tbs);
1233         int rc = 0;
1234
1235         *im_a_router = 0;
1236
1237         if (lnet_str2tbs_sep(&tbs, routes) < 0) {
1238                 CERROR("Error parsing routes\n");
1239                 rc = -EINVAL;
1240         } else {
1241                 rc = lnet_parse_route_tbs(&tbs, im_a_router);
1242         }
1243
1244         LASSERT (lnet_tbnob == 0);
1245         return rc;
1246 }
1247
1248 static int
1249 lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip)
1250 {
1251         LIST_HEAD(list);
1252         int             rc;
1253         int             i;
1254
1255         rc = cfs_ip_addr_parse(token, len, &list);
1256         if (rc != 0)
1257                 return rc;
1258
1259         for (rc = i = 0; !rc && i < nip; i++)
1260                 rc = cfs_ip_addr_match(ipaddrs[i], &list);
1261
1262         cfs_expr_list_free_list(&list);
1263
1264         return rc;
1265 }
1266
1267 static int
1268 lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip)
1269 {
1270         static char tokens[LNET_SINGLE_TEXTBUF_NOB];
1271
1272         int   matched = 0;
1273         int   ntokens = 0;
1274         int   len;
1275         char *net = NULL;
1276         char *sep;
1277         char *token;
1278         int   rc;
1279
1280         LASSERT(strlen(net_entry) < sizeof(tokens));
1281
1282         /* work on a copy of the string */
1283         strcpy(tokens, net_entry);
1284         sep = tokens;
1285         for (;;) {
1286                 /* scan for token start */
1287                 while (isspace(*sep))
1288                         sep++;
1289                 if (*sep == 0)
1290                         break;
1291
1292                 token = sep++;
1293
1294                 /* scan for token end */
1295                 while (*sep != 0 && !isspace(*sep))
1296                         sep++;
1297                 if (*sep != 0)
1298                         *sep++ = 0;
1299
1300                 if (ntokens++ == 0) {
1301                         net = token;
1302                         continue;
1303                 }
1304
1305                 len = strlen(token);
1306
1307                 rc = lnet_match_network_token(token, len, ipaddrs, nip);
1308                 if (rc < 0) {
1309                         lnet_syntax("ip2nets", net_entry,
1310                                     (int)(token - tokens), len);
1311                         return rc;
1312                 }
1313
1314                 matched |= (rc != 0);
1315         }
1316
1317         if (!matched)
1318                 return 0;
1319
1320         strcpy(net_entry, net);                 /* replace with matched net */
1321         return 1;
1322 }
1323
1324 static __u32
1325 lnet_netspec2net(char *netspec)
1326 {
1327         char   *bracket = strchr(netspec, '(');
1328         __u32   net;
1329
1330         if (bracket != NULL)
1331                 *bracket = 0;
1332
1333         net = libcfs_str2net(netspec);
1334
1335         if (bracket != NULL)
1336                 *bracket = '(';
1337
1338         return net;
1339 }
1340
1341 static int
1342 lnet_splitnets(char *source, struct list_head *nets)
1343 {
1344         int               offset = 0;
1345         int               offset2;
1346         int               len;
1347         struct lnet_text_buf  *tb;
1348         struct lnet_text_buf  *tb2;
1349         char             *sep;
1350         char             *bracket;
1351         __u32             net;
1352
1353         LASSERT(!list_empty(nets));
1354         LASSERT(nets->next == nets->prev);      /* single entry */
1355
1356         tb = list_first_entry(nets, struct lnet_text_buf, ltb_list);
1357
1358         for (;;) {
1359                 sep = strchr(tb->ltb_text, ',');
1360                 bracket = strchr(tb->ltb_text, '(');
1361
1362                 if (sep != NULL &&
1363                     bracket != NULL &&
1364                     bracket < sep) {
1365                         /* netspec lists interfaces... */
1366
1367                         offset2 = offset + (int)(bracket - tb->ltb_text);
1368                         len = strlen(bracket);
1369
1370                         bracket = strchr(bracket + 1, ')');
1371
1372                         if (bracket == NULL ||
1373                             !(bracket[1] == ',' || bracket[1] == 0)) {
1374                                 lnet_syntax("ip2nets", source, offset2, len);
1375                                 return -EINVAL;
1376                         }
1377
1378                         sep = (bracket[1] == 0) ? NULL : bracket + 1;
1379                 }
1380
1381                 if (sep != NULL)
1382                         *sep++ = 0;
1383
1384                 net = lnet_netspec2net(tb->ltb_text);
1385                 if (net == LNET_NET_ANY) {
1386                         lnet_syntax("ip2nets", source, offset,
1387                                     strlen(tb->ltb_text));
1388                         return -EINVAL;
1389                 }
1390
1391                 list_for_each_entry(tb2, nets, ltb_list) {
1392                         if (tb2 == tb)
1393                                 continue;
1394
1395                         if (net == lnet_netspec2net(tb2->ltb_text)) {
1396                                 /* duplicate network */
1397                                 lnet_syntax("ip2nets", source, offset,
1398                                             strlen(tb->ltb_text));
1399                                 return -EINVAL;
1400                         }
1401                 }
1402
1403                 if (sep == NULL)
1404                         return 0;
1405
1406                 offset += (int)(sep - tb->ltb_text);
1407                 len = strlen(sep);
1408                 tb2 = lnet_new_text_buf(len);
1409                 if (tb2 == NULL)
1410                         return -ENOMEM;
1411
1412                 strncpy(tb2->ltb_text, sep, len);
1413                 tb2->ltb_text[len] = '\0';
1414                 list_add_tail(&tb2->ltb_list, nets);
1415
1416                 tb = tb2;
1417         }
1418 }
1419
1420 static int
1421 lnet_match_networks(const char **networksp, const char *ip2nets,
1422                     __u32 *ipaddrs, int nip)
1423 {
1424         static char       networks[LNET_SINGLE_TEXTBUF_NOB];
1425         static char       source[LNET_SINGLE_TEXTBUF_NOB];
1426
1427         LIST_HEAD(raw_entries);
1428         LIST_HEAD(matched_nets);
1429         LIST_HEAD(current_nets);
1430         struct list_head *t;
1431         struct list_head *t2;
1432         struct lnet_text_buf  *tb;
1433         int               len;
1434         int               count;
1435         int               rc;
1436
1437         if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) {
1438                 CERROR("Error parsing ip2nets\n");
1439                 LASSERT(lnet_tbnob == 0);
1440                 return -EINVAL;
1441         }
1442
1443         networks[0] = 0;
1444         count = 0;
1445         len = 0;
1446         rc = 0;
1447
1448         while ((tb = list_first_entry_or_null(&raw_entries,
1449                                               struct lnet_text_buf,
1450                                               ltb_list)) != NULL) {
1451                 strncpy(source, tb->ltb_text, sizeof(source));
1452                 source[sizeof(source) - 1] = '\0';
1453
1454                 /* replace ltb_text with the network(s) add on match */
1455                 rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip);
1456                 if (rc < 0)
1457                         break;
1458
1459                 list_del(&tb->ltb_list);
1460
1461                 if (rc == 0) {                  /* no match */
1462                         lnet_free_text_buf(tb);
1463                         continue;
1464                 }
1465
1466                 /* split into separate networks */
1467                 INIT_LIST_HEAD(&current_nets);
1468                 list_add(&tb->ltb_list, &current_nets);
1469                 rc = lnet_splitnets(source, &current_nets);
1470                 if (rc < 0)
1471                         break;
1472
1473                 list_for_each_safe(t, t2, &current_nets) {
1474                         tb = list_entry(t, struct lnet_text_buf, ltb_list);
1475
1476                         list_move_tail(&tb->ltb_list, &matched_nets);
1477
1478                         len += scnprintf(networks + len, sizeof(networks) - len,
1479                                          "%s%s", (len == 0) ? "" : ",",
1480                                          tb->ltb_text);
1481
1482                         if (len >= sizeof(networks)) {
1483                                 CERROR("Too many matched networks\n");
1484                                 rc = -E2BIG;
1485                                 goto out;
1486                         }
1487                 }
1488
1489                 count++;
1490         }
1491
1492  out:
1493         lnet_free_text_bufs(&raw_entries);
1494         lnet_free_text_bufs(&matched_nets);
1495         lnet_free_text_bufs(&current_nets);
1496         LASSERT(lnet_tbnob == 0);
1497
1498         if (rc < 0)
1499                 return rc;
1500
1501         *networksp = networks;
1502         return count;
1503 }
1504
1505 int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns, bool v6)
1506 {
1507         struct lnet_inetdev *ifaces = NULL;
1508         struct net_device *dev;
1509         int nalloc = 0;
1510         int nip = 0;
1511         DECLARE_CONST_IN_IFADDR(ifa);
1512
1513         rtnl_lock();
1514         for_each_netdev(ns, dev) {
1515                 int flags = dev_get_flags(dev);
1516                 struct in_device *in_dev;
1517 #if IS_ENABLED(CONFIG_IPV6)
1518                 struct inet6_dev *in6_dev;
1519                 const struct inet6_ifaddr *ifa6;
1520 #endif
1521                 int node_id;
1522                 int cpt;
1523
1524                 if (flags & IFF_LOOPBACK) /* skip the loopback IF */
1525                         continue;
1526
1527                 if (!(flags & IFF_UP)) {
1528                         CWARN("lnet: Ignoring interface %s: it's down\n",
1529                               dev->name);
1530                         continue;
1531                 }
1532
1533                 node_id = dev_to_node(&dev->dev);
1534                 cpt = cfs_cpt_of_node(lnet_cpt_table(), node_id);
1535
1536                 in_dev = __in_dev_get_rtnl(dev);
1537                 if (!in_dev) {
1538                         if (!v6)
1539                                 CWARN("lnet: Interface %s has no IPv4 status.\n",
1540                                       dev->name);
1541                         goto try_v6;
1542                 }
1543
1544                 in_dev_for_each_ifa_rtnl(ifa, in_dev) {
1545                         if (nip >= nalloc) {
1546                                 struct lnet_inetdev *tmp;
1547
1548                                 nalloc += LNET_INTERFACES_NUM;
1549                                 tmp = krealloc(ifaces, nalloc * sizeof(*tmp),
1550                                                GFP_KERNEL);
1551                                 if (!tmp) {
1552                                         kfree(ifaces);
1553                                         ifaces = NULL;
1554                                         nip = -ENOMEM;
1555                                         goto unlock_rtnl;
1556                                 }
1557                                 ifaces = tmp;
1558                         }
1559
1560                         ifaces[nip].li_cpt = cpt;
1561                         ifaces[nip].li_iff_master = !!(flags & IFF_MASTER);
1562                         ifaces[nip].li_size = sizeof(ifa->ifa_local);
1563                         ifaces[nip].li_index = dev->ifindex;
1564                         ifaces[nip].li_ipaddr = ifa->ifa_local;
1565                         ifaces[nip].li_netmask = ntohl(ifa->ifa_mask);
1566                         strlcpy(ifaces[nip].li_name, ifa->ifa_label,
1567                                 sizeof(ifaces[nip].li_name));
1568                         nip++;
1569                 }
1570                 endfor_ifa(in_dev);
1571
1572         try_v6:
1573                 if (!v6)
1574                         continue;
1575 #if IS_ENABLED(CONFIG_IPV6)
1576                 in6_dev = __in6_dev_get(dev);
1577                 if (!in6_dev) {
1578                         if (!in_dev)
1579                                 CWARN("lnet: Interface %s has no IP status.\n",
1580                                       dev->name);
1581                         continue;
1582                 }
1583
1584                 list_for_each_entry_rcu(ifa6, &in6_dev->addr_list, if_list) {
1585                         if (ifa6->flags & IFA_F_TEMPORARY)
1586                                 continue;
1587                         if (nip >= nalloc) {
1588                                 struct lnet_inetdev *tmp;
1589
1590                                 nalloc += LNET_INTERFACES_NUM;
1591                                 tmp = krealloc(ifaces, nalloc * sizeof(*tmp),
1592                                                GFP_KERNEL);
1593                                 if (!tmp) {
1594                                         kfree(ifaces);
1595                                         ifaces = NULL;
1596                                         nip = -ENOMEM;
1597                                         goto unlock_rtnl;
1598                                 }
1599                                 ifaces = tmp;
1600                         }
1601
1602                         ifaces[nip].li_cpt = cpt;
1603                         ifaces[nip].li_iff_master = !!(flags & IFF_MASTER);
1604                         ifaces[nip].li_size = sizeof(struct in6_addr);
1605                         ifaces[nip].li_index = dev->ifindex;
1606                         memcpy(ifaces[nip].li_ipv6addr,
1607                                &ifa6->addr, sizeof(struct in6_addr));
1608                         strlcpy(ifaces[nip].li_name, dev->name,
1609                                 sizeof(ifaces[nip].li_name));
1610                         nip++;
1611                         /* As different IPv6 addresses don't have unique
1612                          * labels, it is safest just to use the first
1613                          * and ignore the rest.
1614                          */
1615                         break;
1616                 }
1617 #endif /* IS_ENABLED(CONFIG_IPV6) */
1618
1619         }
1620 unlock_rtnl:
1621         rtnl_unlock();
1622
1623         if (nip == 0) {
1624                 CERROR("lnet: Can't find any usable interfaces, rc = -ENOENT\n");
1625                 nip = -ENOENT;
1626         }
1627
1628         *dev_list = ifaces;
1629         return nip;
1630 }
1631 EXPORT_SYMBOL(lnet_inet_enumerate);
1632
1633 int lnet_inet_select(struct lnet_ni *ni,
1634                      struct lnet_inetdev *ifaces,
1635                      int num_ifaces)
1636 {
1637         bool addr_set = nid_addr_is_set(&ni->ni_nid);
1638         int if_idx;
1639
1640         /* default to first interface if both interface and NID unspecified */
1641         if (!ni->ni_interface && !addr_set)
1642                 return 0;
1643
1644         for (if_idx = 0; if_idx < num_ifaces; if_idx++) {
1645                 if (ni->ni_interface &&
1646                         strcmp(ni->ni_interface, ifaces[if_idx].li_name) != 0)
1647                         /* not the specified interface */
1648                         continue;
1649
1650                 if (!addr_set)
1651                         /* IP unspecified, use IP of first matching interface */
1652                         break;
1653
1654                 if (ifaces[if_idx].li_size == NID_ADDR_BYTES(&ni->ni_nid)) {
1655                         char *addr = (char *)&ifaces[if_idx].li_ipaddr;
1656
1657                         if (ifaces[if_idx].li_size != 4)
1658                                 addr = (char *)ifaces[if_idx].li_ipv6addr;
1659
1660                         if (memcmp(ni->ni_nid.nid_addr, addr,
1661                                    ifaces[if_idx].li_size) == 0)
1662                                 break;
1663                 }
1664         }
1665
1666         if (if_idx < num_ifaces)
1667                 return if_idx;
1668
1669         if (ni->ni_interface)
1670                 CERROR("%s: failed to find interface %s%s%s\n",
1671                        libcfs_lnd2modname(ni->ni_nid.nid_type),
1672                        ni->ni_interface, addr_set ? "@" : "",
1673                        addr_set ? libcfs_nidstr(&ni->ni_nid) : "");
1674         else
1675                 CERROR("%s: failed to find IP address %s\n",
1676                        libcfs_lnd2modname(ni->ni_nid.nid_type),
1677                        libcfs_nidstr(&ni->ni_nid));
1678
1679         return -EINVAL;
1680 }
1681 EXPORT_SYMBOL(lnet_inet_select);
1682
1683 int
1684 lnet_parse_ip2nets(const char **networksp, const char *ip2nets)
1685 {
1686         struct lnet_inetdev *ifaces = NULL;
1687         __u32     *ipaddrs = NULL;
1688         int nip;
1689         int        rc;
1690         int i;
1691
1692         if (current->nsproxy && current->nsproxy->net_ns)
1693                 nip = lnet_inet_enumerate(&ifaces, current->nsproxy->net_ns,
1694                                           false);
1695         else
1696                 nip = lnet_inet_enumerate(&ifaces, &init_net, false);
1697         if (nip < 0) {
1698                 if (nip != -ENOENT) {
1699                         LCONSOLE_ERROR_MSG(0x117,
1700                                            "Error %d enumerating local IP interfaces for ip2nets to match\n",
1701                                            nip);
1702                 } else {
1703                         LCONSOLE_ERROR_MSG(0x118,
1704                                            "No local IP interfaces for ip2nets to match\n");
1705                 }
1706                 return nip;
1707         }
1708
1709         CFS_ALLOC_PTR_ARRAY(ipaddrs, nip);
1710         if (!ipaddrs) {
1711                 rc = -ENOMEM;
1712                 CERROR("lnet: Can't allocate ipaddrs[%d], rc = %d\n",
1713                        nip, rc);
1714                 goto out_free_addrs;
1715         }
1716
1717         for (i = 0; i < nip; i++)
1718                 ipaddrs[i] = ntohl(ifaces[i].li_ipaddr);
1719
1720         rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip);
1721         if (rc < 0) {
1722                 LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc);
1723         } else if (rc == 0) {
1724                 LCONSOLE_ERROR_MSG(0x11a, "ip2nets does not match "
1725                                    "any local IP interfaces\n");
1726                 rc = -ENOENT;
1727         }
1728         CFS_FREE_PTR_ARRAY(ipaddrs, nip);
1729 out_free_addrs:
1730         kfree(ifaces);
1731         return rc > 0 ? 0 : rc;
1732 }