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 |
Oleg Drokin | 6a5b99a | 2016-06-14 23:33:40 -0400 | [diff] [blame] | 18 | * http://www.gnu.org/licenses/gpl-2.0.html |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 19 | * |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 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 | * |
Andreas Dilger | 1dc563a | 2015-11-08 18:09:37 -0500 | [diff] [blame] | 26 | * Copyright (c) 2012, 2015, Intel Corporation. |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 27 | */ |
| 28 | /* |
| 29 | * This file is part of Lustre, http://www.lustre.org/ |
| 30 | * Lustre is a trademark of Sun Microsystems, Inc. |
| 31 | */ |
| 32 | |
| 33 | #define DEBUG_SUBSYSTEM S_LNET |
Sebastien Buisson | 4c6722f | 2016-09-18 16:38:59 -0400 | [diff] [blame] | 34 | #include <linux/nsproxy.h> |
| 35 | #include <net/net_namespace.h> |
Greg Kroah-Hartman | 9fdaf8c | 2014-07-11 20:51:16 -0700 | [diff] [blame] | 36 | #include "../../include/linux/lnet/lib-lnet.h" |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 37 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 38 | struct lnet_text_buf { /* tmp struct for parsing routes */ |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 39 | struct list_head ltb_list; /* stash on lists */ |
| 40 | int ltb_size; /* allocated size */ |
| 41 | char ltb_text[0]; /* text buffer */ |
Rafaƫl Bocquet | e416a89 | 2015-04-02 17:12:34 +0200 | [diff] [blame] | 42 | }; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 43 | |
Rashika Kheria | ad0a75b | 2013-10-26 00:24:03 +0530 | [diff] [blame] | 44 | static int lnet_tbnob; /* track text buf allocation */ |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 45 | #define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */ |
| 46 | #define LNET_SINGLE_TEXTBUF_NOB (4 << 10) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 47 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 48 | static void |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 49 | lnet_syntax(char *name, char *str, int offset, int width) |
| 50 | { |
| 51 | static char dots[LNET_SINGLE_TEXTBUF_NOB]; |
| 52 | static char dashes[LNET_SINGLE_TEXTBUF_NOB]; |
| 53 | |
| 54 | memset(dots, '.', sizeof(dots)); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 55 | dots[sizeof(dots) - 1] = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 56 | memset(dashes, '-', sizeof(dashes)); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 57 | dashes[sizeof(dashes) - 1] = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 58 | |
| 59 | LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str); |
| 60 | LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n", |
| 61 | (int)strlen(name), dots, offset, dots, |
| 62 | (width < 1) ? 0 : width - 1, dashes); |
| 63 | } |
| 64 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 65 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 66 | lnet_issep(char c) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 67 | { |
| 68 | switch (c) { |
| 69 | case '\n': |
| 70 | case '\r': |
| 71 | case ';': |
| 72 | return 1; |
| 73 | default: |
| 74 | return 0; |
| 75 | } |
| 76 | } |
| 77 | |
Amir Shehata | 6c9e5a5 | 2016-02-15 10:25:54 -0500 | [diff] [blame] | 78 | int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 79 | lnet_net_unique(__u32 net, struct list_head *nilist) |
| 80 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 81 | struct list_head *tmp; |
| 82 | lnet_ni_t *ni; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 83 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 84 | list_for_each(tmp, nilist) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 85 | ni = list_entry(tmp, lnet_ni_t, ni_list); |
| 86 | |
| 87 | if (LNET_NIDNET(ni->ni_nid) == net) |
| 88 | return 0; |
| 89 | } |
| 90 | |
| 91 | return 1; |
| 92 | } |
| 93 | |
| 94 | void |
| 95 | lnet_ni_free(struct lnet_ni *ni) |
| 96 | { |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 97 | int i; |
| 98 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 99 | if (ni->ni_refs) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 100 | cfs_percpt_free(ni->ni_refs); |
| 101 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 102 | if (ni->ni_tx_queues) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 103 | cfs_percpt_free(ni->ni_tx_queues); |
| 104 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 105 | if (ni->ni_cpts) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 106 | cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts); |
| 107 | |
Amir Shehata | 243a941 | 2016-05-06 21:30:24 -0400 | [diff] [blame] | 108 | if (ni->ni_lnd_tunables) |
| 109 | LIBCFS_FREE(ni->ni_lnd_tunables, sizeof(*ni->ni_lnd_tunables)); |
| 110 | |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 111 | for (i = 0; i < LNET_MAX_INTERFACES && ni->ni_interfaces[i]; i++) { |
| 112 | LIBCFS_FREE(ni->ni_interfaces[i], |
| 113 | strlen(ni->ni_interfaces[i]) + 1); |
| 114 | } |
Sebastien Buisson | 4c6722f | 2016-09-18 16:38:59 -0400 | [diff] [blame] | 115 | |
| 116 | /* release reference to net namespace */ |
| 117 | if (ni->ni_net_ns) |
| 118 | put_net(ni->ni_net_ns); |
| 119 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 120 | LIBCFS_FREE(ni, sizeof(*ni)); |
| 121 | } |
| 122 | |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 123 | lnet_ni_t * |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 124 | lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) |
| 125 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 126 | struct lnet_tx_queue *tq; |
| 127 | struct lnet_ni *ni; |
| 128 | int rc; |
| 129 | int i; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 130 | |
| 131 | if (!lnet_net_unique(net, nilist)) { |
| 132 | LCONSOLE_ERROR_MSG(0x111, "Duplicate network specified: %s\n", |
| 133 | libcfs_net2str(net)); |
| 134 | return NULL; |
| 135 | } |
| 136 | |
| 137 | LIBCFS_ALLOC(ni, sizeof(*ni)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 138 | if (!ni) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 139 | CERROR("Out of memory creating network %s\n", |
| 140 | libcfs_net2str(net)); |
| 141 | return NULL; |
| 142 | } |
| 143 | |
| 144 | spin_lock_init(&ni->ni_lock); |
| 145 | INIT_LIST_HEAD(&ni->ni_cptlist); |
| 146 | ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(), |
| 147 | sizeof(*ni->ni_refs[0])); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 148 | if (!ni->ni_refs) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 149 | goto failed; |
| 150 | |
| 151 | ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(), |
| 152 | sizeof(*ni->ni_tx_queues[0])); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 153 | if (!ni->ni_tx_queues) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 154 | goto failed; |
| 155 | |
| 156 | cfs_percpt_for_each(tq, i, ni->ni_tx_queues) |
| 157 | INIT_LIST_HEAD(&tq->tq_delayed); |
| 158 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 159 | if (!el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 160 | ni->ni_cpts = NULL; |
| 161 | ni->ni_ncpts = LNET_CPT_NUMBER; |
| 162 | } else { |
| 163 | rc = cfs_expr_list_values(el, LNET_CPT_NUMBER, &ni->ni_cpts); |
| 164 | if (rc <= 0) { |
| 165 | CERROR("Failed to set CPTs for NI %s: %d\n", |
| 166 | libcfs_net2str(net), rc); |
| 167 | goto failed; |
| 168 | } |
| 169 | |
| 170 | LASSERT(rc <= LNET_CPT_NUMBER); |
| 171 | if (rc == LNET_CPT_NUMBER) { |
| 172 | LIBCFS_FREE(ni->ni_cpts, rc * sizeof(ni->ni_cpts[0])); |
| 173 | ni->ni_cpts = NULL; |
| 174 | } |
| 175 | |
| 176 | ni->ni_ncpts = rc; |
| 177 | } |
| 178 | |
| 179 | /* LND will fill in the address part of the NID */ |
| 180 | ni->ni_nid = LNET_MKNID(net, 0); |
Sebastien Buisson | 4c6722f | 2016-09-18 16:38:59 -0400 | [diff] [blame] | 181 | |
| 182 | /* Store net namespace in which current ni is being created */ |
| 183 | if (current->nsproxy->net_ns) |
| 184 | ni->ni_net_ns = get_net(current->nsproxy->net_ns); |
| 185 | else |
| 186 | ni->ni_net_ns = NULL; |
| 187 | |
Arnd Bergmann | ec0067d | 2015-09-27 16:45:22 -0400 | [diff] [blame] | 188 | ni->ni_last_alive = ktime_get_real_seconds(); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 189 | list_add_tail(&ni->ni_list, nilist); |
| 190 | return ni; |
| 191 | failed: |
| 192 | lnet_ni_free(ni); |
| 193 | return NULL; |
| 194 | } |
| 195 | |
| 196 | int |
| 197 | lnet_parse_networks(struct list_head *nilist, char *networks) |
| 198 | { |
| 199 | struct cfs_expr_list *el = NULL; |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 200 | int tokensize; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 201 | char *tokens; |
| 202 | char *str; |
| 203 | char *tmp; |
| 204 | struct lnet_ni *ni; |
| 205 | __u32 net; |
| 206 | int nnets = 0; |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 207 | struct list_head *temp_node; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 208 | |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 209 | if (!networks) { |
| 210 | CERROR("networks string is undefined\n"); |
| 211 | return -EINVAL; |
| 212 | } |
| 213 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 214 | if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) { |
| 215 | /* _WAY_ conservative */ |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 216 | LCONSOLE_ERROR_MSG(0x112, |
| 217 | "Can't parse networks: string too long\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 218 | return -EINVAL; |
| 219 | } |
| 220 | |
Amir Shehata | 8766cd12 | 2016-02-22 17:29:04 -0500 | [diff] [blame] | 221 | tokensize = strlen(networks) + 1; |
| 222 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 223 | LIBCFS_ALLOC(tokens, tokensize); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 224 | if (!tokens) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 225 | CERROR("Can't allocate net tokens\n"); |
| 226 | return -ENOMEM; |
| 227 | } |
| 228 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 229 | memcpy(tokens, networks, tokensize); |
James Simmons | d3d3d37 | 2016-02-12 12:06:05 -0500 | [diff] [blame] | 230 | tmp = tokens; |
| 231 | str = tokens; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 232 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 233 | while (str && *str) { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 234 | char *comma = strchr(str, ','); |
| 235 | char *bracket = strchr(str, '('); |
| 236 | char *square = strchr(str, '['); |
| 237 | char *iface; |
| 238 | int niface; |
| 239 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 240 | |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 241 | /* |
| 242 | * NB we don't check interface conflicts here; it's the LNDs |
| 243 | * responsibility (if it cares at all) |
| 244 | */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 245 | if (square && (!comma || square < comma)) { |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 246 | /* |
| 247 | * i.e: o2ib0(ib0)[1,2], number between square |
| 248 | * brackets are CPTs this NI needs to be bond |
| 249 | */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 250 | if (bracket && bracket > square) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 251 | tmp = square; |
| 252 | goto failed_syntax; |
| 253 | } |
| 254 | |
| 255 | tmp = strchr(square, ']'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 256 | if (!tmp) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 257 | tmp = square; |
| 258 | goto failed_syntax; |
| 259 | } |
| 260 | |
| 261 | rc = cfs_expr_list_parse(square, tmp - square + 1, |
| 262 | 0, LNET_CPT_NUMBER - 1, &el); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 263 | if (rc) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 264 | tmp = square; |
| 265 | goto failed_syntax; |
| 266 | } |
| 267 | |
| 268 | while (square <= tmp) |
| 269 | *square++ = ' '; |
| 270 | } |
| 271 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 272 | if (!bracket || (comma && comma < bracket)) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 273 | /* no interface list specified */ |
| 274 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 275 | if (comma) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 276 | *comma++ = 0; |
| 277 | net = libcfs_str2net(cfs_trimwhite(str)); |
| 278 | |
| 279 | if (net == LNET_NIDNET(LNET_NID_ANY)) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 280 | LCONSOLE_ERROR_MSG(0x113, |
| 281 | "Unrecognised network type\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 282 | tmp = str; |
| 283 | goto failed_syntax; |
| 284 | } |
| 285 | |
| 286 | if (LNET_NETTYP(net) != LOLND && /* LO is implicit */ |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 287 | !lnet_ni_alloc(net, el, nilist)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 288 | goto failed; |
| 289 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 290 | if (el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 291 | cfs_expr_list_free(el); |
| 292 | el = NULL; |
| 293 | } |
| 294 | |
| 295 | str = comma; |
| 296 | continue; |
| 297 | } |
| 298 | |
| 299 | *bracket = 0; |
| 300 | net = libcfs_str2net(cfs_trimwhite(str)); |
| 301 | if (net == LNET_NIDNET(LNET_NID_ANY)) { |
| 302 | tmp = str; |
| 303 | goto failed_syntax; |
| 304 | } |
| 305 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 306 | ni = lnet_ni_alloc(net, el, nilist); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 307 | if (!ni) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 308 | goto failed; |
| 309 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 310 | if (el) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 311 | cfs_expr_list_free(el); |
| 312 | el = NULL; |
| 313 | } |
| 314 | |
| 315 | niface = 0; |
| 316 | iface = bracket + 1; |
| 317 | |
| 318 | bracket = strchr(iface, ')'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 319 | if (!bracket) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 320 | tmp = iface; |
| 321 | goto failed_syntax; |
| 322 | } |
| 323 | |
| 324 | *bracket = 0; |
| 325 | do { |
| 326 | comma = strchr(iface, ','); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 327 | if (comma) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 328 | *comma++ = 0; |
| 329 | |
| 330 | iface = cfs_trimwhite(iface); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 331 | if (!*iface) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 332 | tmp = iface; |
| 333 | goto failed_syntax; |
| 334 | } |
| 335 | |
| 336 | if (niface == LNET_MAX_INTERFACES) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 337 | LCONSOLE_ERROR_MSG(0x115, |
| 338 | "Too many interfaces for net %s\n", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 339 | libcfs_net2str(net)); |
| 340 | goto failed; |
| 341 | } |
| 342 | |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 343 | /* |
| 344 | * Allocate a separate piece of memory and copy |
| 345 | * into it the string, so we don't have |
| 346 | * a depencency on the tokens string. This way we |
| 347 | * can free the tokens at the end of the function. |
| 348 | * The newly allocated ni_interfaces[] can be |
| 349 | * freed when freeing the NI |
| 350 | */ |
| 351 | LIBCFS_ALLOC(ni->ni_interfaces[niface], |
| 352 | strlen(iface) + 1); |
| 353 | if (!ni->ni_interfaces[niface]) { |
| 354 | CERROR("Can't allocate net interface name\n"); |
| 355 | goto failed; |
| 356 | } |
| 357 | strncpy(ni->ni_interfaces[niface], iface, |
| 358 | strlen(iface)); |
| 359 | niface++; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 360 | iface = comma; |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 361 | } while (iface); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 362 | |
| 363 | str = bracket + 1; |
| 364 | comma = strchr(bracket + 1, ','); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 365 | if (comma) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 366 | *comma = 0; |
| 367 | str = cfs_trimwhite(str); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 368 | if (*str) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 369 | tmp = str; |
| 370 | goto failed_syntax; |
| 371 | } |
| 372 | str = comma + 1; |
| 373 | continue; |
| 374 | } |
| 375 | |
| 376 | str = cfs_trimwhite(str); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 377 | if (*str) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 378 | tmp = str; |
| 379 | goto failed_syntax; |
| 380 | } |
| 381 | } |
| 382 | |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 383 | list_for_each(temp_node, nilist) |
| 384 | nnets++; |
Amir Shehata | 21602c7 | 2016-02-15 10:25:52 -0500 | [diff] [blame] | 385 | |
| 386 | LIBCFS_FREE(tokens, tokensize); |
Amir Shehata | 9c26b89 | 2016-02-22 17:29:08 -0500 | [diff] [blame] | 387 | return nnets; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 388 | |
| 389 | failed_syntax: |
| 390 | lnet_syntax("networks", networks, (int)(tmp - tokens), strlen(tmp)); |
| 391 | failed: |
| 392 | while (!list_empty(nilist)) { |
| 393 | ni = list_entry(nilist->next, lnet_ni_t, ni_list); |
| 394 | |
| 395 | list_del(&ni->ni_list); |
| 396 | lnet_ni_free(ni); |
| 397 | } |
| 398 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 399 | if (el) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 400 | cfs_expr_list_free(el); |
| 401 | |
| 402 | LIBCFS_FREE(tokens, tokensize); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 403 | |
| 404 | return -EINVAL; |
| 405 | } |
| 406 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 407 | static struct lnet_text_buf * |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 408 | lnet_new_text_buf(int str_len) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 409 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 410 | struct lnet_text_buf *ltb; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 411 | int nob; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 412 | |
| 413 | /* NB allocate space for the terminating 0 */ |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 414 | nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 415 | if (nob > LNET_SINGLE_TEXTBUF_NOB) { |
| 416 | /* _way_ conservative for "route net gateway..." */ |
| 417 | CERROR("text buffer too big\n"); |
| 418 | return NULL; |
| 419 | } |
| 420 | |
| 421 | if (lnet_tbnob + nob > LNET_MAX_TEXTBUF_NOB) { |
| 422 | CERROR("Too many text buffers\n"); |
| 423 | return NULL; |
| 424 | } |
| 425 | |
| 426 | LIBCFS_ALLOC(ltb, nob); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 427 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 428 | return NULL; |
| 429 | |
| 430 | ltb->ltb_size = nob; |
| 431 | ltb->ltb_text[0] = 0; |
| 432 | lnet_tbnob += nob; |
| 433 | return ltb; |
| 434 | } |
| 435 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 436 | static void |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 437 | lnet_free_text_buf(struct lnet_text_buf *ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 438 | { |
| 439 | lnet_tbnob -= ltb->ltb_size; |
| 440 | LIBCFS_FREE(ltb, ltb->ltb_size); |
| 441 | } |
| 442 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 443 | static void |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 444 | lnet_free_text_bufs(struct list_head *tbs) |
| 445 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 446 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 447 | |
| 448 | while (!list_empty(tbs)) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 449 | ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 450 | |
| 451 | list_del(<b->ltb_list); |
| 452 | lnet_free_text_buf(ltb); |
| 453 | } |
| 454 | } |
| 455 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 456 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 457 | lnet_str2tbs_sep(struct list_head *tbs, char *str) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 458 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 459 | struct list_head pending; |
| 460 | char *sep; |
| 461 | int nob; |
| 462 | int i; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 463 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 464 | |
| 465 | INIT_LIST_HEAD(&pending); |
| 466 | |
| 467 | /* Split 'str' into separate commands */ |
| 468 | for (;;) { |
| 469 | /* skip leading whitespace */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 470 | while (isspace(*str)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 471 | str++; |
| 472 | |
| 473 | /* scan for separator or comment */ |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 474 | for (sep = str; *sep; sep++) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 475 | if (lnet_issep(*sep) || *sep == '#') |
| 476 | break; |
| 477 | |
| 478 | nob = (int)(sep - str); |
| 479 | if (nob > 0) { |
| 480 | ltb = lnet_new_text_buf(nob); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 481 | if (!ltb) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 482 | lnet_free_text_bufs(&pending); |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 483 | return -ENOMEM; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 484 | } |
| 485 | |
| 486 | for (i = 0; i < nob; i++) |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 487 | if (isspace(str[i])) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 488 | ltb->ltb_text[i] = ' '; |
| 489 | else |
| 490 | ltb->ltb_text[i] = str[i]; |
| 491 | |
| 492 | ltb->ltb_text[nob] = 0; |
| 493 | |
| 494 | list_add_tail(<b->ltb_list, &pending); |
| 495 | } |
| 496 | |
| 497 | if (*sep == '#') { |
| 498 | /* scan for separator */ |
| 499 | do { |
| 500 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 501 | } while (*sep && !lnet_issep(*sep)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 502 | } |
| 503 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 504 | if (!*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 505 | break; |
| 506 | |
| 507 | str = sep + 1; |
| 508 | } |
| 509 | |
| 510 | list_splice(&pending, tbs->prev); |
| 511 | return 0; |
| 512 | } |
| 513 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 514 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 515 | lnet_expand1tb(struct list_head *list, |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 516 | char *str, char *sep1, char *sep2, |
| 517 | char *item, int itemlen) |
| 518 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 519 | int len1 = (int)(sep1 - str); |
| 520 | int len2 = strlen(sep2 + 1); |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 521 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 522 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 523 | LASSERT(*sep1 == '['); |
| 524 | LASSERT(*sep2 == ']'); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 525 | |
| 526 | ltb = lnet_new_text_buf(len1 + itemlen + len2); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 527 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 528 | return -ENOMEM; |
| 529 | |
| 530 | memcpy(ltb->ltb_text, str, len1); |
| 531 | memcpy(<b->ltb_text[len1], item, itemlen); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 532 | memcpy(<b->ltb_text[len1 + itemlen], sep2 + 1, len2); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 533 | ltb->ltb_text[len1 + itemlen + len2] = 0; |
| 534 | |
| 535 | list_add_tail(<b->ltb_list, list); |
| 536 | return 0; |
| 537 | } |
| 538 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 539 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 540 | lnet_str2tbs_expand(struct list_head *tbs, char *str) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 541 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 542 | char num[16]; |
| 543 | struct list_head pending; |
| 544 | char *sep; |
| 545 | char *sep2; |
| 546 | char *parsed; |
| 547 | char *enditem; |
| 548 | int lo; |
| 549 | int hi; |
| 550 | int stride; |
| 551 | int i; |
| 552 | int nob; |
| 553 | int scanned; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 554 | |
| 555 | INIT_LIST_HEAD(&pending); |
| 556 | |
| 557 | sep = strchr(str, '['); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 558 | if (!sep) /* nothing to expand */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 559 | return 0; |
| 560 | |
| 561 | sep2 = strchr(sep, ']'); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 562 | if (!sep2) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 563 | goto failed; |
| 564 | |
| 565 | for (parsed = sep; parsed < sep2; parsed = enditem) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 566 | enditem = ++parsed; |
| 567 | while (enditem < sep2 && *enditem != ',') |
| 568 | enditem++; |
| 569 | |
| 570 | if (enditem == parsed) /* no empty items */ |
| 571 | goto failed; |
| 572 | |
Rafaƫl Bocquet | 3a338e2 | 2015-04-02 17:12:33 +0200 | [diff] [blame] | 573 | if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, |
| 574 | &stride, &scanned) < 3) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 575 | if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 576 | /* simple string enumeration */ |
James Simmons | c314c31 | 2016-02-12 12:06:01 -0500 | [diff] [blame] | 577 | if (lnet_expand1tb(&pending, str, sep, sep2, |
| 578 | parsed, |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 579 | (int)(enditem - parsed))) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 580 | goto failed; |
Rafaƫl Bocquet | 3a338e2 | 2015-04-02 17:12:33 +0200 | [diff] [blame] | 581 | } |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 582 | continue; |
| 583 | } |
| 584 | |
| 585 | stride = 1; |
| 586 | } |
| 587 | |
| 588 | /* range expansion */ |
| 589 | |
| 590 | if (enditem != parsed + scanned) /* no trailing junk */ |
| 591 | goto failed; |
| 592 | |
| 593 | if (hi < 0 || lo < 0 || stride < 0 || hi < lo || |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 594 | (hi - lo) % stride) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 595 | goto failed; |
| 596 | |
| 597 | for (i = lo; i <= hi; i += stride) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 598 | snprintf(num, sizeof(num), "%d", i); |
| 599 | nob = strlen(num); |
| 600 | if (nob + 1 == sizeof(num)) |
| 601 | goto failed; |
| 602 | |
| 603 | if (lnet_expand1tb(&pending, str, sep, sep2, |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 604 | num, nob)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 605 | goto failed; |
| 606 | } |
| 607 | } |
| 608 | |
| 609 | list_splice(&pending, tbs->prev); |
| 610 | return 1; |
| 611 | |
| 612 | failed: |
| 613 | lnet_free_text_bufs(&pending); |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 614 | return -EINVAL; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 615 | } |
| 616 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 617 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 618 | lnet_parse_hops(char *str, unsigned int *hops) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 619 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 620 | int len = strlen(str); |
| 621 | int nob = len; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 622 | |
| 623 | return (sscanf(str, "%u%n", hops, &nob) >= 1 && |
| 624 | nob == len && |
| 625 | *hops > 0 && *hops < 256); |
| 626 | } |
| 627 | |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 628 | #define LNET_PRIORITY_SEPARATOR (':') |
| 629 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 630 | static int |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 631 | lnet_parse_priority(char *str, unsigned int *priority, char **token) |
| 632 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 633 | int nob; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 634 | char *sep; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 635 | int len; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 636 | |
| 637 | sep = strchr(str, LNET_PRIORITY_SEPARATOR); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 638 | if (!sep) { |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 639 | *priority = 0; |
| 640 | return 0; |
| 641 | } |
| 642 | len = strlen(sep + 1); |
| 643 | |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 644 | if ((sscanf((sep + 1), "%u%n", priority, &nob) < 1) || (len != nob)) { |
Sushuruth Sadagopan | 587cb02 | 2016-01-18 02:09:23 -0500 | [diff] [blame] | 645 | /* |
| 646 | * Update the caller's token pointer so it treats the found |
| 647 | * priority as the token to report in the error message. |
| 648 | */ |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 649 | *token += sep - str + 1; |
James Simmons | 58cb2ad | 2016-03-02 17:01:47 -0500 | [diff] [blame] | 650 | return -EINVAL; |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 651 | } |
| 652 | |
| 653 | CDEBUG(D_NET, "gateway %s, priority %d, nob %d\n", str, *priority, nob); |
| 654 | |
| 655 | /* |
| 656 | * Change priority separator to \0 to be able to parse NID |
| 657 | */ |
| 658 | *sep = '\0'; |
| 659 | return 0; |
| 660 | } |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 661 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 662 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 663 | lnet_parse_route(char *str, int *im_a_router) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 664 | { |
| 665 | /* static scratch buffer OK (single threaded) */ |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 666 | static char cmd[LNET_SINGLE_TEXTBUF_NOB]; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 667 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 668 | struct list_head nets; |
| 669 | struct list_head gateways; |
| 670 | struct list_head *tmp1; |
| 671 | struct list_head *tmp2; |
| 672 | __u32 net; |
| 673 | lnet_nid_t nid; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 674 | struct lnet_text_buf *ltb; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 675 | int rc; |
| 676 | char *sep; |
| 677 | char *token = str; |
| 678 | int ntokens = 0; |
| 679 | int myrc = -1; |
Amir Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 680 | __u32 hops; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 681 | int got_hops = 0; |
| 682 | unsigned int priority = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 683 | |
| 684 | INIT_LIST_HEAD(&gateways); |
| 685 | INIT_LIST_HEAD(&nets); |
| 686 | |
| 687 | /* save a copy of the string for error messages */ |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 688 | strncpy(cmd, str, sizeof(cmd)); |
| 689 | cmd[sizeof(cmd) - 1] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 690 | |
| 691 | sep = str; |
| 692 | for (;;) { |
| 693 | /* scan for token start */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 694 | while (isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 695 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 696 | if (!*sep) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 697 | if (ntokens < (got_hops ? 3 : 2)) |
| 698 | goto token_error; |
| 699 | break; |
| 700 | } |
| 701 | |
| 702 | ntokens++; |
| 703 | token = sep++; |
| 704 | |
| 705 | /* scan for token end */ |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 706 | while (*sep && !isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 707 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 708 | if (*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 709 | *sep++ = 0; |
| 710 | |
| 711 | if (ntokens == 1) { |
| 712 | tmp2 = &nets; /* expanding nets */ |
| 713 | } else if (ntokens == 2 && |
| 714 | lnet_parse_hops(token, &hops)) { |
| 715 | got_hops = 1; /* got a hop count */ |
| 716 | continue; |
| 717 | } else { |
| 718 | tmp2 = &gateways; /* expanding gateways */ |
| 719 | } |
| 720 | |
| 721 | ltb = lnet_new_text_buf(strlen(token)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 722 | if (!ltb) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 723 | goto out; |
| 724 | |
| 725 | strcpy(ltb->ltb_text, token); |
| 726 | tmp1 = <b->ltb_list; |
| 727 | list_add_tail(tmp1, tmp2); |
| 728 | |
| 729 | while (tmp1 != tmp2) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 730 | ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 731 | |
| 732 | rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text); |
| 733 | if (rc < 0) |
| 734 | goto token_error; |
| 735 | |
| 736 | tmp1 = tmp1->next; |
| 737 | |
| 738 | if (rc > 0) { /* expanded! */ |
| 739 | list_del(<b->ltb_list); |
| 740 | lnet_free_text_buf(ltb); |
| 741 | continue; |
| 742 | } |
| 743 | |
| 744 | if (ntokens == 1) { |
| 745 | net = libcfs_str2net(ltb->ltb_text); |
| 746 | if (net == LNET_NIDNET(LNET_NID_ANY) || |
| 747 | LNET_NETTYP(net) == LOLND) |
| 748 | goto token_error; |
| 749 | } else { |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 750 | rc = lnet_parse_priority(ltb->ltb_text, |
| 751 | &priority, &token); |
| 752 | if (rc < 0) |
| 753 | goto token_error; |
| 754 | |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 755 | nid = libcfs_str2nid(ltb->ltb_text); |
| 756 | if (nid == LNET_NID_ANY || |
| 757 | LNET_NETTYP(LNET_NIDNET(nid)) == LOLND) |
| 758 | goto token_error; |
| 759 | } |
| 760 | } |
| 761 | } |
| 762 | |
Amir Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 763 | /** |
| 764 | * if there are no hops set then we want to flag this value as |
| 765 | * unset since hops is an optional parameter |
| 766 | */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 767 | if (!got_hops) |
Amir Shehata | b9bbb61 | 2016-03-02 17:01:46 -0500 | [diff] [blame] | 768 | hops = LNET_UNDEFINED_HOPS; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 769 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 770 | LASSERT(!list_empty(&nets)); |
| 771 | LASSERT(!list_empty(&gateways)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 772 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 773 | list_for_each(tmp1, &nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 774 | ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 775 | net = libcfs_str2net(ltb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 776 | LASSERT(net != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 777 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 778 | list_for_each(tmp2, &gateways) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 779 | ltb = list_entry(tmp2, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 780 | nid = libcfs_str2nid(ltb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 781 | LASSERT(nid != LNET_NID_ANY); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 782 | |
| 783 | if (lnet_islocalnid(nid)) { |
| 784 | *im_a_router = 1; |
| 785 | continue; |
| 786 | } |
| 787 | |
Doug Oucharek | e75fb87 | 2013-12-09 22:56:54 +0800 | [diff] [blame] | 788 | rc = lnet_add_route(net, hops, nid, priority); |
Amir Shehata | be8240a | 2016-02-22 17:29:09 -0500 | [diff] [blame] | 789 | if (rc && rc != -EEXIST && rc != -EHOSTUNREACH) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 790 | CERROR("Can't create route to %s via %s\n", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 791 | libcfs_net2str(net), |
| 792 | libcfs_nid2str(nid)); |
| 793 | goto out; |
| 794 | } |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | myrc = 0; |
| 799 | goto out; |
| 800 | |
| 801 | token_error: |
| 802 | lnet_syntax("routes", cmd, (int)(token - str), strlen(token)); |
| 803 | out: |
| 804 | lnet_free_text_bufs(&nets); |
| 805 | lnet_free_text_bufs(&gateways); |
| 806 | return myrc; |
| 807 | } |
| 808 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 809 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 810 | lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router) |
| 811 | { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 812 | struct lnet_text_buf *ltb; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 813 | |
| 814 | while (!list_empty(tbs)) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 815 | ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 816 | |
| 817 | if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) { |
| 818 | lnet_free_text_bufs(tbs); |
| 819 | return -EINVAL; |
| 820 | } |
| 821 | |
| 822 | list_del(<b->ltb_list); |
| 823 | lnet_free_text_buf(ltb); |
| 824 | } |
| 825 | |
| 826 | return 0; |
| 827 | } |
| 828 | |
| 829 | int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 830 | lnet_parse_routes(char *routes, int *im_a_router) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 831 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 832 | struct list_head tbs; |
| 833 | int rc = 0; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 834 | |
| 835 | *im_a_router = 0; |
| 836 | |
| 837 | INIT_LIST_HEAD(&tbs); |
| 838 | |
| 839 | if (lnet_str2tbs_sep(&tbs, routes) < 0) { |
| 840 | CERROR("Error parsing routes\n"); |
| 841 | rc = -EINVAL; |
| 842 | } else { |
| 843 | rc = lnet_parse_route_tbs(&tbs, im_a_router); |
| 844 | } |
| 845 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 846 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 847 | return rc; |
| 848 | } |
| 849 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 850 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 851 | lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip) |
| 852 | { |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 853 | LIST_HEAD(list); |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 854 | int rc; |
| 855 | int i; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 856 | |
| 857 | rc = cfs_ip_addr_parse(token, len, &list); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 858 | if (rc) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 859 | return rc; |
| 860 | |
| 861 | for (rc = i = 0; !rc && i < nip; i++) |
| 862 | rc = cfs_ip_addr_match(ipaddrs[i], &list); |
| 863 | |
James Simmons | a620ec6 | 2015-10-21 21:52:42 -0400 | [diff] [blame] | 864 | cfs_expr_list_free_list(&list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 865 | |
| 866 | return rc; |
| 867 | } |
| 868 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 869 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 870 | lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) |
| 871 | { |
| 872 | static char tokens[LNET_SINGLE_TEXTBUF_NOB]; |
| 873 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 874 | int matched = 0; |
| 875 | int ntokens = 0; |
| 876 | int len; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 877 | char *net = NULL; |
| 878 | char *sep; |
| 879 | char *token; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 880 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 881 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 882 | LASSERT(strlen(net_entry) < sizeof(tokens)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 883 | |
| 884 | /* work on a copy of the string */ |
| 885 | strcpy(tokens, net_entry); |
| 886 | sep = tokens; |
| 887 | for (;;) { |
| 888 | /* scan for token start */ |
Peng Tao | e525a68 | 2014-03-05 21:27:18 +0800 | [diff] [blame] | 889 | while (isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 890 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 891 | if (!*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 892 | break; |
| 893 | |
| 894 | token = sep++; |
| 895 | |
| 896 | /* scan for token end */ |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 897 | while (*sep && !isspace(*sep)) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 898 | sep++; |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 899 | if (*sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 900 | *sep++ = 0; |
| 901 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 902 | if (!ntokens++) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 903 | net = token; |
| 904 | continue; |
| 905 | } |
| 906 | |
| 907 | len = strlen(token); |
| 908 | |
| 909 | rc = lnet_match_network_token(token, len, ipaddrs, nip); |
| 910 | if (rc < 0) { |
| 911 | lnet_syntax("ip2nets", net_entry, |
| 912 | (int)(token - tokens), len); |
| 913 | return rc; |
| 914 | } |
| 915 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 916 | if (rc) |
| 917 | matched |= 1; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 918 | } |
| 919 | |
| 920 | if (!matched) |
| 921 | return 0; |
| 922 | |
| 923 | strcpy(net_entry, net); /* replace with matched net */ |
| 924 | return 1; |
| 925 | } |
| 926 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 927 | static __u32 |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 928 | lnet_netspec2net(char *netspec) |
| 929 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 930 | char *bracket = strchr(netspec, '('); |
| 931 | __u32 net; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 932 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 933 | if (bracket) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 934 | *bracket = 0; |
| 935 | |
| 936 | net = libcfs_str2net(netspec); |
| 937 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 938 | if (bracket) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 939 | *bracket = '('; |
| 940 | |
| 941 | return net; |
| 942 | } |
| 943 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 944 | static int |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 945 | lnet_splitnets(char *source, struct list_head *nets) |
| 946 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 947 | int offset = 0; |
| 948 | int offset2; |
| 949 | int len; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 950 | struct lnet_text_buf *tb; |
| 951 | struct lnet_text_buf *tb2; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 952 | struct list_head *t; |
| 953 | char *sep; |
| 954 | char *bracket; |
| 955 | __u32 net; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 956 | |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 957 | LASSERT(!list_empty(nets)); |
| 958 | LASSERT(nets->next == nets->prev); /* single entry */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 959 | |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 960 | tb = list_entry(nets->next, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 961 | |
| 962 | for (;;) { |
| 963 | sep = strchr(tb->ltb_text, ','); |
| 964 | bracket = strchr(tb->ltb_text, '('); |
| 965 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 966 | if (sep && bracket && bracket < sep) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 967 | /* netspec lists interfaces... */ |
| 968 | |
| 969 | offset2 = offset + (int)(bracket - tb->ltb_text); |
| 970 | len = strlen(bracket); |
| 971 | |
| 972 | bracket = strchr(bracket + 1, ')'); |
| 973 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 974 | if (!bracket || |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 975 | !(bracket[1] == ',' || !bracket[1])) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 976 | lnet_syntax("ip2nets", source, offset2, len); |
| 977 | return -EINVAL; |
| 978 | } |
| 979 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 980 | sep = !bracket[1] ? NULL : bracket + 1; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 981 | } |
| 982 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 983 | if (sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 984 | *sep++ = 0; |
| 985 | |
| 986 | net = lnet_netspec2net(tb->ltb_text); |
| 987 | if (net == LNET_NIDNET(LNET_NID_ANY)) { |
| 988 | lnet_syntax("ip2nets", source, offset, |
| 989 | strlen(tb->ltb_text)); |
| 990 | return -EINVAL; |
| 991 | } |
| 992 | |
| 993 | list_for_each(t, nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 994 | tb2 = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 995 | |
| 996 | if (tb2 == tb) |
| 997 | continue; |
| 998 | |
| 999 | if (net == lnet_netspec2net(tb2->ltb_text)) { |
| 1000 | /* duplicate network */ |
| 1001 | lnet_syntax("ip2nets", source, offset, |
| 1002 | strlen(tb->ltb_text)); |
| 1003 | return -EINVAL; |
| 1004 | } |
| 1005 | } |
| 1006 | |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1007 | if (!sep) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1008 | return 0; |
| 1009 | |
| 1010 | offset += (int)(sep - tb->ltb_text); |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1011 | len = strlen(sep); |
| 1012 | tb2 = lnet_new_text_buf(len); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1013 | if (!tb2) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1014 | return -ENOMEM; |
| 1015 | |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1016 | strncpy(tb2->ltb_text, sep, len); |
| 1017 | tb2->ltb_text[len] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1018 | list_add_tail(&tb2->ltb_list, nets); |
| 1019 | |
| 1020 | tb = tb2; |
| 1021 | } |
| 1022 | } |
| 1023 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 1024 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1025 | lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1026 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1027 | static char networks[LNET_SINGLE_TEXTBUF_NOB]; |
| 1028 | static char source[LNET_SINGLE_TEXTBUF_NOB]; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1029 | |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1030 | struct list_head raw_entries; |
| 1031 | struct list_head matched_nets; |
| 1032 | struct list_head current_nets; |
| 1033 | struct list_head *t; |
| 1034 | struct list_head *t2; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1035 | struct lnet_text_buf *tb; |
Bhaktipriya Shridhar | cb734cf | 2016-03-12 01:33:03 +0530 | [diff] [blame] | 1036 | struct lnet_text_buf *temp; |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1037 | struct lnet_text_buf *tb2; |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1038 | __u32 net1; |
| 1039 | __u32 net2; |
| 1040 | int len; |
| 1041 | int count; |
| 1042 | int dup; |
| 1043 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1044 | |
| 1045 | INIT_LIST_HEAD(&raw_entries); |
| 1046 | if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) { |
| 1047 | CERROR("Error parsing ip2nets\n"); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1048 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1049 | return -EINVAL; |
| 1050 | } |
| 1051 | |
| 1052 | INIT_LIST_HEAD(&matched_nets); |
| 1053 | INIT_LIST_HEAD(¤t_nets); |
| 1054 | networks[0] = 0; |
| 1055 | count = 0; |
| 1056 | len = 0; |
| 1057 | rc = 0; |
| 1058 | |
Bhaktipriya Shridhar | cb734cf | 2016-03-12 01:33:03 +0530 | [diff] [blame] | 1059 | list_for_each_entry_safe(tb, temp, &raw_entries, ltb_list) { |
Dmitry Eremin | 9563fe8 | 2015-11-04 13:40:00 -0500 | [diff] [blame] | 1060 | strncpy(source, tb->ltb_text, sizeof(source)); |
James Simmons | 51078e2 | 2016-02-12 12:06:04 -0500 | [diff] [blame] | 1061 | source[sizeof(source) - 1] = '\0'; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1062 | |
| 1063 | /* replace ltb_text with the network(s) add on match */ |
| 1064 | rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); |
| 1065 | if (rc < 0) |
| 1066 | break; |
| 1067 | |
| 1068 | list_del(&tb->ltb_list); |
| 1069 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1070 | if (!rc) { /* no match */ |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1071 | lnet_free_text_buf(tb); |
| 1072 | continue; |
| 1073 | } |
| 1074 | |
| 1075 | /* split into separate networks */ |
| 1076 | INIT_LIST_HEAD(¤t_nets); |
| 1077 | list_add(&tb->ltb_list, ¤t_nets); |
| 1078 | rc = lnet_splitnets(source, ¤t_nets); |
| 1079 | if (rc < 0) |
| 1080 | break; |
| 1081 | |
| 1082 | dup = 0; |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1083 | list_for_each(t, ¤t_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1084 | tb = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1085 | net1 = lnet_netspec2net(tb->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1086 | LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1087 | |
| 1088 | list_for_each(t2, &matched_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1089 | tb2 = list_entry(t2, struct lnet_text_buf, |
| 1090 | ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1091 | net2 = lnet_netspec2net(tb2->ltb_text); |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1092 | LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1093 | |
| 1094 | if (net1 == net2) { |
| 1095 | dup = 1; |
| 1096 | break; |
| 1097 | } |
| 1098 | } |
| 1099 | |
| 1100 | if (dup) |
| 1101 | break; |
| 1102 | } |
| 1103 | |
| 1104 | if (dup) { |
| 1105 | lnet_free_text_bufs(¤t_nets); |
| 1106 | continue; |
| 1107 | } |
| 1108 | |
| 1109 | list_for_each_safe(t, t2, ¤t_nets) { |
James Simmons | ddbc66a | 2016-02-12 12:05:59 -0500 | [diff] [blame] | 1110 | tb = list_entry(t, struct lnet_text_buf, ltb_list); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1111 | |
| 1112 | list_del(&tb->ltb_list); |
| 1113 | list_add_tail(&tb->ltb_list, &matched_nets); |
| 1114 | |
| 1115 | len += snprintf(networks + len, sizeof(networks) - len, |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1116 | "%s%s", !len ? "" : ",", |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1117 | tb->ltb_text); |
| 1118 | |
| 1119 | if (len >= sizeof(networks)) { |
| 1120 | CERROR("Too many matched networks\n"); |
| 1121 | rc = -E2BIG; |
| 1122 | goto out; |
| 1123 | } |
| 1124 | } |
| 1125 | |
| 1126 | count++; |
| 1127 | } |
| 1128 | |
| 1129 | out: |
| 1130 | lnet_free_text_bufs(&raw_entries); |
| 1131 | lnet_free_text_bufs(&matched_nets); |
| 1132 | lnet_free_text_bufs(¤t_nets); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1133 | LASSERT(!lnet_tbnob); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1134 | |
| 1135 | if (rc < 0) |
| 1136 | return rc; |
| 1137 | |
| 1138 | *networksp = networks; |
| 1139 | return count; |
| 1140 | } |
| 1141 | |
Benedict Boerger | 714340d | 2014-08-08 18:26:22 +0200 | [diff] [blame] | 1142 | static int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1143 | lnet_ipaddr_enumerate(__u32 **ipaddrsp) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1144 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1145 | int up; |
| 1146 | __u32 netmask; |
| 1147 | __u32 *ipaddrs; |
| 1148 | __u32 *ipaddrs2; |
| 1149 | int nip; |
| 1150 | char **ifnames; |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1151 | int nif = lnet_ipif_enumerate(&ifnames); |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1152 | int i; |
| 1153 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1154 | |
| 1155 | if (nif <= 0) |
| 1156 | return nif; |
| 1157 | |
| 1158 | LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1159 | if (!ipaddrs) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1160 | CERROR("Can't allocate ipaddrs[%d]\n", nif); |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1161 | lnet_ipif_free_enumeration(ifnames, nif); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1162 | return -ENOMEM; |
| 1163 | } |
| 1164 | |
| 1165 | for (i = nip = 0; i < nif; i++) { |
| 1166 | if (!strcmp(ifnames[i], "lo")) |
| 1167 | continue; |
| 1168 | |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1169 | rc = lnet_ipif_query(ifnames[i], &up, &ipaddrs[nip], &netmask); |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1170 | if (rc) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1171 | CWARN("Can't query interface %s: %d\n", |
| 1172 | ifnames[i], rc); |
| 1173 | continue; |
| 1174 | } |
| 1175 | |
| 1176 | if (!up) { |
| 1177 | CWARN("Ignoring interface %s: it's down\n", |
| 1178 | ifnames[i]); |
| 1179 | continue; |
| 1180 | } |
| 1181 | |
| 1182 | nip++; |
| 1183 | } |
| 1184 | |
James Simmons | 1ad6a73 | 2015-06-08 22:27:10 -0400 | [diff] [blame] | 1185 | lnet_ipif_free_enumeration(ifnames, nif); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1186 | |
| 1187 | if (nip == nif) { |
| 1188 | *ipaddrsp = ipaddrs; |
| 1189 | } else { |
| 1190 | if (nip > 0) { |
| 1191 | LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2)); |
James Simmons | 06ace26 | 2016-02-12 12:06:08 -0500 | [diff] [blame] | 1192 | if (!ipaddrs2) { |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1193 | CERROR("Can't allocate ipaddrs[%d]\n", nip); |
| 1194 | nip = -ENOMEM; |
| 1195 | } else { |
| 1196 | memcpy(ipaddrs2, ipaddrs, |
| 1197 | nip * sizeof(*ipaddrs)); |
| 1198 | *ipaddrsp = ipaddrs2; |
| 1199 | rc = nip; |
| 1200 | } |
| 1201 | } |
Shivani Bhardwaj | cfa3811 | 2015-10-29 12:28:31 +0530 | [diff] [blame] | 1202 | LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1203 | } |
| 1204 | return nip; |
| 1205 | } |
| 1206 | |
| 1207 | int |
Rashika Kheria | 24edbe4 | 2013-10-26 00:21:24 +0530 | [diff] [blame] | 1208 | lnet_parse_ip2nets(char **networksp, char *ip2nets) |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1209 | { |
Mike Shuey | 7e7ab09 | 2015-05-19 10:14:32 -0400 | [diff] [blame] | 1210 | __u32 *ipaddrs = NULL; |
| 1211 | int nip = lnet_ipaddr_enumerate(&ipaddrs); |
| 1212 | int rc; |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1213 | |
| 1214 | if (nip < 0) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1215 | LCONSOLE_ERROR_MSG(0x117, |
| 1216 | "Error %d enumerating local IP interfaces for ip2nets to match\n", |
| 1217 | nip); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1218 | return nip; |
| 1219 | } |
| 1220 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1221 | if (!nip) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1222 | LCONSOLE_ERROR_MSG(0x118, |
| 1223 | "No local IP interfaces for ip2nets to match\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1224 | return -ENOENT; |
| 1225 | } |
| 1226 | |
| 1227 | rc = lnet_match_networks(networksp, ip2nets, ipaddrs, nip); |
Shivani Bhardwaj | cfa3811 | 2015-10-29 12:28:31 +0530 | [diff] [blame] | 1228 | LIBCFS_FREE(ipaddrs, nip * sizeof(*ipaddrs)); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1229 | |
| 1230 | if (rc < 0) { |
| 1231 | LCONSOLE_ERROR_MSG(0x119, "Error %d parsing ip2nets\n", rc); |
| 1232 | return rc; |
| 1233 | } |
| 1234 | |
James Simmons | 5fd8833 | 2016-02-12 12:06:09 -0500 | [diff] [blame] | 1235 | if (!rc) { |
Rashika Kheria | e46b3a0 | 2013-10-26 00:22:54 +0530 | [diff] [blame] | 1236 | LCONSOLE_ERROR_MSG(0x11a, |
| 1237 | "ip2nets does not match any local IP interfaces\n"); |
Peng Tao | d7e09d0 | 2013-05-02 16:46:55 +0800 | [diff] [blame] | 1238 | return -ENOENT; |
| 1239 | } |
| 1240 | |
| 1241 | return 0; |
| 1242 | } |