Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 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.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 Dilger | 1dc563a | 2015-11-08 18:09:37 -0500 | [diff] [blame] | 30 | * Copyright (c) 2012, 2015, Intel Corporation. |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 31 | */ |
| 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-Hartman | 9fdaf8c | 2014-07-11 20:51:16 -0700 | [diff] [blame] | 38 | #include "../../include/linux/lnet/lib-lnet.h" |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 39 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 40 | struct lnet_text_buf { /* tmp struct for parsing routes */ |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 41 | struct list_head ltb_list; /* stash on lists */ |
| 42 | int ltb_size; /* allocated size */ |
| 43 | char ltb_text[0]; /* text buffer */ |
Rafaƫl Bocquet | e416a89 | 2015-04-02 17:12:34 +0200 | [diff] [blame] | 44 | }; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 45 | |
Rashika Kheria | ad0a75b | 2013-10-26 00:24:03 +0530 | [diff] [blame] | 46 | static int lnet_tbnob; /* track text buf allocation */ |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 47 | #define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */ |
| 48 | #define LNET_SINGLE_TEXTBUF_NOB (4 << 10) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 49 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 50 | static void |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 51 | lnet_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 Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 57 | dots[sizeof(dots) - 1] = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 58 | memset(dashes, '-', sizeof(dashes)); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 59 | dashes[sizeof(dashes) - 1] = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 60 | |
| 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 Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 67 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 68 | lnet_issep(char c) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 69 | { |
| 70 | switch (c) { |
| 71 | case '\n': |
| 72 | case '\r': |
| 73 | case ';': |
| 74 | return 1; |
| 75 | default: |
| 76 | return 0; |
| 77 | } |
| 78 | } |
| 79 | |
Amir Shehata | 6c9e5a5 | 2016-02-15 10:25:54 -0500 | [diff] [blame] | 80 | int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 81 | lnet_net_unique(__u32 net, struct list_head *nilist) |
| 82 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 83 | struct list_head *tmp; |
| 84 | lnet_ni_t *ni; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 85 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 86 | list_for_each(tmp, nilist) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 87 | 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 | |
| 96 | void |
| 97 | lnet_ni_free(struct lnet_ni *ni) |
| 98 | { |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 99 | int i; |
| 100 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 101 | if (ni->ni_refs) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 102 | cfs_percpt_free(ni->ni_refs); |
| 103 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 104 | if (ni->ni_tx_queues) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 105 | cfs_percpt_free(ni->ni_tx_queues); |
| 106 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 107 | if (ni->ni_cpts) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 108 | cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts); |
| 109 | |
Amir Shehata | 243a941 | 2016-05-06 21:30:24 -0400 | [diff] [blame] | 110 | if (ni->ni_lnd_tunables) |
| 111 | LIBCFS_FREE(ni->ni_lnd_tunables, sizeof(*ni->ni_lnd_tunables)); |
| 112 | |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 113 | 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 117 | LIBCFS_FREE(ni, sizeof(*ni)); |
| 118 | } |
| 119 | |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 120 | lnet_ni_t * |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 121 | lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) |
| 122 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 123 | struct lnet_tx_queue *tq; |
| 124 | struct lnet_ni *ni; |
| 125 | int rc; |
| 126 | int i; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 127 | |
| 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 135 | if (!ni) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 136 | 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 145 | if (!ni->ni_refs) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 146 | goto failed; |
| 147 | |
| 148 | ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(), |
| 149 | sizeof(*ni->ni_tx_queues[0])); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 150 | if (!ni->ni_tx_queues) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 151 | goto failed; |
| 152 | |
| 153 | cfs_percpt_for_each(tq, i, ni->ni_tx_queues) |
| 154 | INIT_LIST_HEAD(&tq->tq_delayed); |
| 155 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 156 | if (!el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 157 | 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 Bergmann | ec0067d | 2015-09-27 16:45:22 -0400 | [diff] [blame] | 178 | ni->ni_last_alive = ktime_get_real_seconds(); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 179 | list_add_tail(&ni->ni_list, nilist); |
| 180 | return ni; |
| 181 | failed: |
| 182 | lnet_ni_free(ni); |
| 183 | return NULL; |
| 184 | } |
| 185 | |
| 186 | int |
| 187 | lnet_parse_networks(struct list_head *nilist, char *networks) |
| 188 | { |
| 189 | struct cfs_expr_list *el = NULL; |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 190 | int tokensize; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 191 | char *tokens; |
| 192 | char *str; |
| 193 | char *tmp; |
| 194 | struct lnet_ni *ni; |
| 195 | __u32 net; |
| 196 | int nnets = 0; |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 197 | struct list_head *temp_node; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 198 | |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 199 | if (!networks) { |
| 200 | CERROR("networks string is undefined\n"); |
| 201 | return -EINVAL; |
| 202 | } |
| 203 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 204 | if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) { |
| 205 | /* _WAY_ conservative */ |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 206 | LCONSOLE_ERROR_MSG(0x112, |
| 207 | "Can't parse networks: string too long\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 208 | return -EINVAL; |
| 209 | } |
| 210 | |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 211 | tokensize = strlen(networks) + 1; |
| 212 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 213 | LIBCFS_ALLOC(tokens, tokensize); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 214 | if (!tokens) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 215 | CERROR("Can't allocate net tokens\n"); |
| 216 | return -ENOMEM; |
| 217 | } |
| 218 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 219 | memcpy(tokens, networks, tokensize); |
James Simmons | d3d3d37 | 2016-02-12 12:06:05 -0500 | [diff] [blame] | 220 | tmp = tokens; |
| 221 | str = tokens; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 222 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 223 | while (str && *str) { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 224 | char *comma = strchr(str, ','); |
| 225 | char *bracket = strchr(str, '('); |
| 226 | char *square = strchr(str, '['); |
| 227 | char *iface; |
| 228 | int niface; |
| 229 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 230 | |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 231 | /* |
| 232 | * NB we don't check interface conflicts here; it's the LNDs |
| 233 | * responsibility (if it cares at all) |
| 234 | */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 235 | if (square && (!comma || square < comma)) { |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 236 | /* |
| 237 | * i.e: o2ib0(ib0)[1,2], number between square |
| 238 | * brackets are CPTs this NI needs to be bond |
| 239 | */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 240 | if (bracket && bracket > square) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 241 | tmp = square; |
| 242 | goto failed_syntax; |
| 243 | } |
| 244 | |
| 245 | tmp = strchr(square, ']'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 246 | if (!tmp) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 247 | 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 253 | if (rc) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 254 | tmp = square; |
| 255 | goto failed_syntax; |
| 256 | } |
| 257 | |
| 258 | while (square <= tmp) |
| 259 | *square++ = ' '; |
| 260 | } |
| 261 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 262 | if (!bracket || (comma && comma < bracket)) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 263 | /* no interface list specified */ |
| 264 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 265 | if (comma) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 266 | *comma++ = 0; |
| 267 | net = libcfs_str2net(cfs_trimwhite(str)); |
| 268 | |
| 269 | if (net == LNET_NIDNET(LNET_NID_ANY)) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 270 | LCONSOLE_ERROR_MSG(0x113, |
| 271 | "Unrecognised network type\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 272 | tmp = str; |
| 273 | goto failed_syntax; |
| 274 | } |
| 275 | |
| 276 | if (LNET_NETTYP(net) != LOLND && /* LO is implicit */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 277 | !lnet_ni_alloc(net, el, nilist)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 278 | goto failed; |
| 279 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 280 | if (el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 281 | 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 296 | ni = lnet_ni_alloc(net, el, nilist); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 297 | if (!ni) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 298 | goto failed; |
| 299 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 300 | if (el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 301 | cfs_expr_list_free(el); |
| 302 | el = NULL; |
| 303 | } |
| 304 | |
| 305 | niface = 0; |
| 306 | iface = bracket + 1; |
| 307 | |
| 308 | bracket = strchr(iface, ')'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 309 | if (!bracket) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 310 | tmp = iface; |
| 311 | goto failed_syntax; |
| 312 | } |
| 313 | |
| 314 | *bracket = 0; |
| 315 | do { |
| 316 | comma = strchr(iface, ','); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 317 | if (comma) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 318 | *comma++ = 0; |
| 319 | |
| 320 | iface = cfs_trimwhite(iface); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 321 | if (!*iface) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 322 | tmp = iface; |
| 323 | goto failed_syntax; |
| 324 | } |
| 325 | |
| 326 | if (niface == LNET_MAX_INTERFACES) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 327 | LCONSOLE_ERROR_MSG(0x115, |
| 328 | "Too many interfaces for net %s\n", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 329 | libcfs_net2str(net)); |
| 330 | goto failed; |
| 331 | } |
| 332 | |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 333 | /* |
| 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 350 | iface = comma; |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 351 | } while (iface); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 352 | |
| 353 | str = bracket + 1; |
| 354 | comma = strchr(bracket + 1, ','); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 355 | if (comma) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 356 | *comma = 0; |
| 357 | str = cfs_trimwhite(str); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 358 | if (*str) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 359 | tmp = str; |
| 360 | goto failed_syntax; |
| 361 | } |
| 362 | str = comma + 1; |
| 363 | continue; |
| 364 | } |
| 365 | |
| 366 | str = cfs_trimwhite(str); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 367 | if (*str) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 368 | tmp = str; |
| 369 | goto failed_syntax; |
| 370 | } |
| 371 | } |
| 372 | |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 373 | list_for_each(temp_node, nilist) |
| 374 | nnets++; |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 375 | |
| 376 | LIBCFS_FREE(tokens, tokensize); |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 377 | return nnets; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 378 | |
| 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 389 | if (el) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 390 | cfs_expr_list_free(el); |
| 391 | |
| 392 | LIBCFS_FREE(tokens, tokensize); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 393 | |
| 394 | return -EINVAL; |
| 395 | } |
| 396 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 397 | static struct lnet_text_buf * |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 398 | lnet_new_text_buf(int str_len) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 399 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 400 | struct lnet_text_buf *ltb; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 401 | int nob; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 402 | |
| 403 | /* NB allocate space for the terminating 0 */ |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 404 | nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 405 | 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 417 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 418 | return NULL; |
| 419 | |
| 420 | ltb->ltb_size = nob; |
| 421 | ltb->ltb_text[0] = 0; |
| 422 | lnet_tbnob += nob; |
| 423 | return ltb; |
| 424 | } |
| 425 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 426 | static void |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 427 | lnet_free_text_buf(struct lnet_text_buf *ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 428 | { |
| 429 | lnet_tbnob -= ltb->ltb_size; |
| 430 | LIBCFS_FREE(ltb, ltb->ltb_size); |
| 431 | } |
| 432 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 433 | static void |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 434 | lnet_free_text_bufs(struct list_head *tbs) |
| 435 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 436 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 437 | |
| 438 | while (!list_empty(tbs)) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 439 | ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 440 | |
| 441 | list_del(<b->ltb_list); |
| 442 | lnet_free_text_buf(ltb); |
| 443 | } |
| 444 | } |
| 445 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 446 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 447 | lnet_str2tbs_sep(struct list_head *tbs, char *str) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 448 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 449 | struct list_head pending; |
| 450 | char *sep; |
| 451 | int nob; |
| 452 | int i; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 453 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 454 | |
| 455 | INIT_LIST_HEAD(&pending); |
| 456 | |
| 457 | /* Split 'str' into separate commands */ |
| 458 | for (;;) { |
| 459 | /* skip leading whitespace */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 460 | while (isspace(*str)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 461 | str++; |
| 462 | |
| 463 | /* scan for separator or comment */ |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 464 | for (sep = str; *sep; sep++) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 465 | 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 471 | if (!ltb) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 472 | lnet_free_text_bufs(&pending); |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 473 | return -ENOMEM; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | for (i = 0; i < nob; i++) |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 477 | if (isspace(str[i])) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 478 | 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(<b->ltb_list, &pending); |
| 485 | } |
| 486 | |
| 487 | if (*sep == '#') { |
| 488 | /* scan for separator */ |
| 489 | do { |
| 490 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 491 | } while (*sep && !lnet_issep(*sep)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 492 | } |
| 493 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 494 | if (!*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 495 | break; |
| 496 | |
| 497 | str = sep + 1; |
| 498 | } |
| 499 | |
| 500 | list_splice(&pending, tbs->prev); |
| 501 | return 0; |
| 502 | } |
| 503 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 504 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 505 | lnet_expand1tb(struct list_head *list, |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 506 | char *str, char *sep1, char *sep2, |
| 507 | char *item, int itemlen) |
| 508 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 509 | int len1 = (int)(sep1 - str); |
| 510 | int len2 = strlen(sep2 + 1); |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 511 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 512 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 513 | LASSERT(*sep1 == '['); |
| 514 | LASSERT(*sep2 == ']'); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 515 | |
| 516 | ltb = lnet_new_text_buf(len1 + itemlen + len2); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 517 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 518 | return -ENOMEM; |
| 519 | |
| 520 | memcpy(ltb->ltb_text, str, len1); |
| 521 | memcpy(<b->ltb_text[len1], item, itemlen); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 522 | memcpy(<b->ltb_text[len1 + itemlen], sep2 + 1, len2); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 523 | ltb->ltb_text[len1 + itemlen + len2] = 0; |
| 524 | |
| 525 | list_add_tail(<b->ltb_list, list); |
| 526 | return 0; |
| 527 | } |
| 528 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 529 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 530 | lnet_str2tbs_expand(struct list_head *tbs, char *str) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 531 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 532 | 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 544 | |
| 545 | INIT_LIST_HEAD(&pending); |
| 546 | |
| 547 | sep = strchr(str, '['); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 548 | if (!sep) /* nothing to expand */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 549 | return 0; |
| 550 | |
| 551 | sep2 = strchr(sep, ']'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 552 | if (!sep2) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 553 | goto failed; |
| 554 | |
| 555 | for (parsed = sep; parsed < sep2; parsed = enditem) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 556 | enditem = ++parsed; |
| 557 | while (enditem < sep2 && *enditem != ',') |
| 558 | enditem++; |
| 559 | |
| 560 | if (enditem == parsed) /* no empty items */ |
| 561 | goto failed; |
| 562 | |
Rafaƫl Bocquet | 3a338e2 | 2015-04-02 17:12:33 +0200 | [diff] [blame] | 563 | if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, |
| 564 | &stride, &scanned) < 3) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 565 | if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 566 | /* simple string enumeration */ |
James Simmons | c314c31 | 2016-02-12 12:06:01 -0500 | [diff] [blame] | 567 | if (lnet_expand1tb(&pending, str, sep, sep2, |
| 568 | parsed, |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 569 | (int)(enditem - parsed))) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 570 | goto failed; |
Rafaƫl Bocquet | 3a338e2 | 2015-04-02 17:12:33 +0200 | [diff] [blame] | 571 | } |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 572 | 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 584 | (hi - lo) % stride) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 585 | goto failed; |
| 586 | |
| 587 | for (i = lo; i <= hi; i += stride) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 588 | 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 594 | num, nob)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 595 | goto failed; |
| 596 | } |
| 597 | } |
| 598 | |
| 599 | list_splice(&pending, tbs->prev); |
| 600 | return 1; |
| 601 | |
| 602 | failed: |
| 603 | lnet_free_text_bufs(&pending); |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 604 | return -EINVAL; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 605 | } |
| 606 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 607 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 608 | lnet_parse_hops(char *str, unsigned int *hops) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 609 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 610 | int len = strlen(str); |
| 611 | int nob = len; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 612 | |
| 613 | return (sscanf(str, "%u%n", hops, &nob) >= 1 && |
| 614 | nob == len && |
| 615 | *hops > 0 && *hops < 256); |
| 616 | } |
| 617 | |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 618 | #define LNET_PRIORITY_SEPARATOR (':') |
| 619 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 620 | static int |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 621 | lnet_parse_priority(char *str, unsigned int *priority, char **token) |
| 622 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 623 | int nob; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 624 | char *sep; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 625 | int len; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 626 | |
| 627 | sep = strchr(str, LNET_PRIORITY_SEPARATOR); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 628 | if (!sep) { |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 629 | *priority = 0; |
| 630 | return 0; |
| 631 | } |
| 632 | len = strlen(sep + 1); |
| 633 | |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 634 | if ((sscanf((sep + 1), "%u%n", priority, &nob) < 1) || (len != nob)) { |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 635 | /* |
| 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 Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 639 | *token += sep - str + 1; |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 640 | return -EINVAL; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 641 | } |
| 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 651 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 652 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 653 | lnet_parse_route(char *str, int *im_a_router) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 654 | { |
| 655 | /* static scratch buffer OK (single threaded) */ |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 656 | static char cmd[LNET_SINGLE_TEXTBUF_NOB]; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 657 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 658 | 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 Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 664 | struct lnet_text_buf *ltb; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 665 | int rc; |
| 666 | char *sep; |
| 667 | char *token = str; |
| 668 | int ntokens = 0; |
| 669 | int myrc = -1; |
Amir Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 670 | __u32 hops; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 671 | int got_hops = 0; |
| 672 | unsigned int priority = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 673 | |
| 674 | INIT_LIST_HEAD(&gateways); |
| 675 | INIT_LIST_HEAD(&nets); |
| 676 | |
| 677 | /* save a copy of the string for error messages */ |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 678 | strncpy(cmd, str, sizeof(cmd)); |
| 679 | cmd[sizeof(cmd) - 1] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 680 | |
| 681 | sep = str; |
| 682 | for (;;) { |
| 683 | /* scan for token start */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 684 | while (isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 685 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 686 | if (!*sep) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 687 | 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 696 | while (*sep && !isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 697 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 698 | if (*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 699 | *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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 712 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 713 | goto out; |
| 714 | |
| 715 | strcpy(ltb->ltb_text, token); |
| 716 | tmp1 = <b->ltb_list; |
| 717 | list_add_tail(tmp1, tmp2); |
| 718 | |
| 719 | while (tmp1 != tmp2) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 720 | ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 721 | |
| 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(<b->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 Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 740 | rc = lnet_parse_priority(ltb->ltb_text, |
| 741 | &priority, &token); |
| 742 | if (rc < 0) |
| 743 | goto token_error; |
| 744 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 745 | 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 Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 753 | /** |
| 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 Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 757 | if (!got_hops) |
Amir Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 758 | hops = LNET_UNDEFINED_HOPS; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 759 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 760 | LASSERT(!list_empty(&nets)); |
| 761 | LASSERT(!list_empty(&gateways)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 762 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 763 | list_for_each(tmp1, &nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 764 | ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 765 | net = libcfs_str2net(ltb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 766 | LASSERT(net != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 767 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 768 | list_for_each(tmp2, &gateways) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 769 | ltb = list_entry(tmp2, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 770 | nid = libcfs_str2nid(ltb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 771 | LASSERT(nid != LNET_NID_ANY); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 772 | |
| 773 | if (lnet_islocalnid(nid)) { |
| 774 | *im_a_router = 1; |
| 775 | continue; |
| 776 | } |
| 777 | |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 778 | rc = lnet_add_route(net, hops, nid, priority); |
Amir Shehata | be8240a | 2016-02-22 17:29:09 -0500 | [diff] [blame] | 779 | if (rc && rc != -EEXIST && rc != -EHOSTUNREACH) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 780 | CERROR("Can't create route to %s via %s\n", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 781 | 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 Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 799 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 800 | lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router) |
| 801 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 802 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 803 | |
| 804 | while (!list_empty(tbs)) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 805 | ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 806 | |
| 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(<b->ltb_list); |
| 813 | lnet_free_text_buf(ltb); |
| 814 | } |
| 815 | |
| 816 | return 0; |
| 817 | } |
| 818 | |
| 819 | int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 820 | lnet_parse_routes(char *routes, int *im_a_router) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 821 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 822 | struct list_head tbs; |
| 823 | int rc = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 824 | |
| 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 836 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 837 | return rc; |
| 838 | } |
| 839 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 840 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 841 | lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip) |
| 842 | { |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 843 | LIST_HEAD(list); |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 844 | int rc; |
| 845 | int i; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 846 | |
| 847 | rc = cfs_ip_addr_parse(token, len, &list); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 848 | if (rc) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 849 | return rc; |
| 850 | |
| 851 | for (rc = i = 0; !rc && i < nip; i++) |
| 852 | rc = cfs_ip_addr_match(ipaddrs[i], &list); |
| 853 | |
James Simmons | a620ec6 | 2015-10-21 21:52:42 -0400 | [diff] [blame] | 854 | cfs_expr_list_free_list(&list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 855 | |
| 856 | return rc; |
| 857 | } |
| 858 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 859 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 860 | lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) |
| 861 | { |
| 862 | static char tokens[LNET_SINGLE_TEXTBUF_NOB]; |
| 863 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 864 | int matched = 0; |
| 865 | int ntokens = 0; |
| 866 | int len; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 867 | char *net = NULL; |
| 868 | char *sep; |
| 869 | char *token; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 870 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 871 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 872 | LASSERT(strlen(net_entry) < sizeof(tokens)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 873 | |
| 874 | /* work on a copy of the string */ |
| 875 | strcpy(tokens, net_entry); |
| 876 | sep = tokens; |
| 877 | for (;;) { |
| 878 | /* scan for token start */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 879 | while (isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 880 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 881 | if (!*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 882 | break; |
| 883 | |
| 884 | token = sep++; |
| 885 | |
| 886 | /* scan for token end */ |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 887 | while (*sep && !isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 888 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 889 | if (*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 890 | *sep++ = 0; |
| 891 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 892 | if (!ntokens++) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 893 | 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 906 | if (rc) |
| 907 | matched |= 1; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 908 | } |
| 909 | |
| 910 | if (!matched) |
| 911 | return 0; |
| 912 | |
| 913 | strcpy(net_entry, net); /* replace with matched net */ |
| 914 | return 1; |
| 915 | } |
| 916 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 917 | static __u32 |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 918 | lnet_netspec2net(char *netspec) |
| 919 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 920 | char *bracket = strchr(netspec, '('); |
| 921 | __u32 net; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 922 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 923 | if (bracket) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 924 | *bracket = 0; |
| 925 | |
| 926 | net = libcfs_str2net(netspec); |
| 927 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 928 | if (bracket) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 929 | *bracket = '('; |
| 930 | |
| 931 | return net; |
| 932 | } |
| 933 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 934 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 935 | lnet_splitnets(char *source, struct list_head *nets) |
| 936 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 937 | int offset = 0; |
| 938 | int offset2; |
| 939 | int len; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 940 | struct lnet_text_buf *tb; |
| 941 | struct lnet_text_buf *tb2; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 942 | struct list_head *t; |
| 943 | char *sep; |
| 944 | char *bracket; |
| 945 | __u32 net; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 946 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 947 | LASSERT(!list_empty(nets)); |
| 948 | LASSERT(nets->next == nets->prev); /* single entry */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 949 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 950 | tb = list_entry(nets->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 951 | |
| 952 | for (;;) { |
| 953 | sep = strchr(tb->ltb_text, ','); |
| 954 | bracket = strchr(tb->ltb_text, '('); |
| 955 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 956 | if (sep && bracket && bracket < sep) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 957 | /* netspec lists interfaces... */ |
| 958 | |
| 959 | offset2 = offset + (int)(bracket - tb->ltb_text); |
| 960 | len = strlen(bracket); |
| 961 | |
| 962 | bracket = strchr(bracket + 1, ')'); |
| 963 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 964 | if (!bracket || |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 965 | !(bracket[1] == ',' || !bracket[1])) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 966 | lnet_syntax("ip2nets", source, offset2, len); |
| 967 | return -EINVAL; |
| 968 | } |
| 969 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 970 | sep = !bracket[1] ? NULL : bracket + 1; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 971 | } |
| 972 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 973 | if (sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 974 | *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 Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 984 | tb2 = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 985 | |
| 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 Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 997 | if (!sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 998 | return 0; |
| 999 | |
| 1000 | offset += (int)(sep - tb->ltb_text); |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1001 | len = strlen(sep); |
| 1002 | tb2 = lnet_new_text_buf(len); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1003 | if (!tb2) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1004 | return -ENOMEM; |
| 1005 | |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1006 | strncpy(tb2->ltb_text, sep, len); |
| 1007 | tb2->ltb_text[len] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1008 | list_add_tail(&tb2->ltb_list, nets); |
| 1009 | |
| 1010 | tb = tb2; |
| 1011 | } |
| 1012 | } |
| 1013 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 1014 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1015 | lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1016 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1017 | static char networks[LNET_SINGLE_TEXTBUF_NOB]; |
| 1018 | static char source[LNET_SINGLE_TEXTBUF_NOB]; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1019 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1020 | 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 Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1025 | struct lnet_text_buf *tb; |
Bhaktipriya Shridhar | cb734cf | 2016-03-12 01:33:03 +0530 | [diff] [blame] | 1026 | struct lnet_text_buf *temp; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1027 | struct lnet_text_buf *tb2; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1028 | __u32 net1; |
| 1029 | __u32 net2; |
| 1030 | int len; |
| 1031 | int count; |
| 1032 | int dup; |
| 1033 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1034 | |
| 1035 | INIT_LIST_HEAD(&raw_entries); |
| 1036 | if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) { |
| 1037 | CERROR("Error parsing ip2nets\n"); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1038 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1039 | return -EINVAL; |
| 1040 | } |
| 1041 | |
| 1042 | INIT_LIST_HEAD(&matched_nets); |
| 1043 | INIT_LIST_HEAD(¤t_nets); |
| 1044 | networks[0] = 0; |
| 1045 | count = 0; |
| 1046 | len = 0; |
| 1047 | rc = 0; |
| 1048 | |
Bhaktipriya Shridhar | cb734cf | 2016-03-12 01:33:03 +0530 | [diff] [blame] | 1049 | list_for_each_entry_safe(tb, temp, &raw_entries, ltb_list) { |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1050 | strncpy(source, tb->ltb_text, sizeof(source)); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 1051 | source[sizeof(source) - 1] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1052 | |
| 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1060 | if (!rc) { /* no match */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1061 | lnet_free_text_buf(tb); |
| 1062 | continue; |
| 1063 | } |
| 1064 | |
| 1065 | /* split into separate networks */ |
| 1066 | INIT_LIST_HEAD(¤t_nets); |
| 1067 | list_add(&tb->ltb_list, ¤t_nets); |
| 1068 | rc = lnet_splitnets(source, ¤t_nets); |
| 1069 | if (rc < 0) |
| 1070 | break; |
| 1071 | |
| 1072 | dup = 0; |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1073 | list_for_each(t, ¤t_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1074 | tb = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1075 | net1 = lnet_netspec2net(tb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1076 | LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1077 | |
| 1078 | list_for_each(t2, &matched_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1079 | tb2 = list_entry(t2, struct lnet_text_buf, |
| 1080 | ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1081 | net2 = lnet_netspec2net(tb2->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1082 | LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1083 | |
| 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(¤t_nets); |
| 1096 | continue; |
| 1097 | } |
| 1098 | |
| 1099 | list_for_each_safe(t, t2, ¤t_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1100 | tb = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1101 | |
| 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 Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1106 | "%s%s", !len ? "" : ",", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1107 | 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(¤t_nets); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1123 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1124 | |
| 1125 | if (rc < 0) |
| 1126 | return rc; |
| 1127 | |
| 1128 | *networksp = networks; |
| 1129 | return count; |
| 1130 | } |
| 1131 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 1132 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1133 | lnet_ipaddr_enumerate(__u32 **ipaddrsp) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1134 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1135 | int up; |
| 1136 | __u32 netmask; |
| 1137 | __u32 *ipaddrs; |
| 1138 | __u32 *ipaddrs2; |
| 1139 | int nip; |
| 1140 | char **ifnames; |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1141 | int nif = lnet_ipif_enumerate(&ifnames); |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1142 | int i; |
| 1143 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1144 | |
| 1145 | if (nif <= 0) |
| 1146 | return nif; |
| 1147 | |
| 1148 | LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1149 | if (!ipaddrs) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1150 | CERROR("Can't allocate ipaddrs[%d]\n", nif); |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1151 | lnet_ipif_free_enumeration(ifnames, nif); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1152 | return -ENOMEM; |
| 1153 | } |
| 1154 | |
| 1155 | for (i = nip = 0; i < nif; i++) { |
| 1156 | if (!strcmp(ifnames[i], "lo")) |
| 1157 | continue; |
| 1158 | |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1159 | rc = lnet_ipif_query(ifnames[i], &up, &ipaddrs[nip], &netmask); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1160 | if (rc) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1161 | 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 Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1175 | lnet_ipif_free_enumeration(ifnames, nif); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1176 | |
| 1177 | if (nip == nif) { |
| 1178 | *ipaddrsp = ipaddrs; |
| 1179 | } else { |
| 1180 | if (nip > 0) { |
| 1181 | LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1182 | if (!ipaddrs2) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1183 | 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 Bhardwaj | cfa3811 | 2015-10-29 12:28:31 +0530 | [diff] [blame] | 1192 | LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1193 | } |
| 1194 | return nip; |
| 1195 | } |
| 1196 | |
| 1197 | int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1198 | lnet_parse_ip2nets(char **networksp, char *ip2nets) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1199 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1200 | __u32 *ipaddrs = NULL; |
| 1201 | int nip = lnet_ipaddr_enumerate(&ipaddrs); |
| 1202 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1203 | |
| 1204 | if (nip < 0) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1205 | LCONSOLE_ERROR_MSG(0x117, |
| 1206 | "Error %d enumerating local IP interfaces for ip2nets to match\n", |
| 1207 | nip); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1208 | return nip; |
| 1209 | } |
| 1210 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1211 | if (!nip) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1212 | LCONSOLE_ERROR_MSG(0x118, |
| 1213 | "No local IP interfaces for ip2nets to match\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1214 | return -ENOENT; |
| 1215 | } |
| 1216 | |
| 1217 | rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); |
Shivani Bhardwaj | cfa3811 | 2015-10-29 12:28:31 +0530 | [diff] [blame] | 1218 | LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1219 | |
| 1220 | if (rc < 0) { |
| 1221 | LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc); |
| 1222 | return rc; |
| 1223 | } |
| 1224 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1225 | if (!rc) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1226 | LCONSOLE_ERROR_MSG(0x11a, |
| 1227 | "ip2nets does not match any local IP interfaces\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1228 | return -ENOENT; |
| 1229 | } |
| 1230 | |
| 1231 | return 0; |
| 1232 | } |