Blame view
net/smc/smc_pnet.c
29.2 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
6812baabf smc: establish pn... |
2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * Shared Memory Communications over RDMA (SMC-R) and RoCE * * Generic netlink support functions to configure an SMC-R PNET table * * Copyright IBM Corp. 2016 * * Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com> */ #include <linux/module.h> #include <linux/list.h> #include <linux/ctype.h> |
92f3cb0e1 net/smc: fix slee... |
15 |
#include <linux/mutex.h> |
6812baabf smc: establish pn... |
16 17 18 19 20 21 22 |
#include <net/netlink.h> #include <net/genetlink.h> #include <uapi/linux/if.h> #include <uapi/linux/smc.h> #include <rdma/ib_verbs.h> |
64e28b52c net/smc: add pnet... |
23 24 |
#include <net/netns/generic.h> #include "smc_netns.h" |
6812baabf smc: establish pn... |
25 26 |
#include "smc_pnet.h" #include "smc_ib.h" |
1619f7705 net/smc: add pnet... |
27 |
#include "smc_ism.h" |
bc36d2fc9 net/smc: consolid... |
28 |
#include "smc_core.h" |
6812baabf smc: establish pn... |
29 |
|
e888a2e83 net/smc: introduc... |
30 |
static struct net_device *__pnet_find_base_ndev(struct net_device *ndev); |
890a2cb4a net/smc: rework p... |
31 |
static struct net_device *pnet_find_base_ndev(struct net_device *ndev); |
09d0310f0 net/smc: mark smc... |
32 |
static const struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = { |
6812baabf smc: establish pn... |
33 34 |
[SMC_PNETID_NAME] = { .type = NLA_NUL_STRING, |
ca8dc1334 net/smc: allow 16... |
35 |
.len = SMC_MAX_PNETID_LEN |
6812baabf smc: establish pn... |
36 37 38 39 40 41 42 43 44 45 46 47 48 |
}, [SMC_PNETID_ETHNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, [SMC_PNETID_IBNAME] = { .type = NLA_NUL_STRING, .len = IB_DEVICE_NAME_MAX - 1 }, [SMC_PNETID_IBPORT] = { .type = NLA_U8 } }; static struct genl_family smc_pnet_nl_family; |
fdff704dc net/smc: rework p... |
49 50 51 |
enum smc_pnet_nametype { SMC_PNET_ETH = 1, SMC_PNET_IB = 2, |
6812baabf smc: establish pn... |
52 |
}; |
890a2cb4a net/smc: rework p... |
53 54 55 56 |
/* pnet entry stored in pnet table */ struct smc_pnetentry { struct list_head list; char pnet_name[SMC_MAX_PNETID_LEN + 1]; |
fdff704dc net/smc: rework p... |
57 58 59 60 61 62 63 64 65 66 67 |
enum smc_pnet_nametype type; union { struct { char eth_name[IFNAMSIZ + 1]; struct net_device *ndev; }; struct { char ib_name[IB_DEVICE_NAME_MAX + 1]; u8 ib_port; }; }; |
890a2cb4a net/smc: rework p... |
68 |
}; |
6812baabf smc: establish pn... |
69 |
|
a304e29a2 net/smc: remove c... |
70 |
/* Check if the pnetid is set */ |
d70bf4f7a net/smc: determin... |
71 |
bool smc_pnet_is_pnetid_set(u8 *pnetid) |
a304e29a2 net/smc: remove c... |
72 73 74 75 76 |
{ if (pnetid[0] == 0 || pnetid[0] == _S) return false; return true; } |
890a2cb4a net/smc: rework p... |
77 78 |
/* Check if two given pnetids match */ static bool smc_pnet_match(u8 *pnetid1, u8 *pnetid2) |
6812baabf smc: establish pn... |
79 |
{ |
890a2cb4a net/smc: rework p... |
80 |
int i; |
6812baabf smc: establish pn... |
81 |
|
890a2cb4a net/smc: rework p... |
82 |
for (i = 0; i < SMC_MAX_PNETID_LEN; i++) { |
a304e29a2 net/smc: remove c... |
83 84 |
if ((pnetid1[i] == 0 || pnetid1[i] == _S) && (pnetid2[i] == 0 || pnetid2[i] == _S)) |
6812baabf smc: establish pn... |
85 |
break; |
890a2cb4a net/smc: rework p... |
86 87 |
if (pnetid1[i] != pnetid2[i]) return false; |
6812baabf smc: establish pn... |
88 |
} |
890a2cb4a net/smc: rework p... |
89 |
return true; |
6812baabf smc: establish pn... |
90 91 92 93 |
} /* Remove a pnetid from the pnet table. */ |
64e28b52c net/smc: add pnet... |
94 |
static int smc_pnet_remove_by_pnetid(struct net *net, char *pnet_name) |
6812baabf smc: establish pn... |
95 96 |
{ struct smc_pnetentry *pnetelem, *tmp_pe; |
64e28b52c net/smc: add pnet... |
97 |
struct smc_pnettable *pnettable; |
890a2cb4a net/smc: rework p... |
98 |
struct smc_ib_device *ibdev; |
f3d74b224 net/smc: add smcd... |
99 |
struct smcd_dev *smcd_dev; |
64e28b52c net/smc: add pnet... |
100 |
struct smc_net *sn; |
6812baabf smc: establish pn... |
101 |
int rc = -ENOENT; |
890a2cb4a net/smc: rework p... |
102 |
int ibport; |
6812baabf smc: establish pn... |
103 |
|
64e28b52c net/smc: add pnet... |
104 105 106 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; |
fdff704dc net/smc: rework p... |
107 |
/* remove table entry */ |
64e28b52c net/smc: add pnet... |
108 109 |
write_lock(&pnettable->lock); list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, |
6812baabf smc: establish pn... |
110 |
list) { |
890a2cb4a net/smc: rework p... |
111 112 |
if (!pnet_name || smc_pnet_match(pnetelem->pnet_name, pnet_name)) { |
6812baabf smc: establish pn... |
113 |
list_del(&pnetelem->list); |
0a99be434 net/smc: log impo... |
114 |
if (pnetelem->type == SMC_PNET_ETH && pnetelem->ndev) { |
fdff704dc net/smc: rework p... |
115 |
dev_put(pnetelem->ndev); |
0a99be434 net/smc: log impo... |
116 117 118 119 120 121 122 |
pr_warn_ratelimited("smc: net device %s " "erased user defined " "pnetid %.16s ", pnetelem->eth_name, pnetelem->pnet_name); } |
6812baabf smc: establish pn... |
123 124 |
kfree(pnetelem); rc = 0; |
6812baabf smc: establish pn... |
125 126 |
} } |
64e28b52c net/smc: add pnet... |
127 128 129 130 131 |
write_unlock(&pnettable->lock); /* if this is not the initial namespace, stop here */ if (net != &init_net) return rc; |
890a2cb4a net/smc: rework p... |
132 |
/* remove ib devices */ |
92f3cb0e1 net/smc: fix slee... |
133 |
mutex_lock(&smc_ib_devices.mutex); |
890a2cb4a net/smc: rework p... |
134 135 136 137 138 139 |
list_for_each_entry(ibdev, &smc_ib_devices.list, list) { for (ibport = 0; ibport < SMC_MAX_PORTS; ibport++) { if (ibdev->pnetid_by_user[ibport] && (!pnet_name || smc_pnet_match(pnet_name, ibdev->pnetid[ibport]))) { |
0a99be434 net/smc: log impo... |
140 141 142 143 144 145 146 |
pr_warn_ratelimited("smc: ib device %s ibport " "%d erased user defined " "pnetid %.16s ", ibdev->ibdev->name, ibport + 1, ibdev->pnetid[ibport]); |
890a2cb4a net/smc: rework p... |
147 148 149 150 151 152 153 |
memset(ibdev->pnetid[ibport], 0, SMC_MAX_PNETID_LEN); ibdev->pnetid_by_user[ibport] = false; rc = 0; } } } |
92f3cb0e1 net/smc: fix slee... |
154 |
mutex_unlock(&smc_ib_devices.mutex); |
f3d74b224 net/smc: add smcd... |
155 |
/* remove smcd devices */ |
82087c033 net/smc: switch s... |
156 |
mutex_lock(&smcd_dev_list.mutex); |
f3d74b224 net/smc: add smcd... |
157 158 159 160 |
list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) { if (smcd_dev->pnetid_by_user && (!pnet_name || smc_pnet_match(pnet_name, smcd_dev->pnetid))) { |
0a99be434 net/smc: log impo... |
161 162 163 164 165 |
pr_warn_ratelimited("smc: smcd device %s " "erased user defined pnetid " "%.16s ", dev_name(&smcd_dev->dev), smcd_dev->pnetid); |
f3d74b224 net/smc: add smcd... |
166 167 168 169 170 |
memset(smcd_dev->pnetid, 0, SMC_MAX_PNETID_LEN); smcd_dev->pnetid_by_user = false; rc = 0; } } |
82087c033 net/smc: switch s... |
171 |
mutex_unlock(&smcd_dev_list.mutex); |
6812baabf smc: establish pn... |
172 173 |
return rc; } |
fdff704dc net/smc: rework p... |
174 |
/* Add the reference to a given network device to the pnet table. |
6812baabf smc: establish pn... |
175 |
*/ |
fdff704dc net/smc: rework p... |
176 |
static int smc_pnet_add_by_ndev(struct net_device *ndev) |
6812baabf smc: establish pn... |
177 178 |
{ struct smc_pnetentry *pnetelem, *tmp_pe; |
64e28b52c net/smc: add pnet... |
179 180 181 |
struct smc_pnettable *pnettable; struct net *net = dev_net(ndev); struct smc_net *sn; |
6812baabf smc: establish pn... |
182 |
int rc = -ENOENT; |
64e28b52c net/smc: add pnet... |
183 184 185 186 187 188 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; write_lock(&pnettable->lock); list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) { |
fdff704dc net/smc: rework p... |
189 190 191 192 |
if (pnetelem->type == SMC_PNET_ETH && !pnetelem->ndev && !strncmp(pnetelem->eth_name, ndev->name, IFNAMSIZ)) { dev_hold(ndev); pnetelem->ndev = ndev; |
6812baabf smc: establish pn... |
193 |
rc = 0; |
0a99be434 net/smc: log impo... |
194 195 196 197 198 |
pr_warn_ratelimited("smc: adding net device %s with " "user defined pnetid %.16s ", pnetelem->eth_name, pnetelem->pnet_name); |
6812baabf smc: establish pn... |
199 200 201 |
break; } } |
64e28b52c net/smc: add pnet... |
202 |
write_unlock(&pnettable->lock); |
6812baabf smc: establish pn... |
203 204 |
return rc; } |
fdff704dc net/smc: rework p... |
205 |
/* Remove the reference to a given network device from the pnet table. |
6812baabf smc: establish pn... |
206 |
*/ |
fdff704dc net/smc: rework p... |
207 |
static int smc_pnet_remove_by_ndev(struct net_device *ndev) |
6812baabf smc: establish pn... |
208 |
{ |
fdff704dc net/smc: rework p... |
209 210 211 212 213 |
struct smc_pnetentry *pnetelem, *tmp_pe; struct smc_pnettable *pnettable; struct net *net = dev_net(ndev); struct smc_net *sn; int rc = -ENOENT; |
890a2cb4a net/smc: rework p... |
214 |
|
fdff704dc net/smc: rework p... |
215 216 217 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; |
f3d74b224 net/smc: add smcd... |
218 |
|
fdff704dc net/smc: rework p... |
219 220 221 222 223 224 |
write_lock(&pnettable->lock); list_for_each_entry_safe(pnetelem, tmp_pe, &pnettable->pnetlist, list) { if (pnetelem->type == SMC_PNET_ETH && pnetelem->ndev == ndev) { dev_put(pnetelem->ndev); pnetelem->ndev = NULL; rc = 0; |
0a99be434 net/smc: log impo... |
225 226 227 228 229 |
pr_warn_ratelimited("smc: removing net device %s with " "user defined pnetid %.16s ", pnetelem->eth_name, pnetelem->pnet_name); |
fdff704dc net/smc: rework p... |
230 |
break; |
f3d74b224 net/smc: add smcd... |
231 |
} |
f3d74b224 net/smc: add smcd... |
232 |
} |
fdff704dc net/smc: rework p... |
233 234 235 |
write_unlock(&pnettable->lock); return rc; } |
6812baabf smc: establish pn... |
236 |
|
fdff704dc net/smc: rework p... |
237 238 239 240 241 |
/* Apply pnetid to ib device when no pnetid is set. */ static bool smc_pnet_apply_ib(struct smc_ib_device *ib_dev, u8 ib_port, char *pnet_name) { |
fdff704dc net/smc: rework p... |
242 |
bool applied = false; |
890a2cb4a net/smc: rework p... |
243 |
|
92f3cb0e1 net/smc: fix slee... |
244 |
mutex_lock(&smc_ib_devices.mutex); |
a304e29a2 net/smc: remove c... |
245 |
if (!smc_pnet_is_pnetid_set(ib_dev->pnetid[ib_port - 1])) { |
fdff704dc net/smc: rework p... |
246 247 248 249 250 |
memcpy(ib_dev->pnetid[ib_port - 1], pnet_name, SMC_MAX_PNETID_LEN); ib_dev->pnetid_by_user[ib_port - 1] = true; applied = true; } |
92f3cb0e1 net/smc: fix slee... |
251 |
mutex_unlock(&smc_ib_devices.mutex); |
fdff704dc net/smc: rework p... |
252 253 |
return applied; } |
890a2cb4a net/smc: rework p... |
254 |
|
fdff704dc net/smc: rework p... |
255 256 257 258 |
/* Apply pnetid to smcd device when no pnetid is set. */ static bool smc_pnet_apply_smcd(struct smcd_dev *smcd_dev, char *pnet_name) { |
fdff704dc net/smc: rework p... |
259 |
bool applied = false; |
6812baabf smc: establish pn... |
260 |
|
82087c033 net/smc: switch s... |
261 |
mutex_lock(&smcd_dev_list.mutex); |
a304e29a2 net/smc: remove c... |
262 |
if (!smc_pnet_is_pnetid_set(smcd_dev->pnetid)) { |
fdff704dc net/smc: rework p... |
263 264 265 |
memcpy(smcd_dev->pnetid, pnet_name, SMC_MAX_PNETID_LEN); smcd_dev->pnetid_by_user = true; applied = true; |
890a2cb4a net/smc: rework p... |
266 |
} |
82087c033 net/smc: switch s... |
267 |
mutex_unlock(&smcd_dev_list.mutex); |
fdff704dc net/smc: rework p... |
268 |
return applied; |
6812baabf smc: establish pn... |
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
} /* The limit for pnetid is 16 characters. * Valid characters should be (single-byte character set) a-z, A-Z, 0-9. * Lower case letters are converted to upper case. * Interior blanks should not be used. */ static bool smc_pnetid_valid(const char *pnet_name, char *pnetid) { char *bf = skip_spaces(pnet_name); size_t len = strlen(bf); char *end = bf + len; if (!len) return false; while (--end >= bf && isspace(*end)) ; |
0afff91c6 net/smc: add pnet... |
286 |
if (end - bf >= SMC_MAX_PNETID_LEN) |
6812baabf smc: establish pn... |
287 288 289 290 291 292 293 294 295 296 297 298 |
return false; while (bf <= end) { if (!isalnum(*bf)) return false; *pnetid++ = islower(*bf) ? toupper(*bf) : *bf; bf++; } *pnetid = '\0'; return true; } /* Find an infiniband device by a given name. The device might not exist. */ |
249633a44 net/smc: remove u... |
299 |
static struct smc_ib_device *smc_pnet_find_ib(char *ib_name) |
6812baabf smc: establish pn... |
300 301 |
{ struct smc_ib_device *ibdev; |
92f3cb0e1 net/smc: fix slee... |
302 |
mutex_lock(&smc_ib_devices.mutex); |
6812baabf smc: establish pn... |
303 304 |
list_for_each_entry(ibdev, &smc_ib_devices.list, list) { if (!strncmp(ibdev->ibdev->name, ib_name, |
af5f60c7e net/smc: allow PC... |
305 306 307 |
sizeof(ibdev->ibdev->name)) || !strncmp(dev_name(ibdev->ibdev->dev.parent), ib_name, IB_DEVICE_NAME_MAX - 1)) { |
6812baabf smc: establish pn... |
308 309 310 311 312 |
goto out; } } ibdev = NULL; out: |
92f3cb0e1 net/smc: fix slee... |
313 |
mutex_unlock(&smc_ib_devices.mutex); |
6812baabf smc: establish pn... |
314 315 |
return ibdev; } |
f3d74b224 net/smc: add smcd... |
316 317 318 319 |
/* Find an smcd device by a given name. The device might not exist. */ static struct smcd_dev *smc_pnet_find_smcd(char *smcd_name) { struct smcd_dev *smcd_dev; |
82087c033 net/smc: switch s... |
320 |
mutex_lock(&smcd_dev_list.mutex); |
f3d74b224 net/smc: add smcd... |
321 322 323 324 325 326 327 |
list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) { if (!strncmp(dev_name(&smcd_dev->dev), smcd_name, IB_DEVICE_NAME_MAX - 1)) goto out; } smcd_dev = NULL; out: |
82087c033 net/smc: switch s... |
328 |
mutex_unlock(&smcd_dev_list.mutex); |
f3d74b224 net/smc: add smcd... |
329 330 |
return smcd_dev; } |
fdff704dc net/smc: rework p... |
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net, char *eth_name, char *pnet_name) { struct smc_pnetentry *tmp_pe, *new_pe; struct net_device *ndev, *base_ndev; u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; bool new_netdev; int rc; /* check if (base) netdev already has a pnetid. If there is one, we do * not want to add a pnet table entry */ rc = -EEXIST; ndev = dev_get_by_name(net, eth_name); /* dev_hold() */ if (ndev) { base_ndev = pnet_find_base_ndev(ndev); if (!smc_pnetid_by_dev_port(base_ndev->dev.parent, base_ndev->dev_port, ndev_pnetid)) goto out_put; } /* add a new netdev entry to the pnet table if there isn't one */ rc = -ENOMEM; new_pe = kzalloc(sizeof(*new_pe), GFP_KERNEL); if (!new_pe) goto out_put; new_pe->type = SMC_PNET_ETH; memcpy(new_pe->pnet_name, pnet_name, SMC_MAX_PNETID_LEN); strncpy(new_pe->eth_name, eth_name, IFNAMSIZ); new_pe->ndev = ndev; rc = -EEXIST; new_netdev = true; write_lock(&pnettable->lock); list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { if (tmp_pe->type == SMC_PNET_ETH && !strncmp(tmp_pe->eth_name, eth_name, IFNAMSIZ)) { new_netdev = false; break; } } if (new_netdev) { list_add_tail(&new_pe->list, &pnettable->pnetlist); write_unlock(&pnettable->lock); } else { write_unlock(&pnettable->lock); kfree(new_pe); goto out_put; } |
0a99be434 net/smc: log impo... |
380 381 382 383 384 |
if (ndev) pr_warn_ratelimited("smc: net device %s " "applied user defined pnetid %.16s ", new_pe->eth_name, new_pe->pnet_name); |
fdff704dc net/smc: rework p... |
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
return 0; out_put: if (ndev) dev_put(ndev); return rc; } static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name, u8 ib_port, char *pnet_name) { struct smc_pnetentry *tmp_pe, *new_pe; struct smc_ib_device *ib_dev; bool smcddev_applied = true; bool ibdev_applied = true; struct smcd_dev *smcd_dev; bool new_ibdev; /* try to apply the pnetid to active devices */ ib_dev = smc_pnet_find_ib(ib_name); |
0a99be434 net/smc: log impo... |
405 |
if (ib_dev) { |
fdff704dc net/smc: rework p... |
406 |
ibdev_applied = smc_pnet_apply_ib(ib_dev, ib_port, pnet_name); |
0a99be434 net/smc: log impo... |
407 408 409 410 411 412 413 414 |
if (ibdev_applied) pr_warn_ratelimited("smc: ib device %s ibport %d " "applied user defined pnetid " "%.16s ", ib_dev->ibdev->name, ib_port, ib_dev->pnetid[ib_port - 1]); } |
fdff704dc net/smc: rework p... |
415 |
smcd_dev = smc_pnet_find_smcd(ib_name); |
0a99be434 net/smc: log impo... |
416 |
if (smcd_dev) { |
fdff704dc net/smc: rework p... |
417 |
smcddev_applied = smc_pnet_apply_smcd(smcd_dev, pnet_name); |
0a99be434 net/smc: log impo... |
418 419 420 421 422 423 424 |
if (smcddev_applied) pr_warn_ratelimited("smc: smcd device %s " "applied user defined pnetid " "%.16s ", dev_name(&smcd_dev->dev), smcd_dev->pnetid); } |
fdff704dc net/smc: rework p... |
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 |
/* Apply fails when a device has a hardware-defined pnetid set, do not * add a pnet table entry in that case. */ if (!ibdev_applied || !smcddev_applied) return -EEXIST; /* add a new ib entry to the pnet table if there isn't one */ new_pe = kzalloc(sizeof(*new_pe), GFP_KERNEL); if (!new_pe) return -ENOMEM; new_pe->type = SMC_PNET_IB; memcpy(new_pe->pnet_name, pnet_name, SMC_MAX_PNETID_LEN); strncpy(new_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX); new_pe->ib_port = ib_port; new_ibdev = true; write_lock(&pnettable->lock); list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { if (tmp_pe->type == SMC_PNET_IB && !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) { new_ibdev = false; break; } } if (new_ibdev) { list_add_tail(&new_pe->list, &pnettable->pnetlist); write_unlock(&pnettable->lock); } else { write_unlock(&pnettable->lock); kfree(new_pe); } return (new_ibdev) ? 0 : -EEXIST; } /* Append a pnetid to the end of the pnet table if not already on this list. |
6812baabf smc: establish pn... |
460 |
*/ |
fdff704dc net/smc: rework p... |
461 |
static int smc_pnet_enter(struct net *net, struct nlattr *tb[]) |
6812baabf smc: establish pn... |
462 |
{ |
fdff704dc net/smc: rework p... |
463 464 465 466 467 468 469 |
char pnet_name[SMC_MAX_PNETID_LEN + 1]; struct smc_pnettable *pnettable; bool new_netdev = false; bool new_ibdev = false; struct smc_net *sn; u8 ibport = 1; char *string; |
d49baa7e1 net/smc: check fo... |
470 |
int rc; |
6812baabf smc: establish pn... |
471 |
|
fdff704dc net/smc: rework p... |
472 473 474 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; |
d49baa7e1 net/smc: check fo... |
475 476 477 478 479 |
rc = -EINVAL; if (!tb[SMC_PNETID_NAME]) goto error; string = (char *)nla_data(tb[SMC_PNETID_NAME]); |
fdff704dc net/smc: rework p... |
480 |
if (!smc_pnetid_valid(string, pnet_name)) |
d49baa7e1 net/smc: check fo... |
481 |
goto error; |
890a2cb4a net/smc: rework p... |
482 483 |
if (tb[SMC_PNETID_ETHNAME]) { string = (char *)nla_data(tb[SMC_PNETID_ETHNAME]); |
fdff704dc net/smc: rework p... |
484 485 486 487 |
rc = smc_pnet_add_eth(pnettable, net, string, pnet_name); if (!rc) new_netdev = true; else if (rc != -EEXIST) |
890a2cb4a net/smc: rework p... |
488 489 |
goto error; } |
d49baa7e1 net/smc: check fo... |
490 |
|
64e28b52c net/smc: add pnet... |
491 492 |
/* if this is not the initial namespace, stop here */ if (net != &init_net) |
fdff704dc net/smc: rework p... |
493 |
return new_netdev ? 0 : -EEXIST; |
64e28b52c net/smc: add pnet... |
494 |
|
d49baa7e1 net/smc: check fo... |
495 |
rc = -EINVAL; |
890a2cb4a net/smc: rework p... |
496 |
if (tb[SMC_PNETID_IBNAME]) { |
fdff704dc net/smc: rework p... |
497 498 499 500 501 |
string = (char *)nla_data(tb[SMC_PNETID_IBNAME]); string = strim(string); if (tb[SMC_PNETID_IBPORT]) { ibport = nla_get_u8(tb[SMC_PNETID_IBPORT]); if (ibport < 1 || ibport > SMC_MAX_PORTS) |
890a2cb4a net/smc: rework p... |
502 503 |
goto error; } |
fdff704dc net/smc: rework p... |
504 505 506 507 508 |
rc = smc_pnet_add_ib(pnettable, string, ibport, pnet_name); if (!rc) new_ibdev = true; else if (rc != -EEXIST) goto error; |
890a2cb4a net/smc: rework p... |
509 |
} |
fdff704dc net/smc: rework p... |
510 |
return (new_netdev || new_ibdev) ? 0 : -EEXIST; |
6812baabf smc: establish pn... |
511 512 |
error: |
6812baabf smc: establish pn... |
513 514 515 516 |
return rc; } /* Convert an smc_pnetentry to a netlink attribute sequence */ |
890a2cb4a net/smc: rework p... |
517 |
static int smc_pnet_set_nla(struct sk_buff *msg, |
fdff704dc net/smc: rework p... |
518 |
struct smc_pnetentry *pnetelem) |
6812baabf smc: establish pn... |
519 |
{ |
890a2cb4a net/smc: rework p... |
520 |
if (nla_put_string(msg, SMC_PNETID_NAME, pnetelem->pnet_name)) |
6812baabf smc: establish pn... |
521 |
return -1; |
fdff704dc net/smc: rework p... |
522 |
if (pnetelem->type == SMC_PNET_ETH) { |
890a2cb4a net/smc: rework p... |
523 |
if (nla_put_string(msg, SMC_PNETID_ETHNAME, |
fdff704dc net/smc: rework p... |
524 |
pnetelem->eth_name)) |
890a2cb4a net/smc: rework p... |
525 526 527 528 |
return -1; } else { if (nla_put_string(msg, SMC_PNETID_ETHNAME, "n/a")) return -1; |
6812baabf smc: establish pn... |
529 |
} |
fdff704dc net/smc: rework p... |
530 531 |
if (pnetelem->type == SMC_PNET_IB) { if (nla_put_string(msg, SMC_PNETID_IBNAME, pnetelem->ib_name) || |
890a2cb4a net/smc: rework p... |
532 533 534 535 536 537 |
nla_put_u8(msg, SMC_PNETID_IBPORT, pnetelem->ib_port)) return -1; } else { if (nla_put_string(msg, SMC_PNETID_IBNAME, "n/a") || nla_put_u8(msg, SMC_PNETID_IBPORT, 0xff)) return -1; |
6812baabf smc: establish pn... |
538 |
} |
890a2cb4a net/smc: rework p... |
539 |
return 0; |
6812baabf smc: establish pn... |
540 541 542 543 544 |
} static int smc_pnet_add(struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); |
64e28b52c net/smc: add pnet... |
545 |
|
fdff704dc net/smc: rework p... |
546 |
return smc_pnet_enter(net, info->attrs); |
6812baabf smc: establish pn... |
547 548 549 550 |
} static int smc_pnet_del(struct sk_buff *skb, struct genl_info *info) { |
64e28b52c net/smc: add pnet... |
551 |
struct net *net = genl_info_net(info); |
d49baa7e1 net/smc: check fo... |
552 553 |
if (!info->attrs[SMC_PNETID_NAME]) return -EINVAL; |
64e28b52c net/smc: add pnet... |
554 |
return smc_pnet_remove_by_pnetid(net, |
6812baabf smc: establish pn... |
555 556 557 558 559 560 561 562 563 564 565 |
(char *)nla_data(info->attrs[SMC_PNETID_NAME])); } static int smc_pnet_dump_start(struct netlink_callback *cb) { cb->args[0] = 0; return 0; } static int smc_pnet_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq, u32 flags, |
fdff704dc net/smc: rework p... |
566 |
struct smc_pnetentry *pnetelem) |
6812baabf smc: establish pn... |
567 568 569 570 571 572 573 574 575 576 577 578 579 580 |
{ void *hdr; hdr = genlmsg_put(skb, portid, seq, &smc_pnet_nl_family, flags, SMC_PNETID_GET); if (!hdr) return -ENOMEM; if (smc_pnet_set_nla(skb, pnetelem) < 0) { genlmsg_cancel(skb, hdr); return -EMSGSIZE; } genlmsg_end(skb, hdr); return 0; } |
64e28b52c net/smc: add pnet... |
581 582 |
static int _smc_pnet_dump(struct net *net, struct sk_buff *skb, u32 portid, u32 seq, u8 *pnetid, int start_idx) |
6812baabf smc: establish pn... |
583 |
{ |
64e28b52c net/smc: add pnet... |
584 |
struct smc_pnettable *pnettable; |
6812baabf smc: establish pn... |
585 |
struct smc_pnetentry *pnetelem; |
64e28b52c net/smc: add pnet... |
586 |
struct smc_net *sn; |
6812baabf smc: establish pn... |
587 |
int idx = 0; |
64e28b52c net/smc: add pnet... |
588 589 590 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; |
fdff704dc net/smc: rework p... |
591 |
/* dump pnettable entries */ |
64e28b52c net/smc: add pnet... |
592 593 |
read_lock(&pnettable->lock); list_for_each_entry(pnetelem, &pnettable->pnetlist, list) { |
890a2cb4a net/smc: rework p... |
594 595 596 |
if (pnetid && !smc_pnet_match(pnetelem->pnet_name, pnetid)) continue; if (idx++ < start_idx) |
6812baabf smc: establish pn... |
597 |
continue; |
fdff704dc net/smc: rework p... |
598 599 600 |
/* if this is not the initial namespace, dump only netdev */ if (net != &init_net && pnetelem->type != SMC_PNET_ETH) continue; |
890a2cb4a net/smc: rework p... |
601 |
if (smc_pnet_dumpinfo(skb, portid, seq, NLM_F_MULTI, |
fdff704dc net/smc: rework p... |
602 |
pnetelem)) { |
6812baabf smc: establish pn... |
603 604 605 606 |
--idx; break; } } |
64e28b52c net/smc: add pnet... |
607 |
read_unlock(&pnettable->lock); |
890a2cb4a net/smc: rework p... |
608 609 610 611 612 |
return idx; } static int smc_pnet_dump(struct sk_buff *skb, struct netlink_callback *cb) { |
64e28b52c net/smc: add pnet... |
613 |
struct net *net = sock_net(skb->sk); |
890a2cb4a net/smc: rework p... |
614 |
int idx; |
64e28b52c net/smc: add pnet... |
615 |
idx = _smc_pnet_dump(net, skb, NETLINK_CB(cb->skb).portid, |
890a2cb4a net/smc: rework p... |
616 617 618 |
cb->nlh->nlmsg_seq, NULL, cb->args[0]); cb->args[0] = idx; |
6812baabf smc: establish pn... |
619 620 |
return skb->len; } |
890a2cb4a net/smc: rework p... |
621 622 623 |
/* Retrieve one PNETID entry */ static int smc_pnet_get(struct sk_buff *skb, struct genl_info *info) { |
64e28b52c net/smc: add pnet... |
624 |
struct net *net = genl_info_net(info); |
890a2cb4a net/smc: rework p... |
625 626 627 628 629 630 631 632 633 |
struct sk_buff *msg; void *hdr; if (!info->attrs[SMC_PNETID_NAME]) return -EINVAL; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return -ENOMEM; |
64e28b52c net/smc: add pnet... |
634 |
_smc_pnet_dump(net, msg, info->snd_portid, info->snd_seq, |
890a2cb4a net/smc: rework p... |
635 636 637 638 639 640 641 642 643 644 645 |
nla_data(info->attrs[SMC_PNETID_NAME]), 0); /* finish multi part message and send it */ hdr = nlmsg_put(msg, info->snd_portid, info->snd_seq, NLMSG_DONE, 0, NLM_F_MULTI); if (!hdr) { nlmsg_free(msg); return -EMSGSIZE; } return genlmsg_reply(msg, info); } |
6812baabf smc: establish pn... |
646 647 648 649 |
/* Remove and delete all pnetids from pnet table. */ static int smc_pnet_flush(struct sk_buff *skb, struct genl_info *info) { |
64e28b52c net/smc: add pnet... |
650 |
struct net *net = genl_info_net(info); |
8ef659f1a net/smc: fix retu... |
651 652 |
smc_pnet_remove_by_pnetid(net, NULL); return 0; |
6812baabf smc: establish pn... |
653 654 655 656 657 658 |
} /* SMC_PNETID generic netlink operation definition */ static const struct genl_ops smc_pnet_ops[] = { { .cmd = SMC_PNETID_GET, |
ef6243acb genetlink: option... |
659 |
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
29237d22b net/smc: allow un... |
660 |
/* can be retrieved by unprivileged users */ |
6812baabf smc: establish pn... |
661 662 663 664 665 666 |
.doit = smc_pnet_get, .dumpit = smc_pnet_dump, .start = smc_pnet_dump_start }, { .cmd = SMC_PNETID_ADD, |
ef6243acb genetlink: option... |
667 |
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
6812baabf smc: establish pn... |
668 |
.flags = GENL_ADMIN_PERM, |
6812baabf smc: establish pn... |
669 670 671 672 |
.doit = smc_pnet_add }, { .cmd = SMC_PNETID_DEL, |
ef6243acb genetlink: option... |
673 |
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
6812baabf smc: establish pn... |
674 |
.flags = GENL_ADMIN_PERM, |
6812baabf smc: establish pn... |
675 676 677 678 |
.doit = smc_pnet_del }, { .cmd = SMC_PNETID_FLUSH, |
ef6243acb genetlink: option... |
679 |
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
6812baabf smc: establish pn... |
680 |
.flags = GENL_ADMIN_PERM, |
6812baabf smc: establish pn... |
681 682 683 684 685 |
.doit = smc_pnet_flush } }; /* SMC_PNETID family definition */ |
56ce3c5a5 smc: generic netl... |
686 |
static struct genl_family smc_pnet_nl_family __ro_after_init = { |
6812baabf smc: establish pn... |
687 688 689 690 |
.hdrsize = 0, .name = SMCR_GENL_FAMILY_NAME, .version = SMCR_GENL_FAMILY_VERSION, .maxattr = SMC_PNETID_MAX, |
3b0f31f2b genetlink: make p... |
691 |
.policy = smc_pnet_policy, |
6812baabf smc: establish pn... |
692 693 694 695 696 |
.netnsok = true, .module = THIS_MODULE, .ops = smc_pnet_ops, .n_ops = ARRAY_SIZE(smc_pnet_ops) }; |
e888a2e83 net/smc: introduc... |
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 |
bool smc_pnet_is_ndev_pnetid(struct net *net, u8 *pnetid) { struct smc_net *sn = net_generic(net, smc_net_id); struct smc_pnetids_ndev_entry *pe; bool rc = false; read_lock(&sn->pnetids_ndev.lock); list_for_each_entry(pe, &sn->pnetids_ndev.list, list) { if (smc_pnet_match(pnetid, pe->pnetid)) { rc = true; goto unlock; } } unlock: read_unlock(&sn->pnetids_ndev.lock); return rc; } static int smc_pnet_add_pnetid(struct net *net, u8 *pnetid) { struct smc_net *sn = net_generic(net, smc_net_id); struct smc_pnetids_ndev_entry *pe, *pi; pe = kzalloc(sizeof(*pe), GFP_KERNEL); if (!pe) return -ENOMEM; write_lock(&sn->pnetids_ndev.lock); list_for_each_entry(pi, &sn->pnetids_ndev.list, list) { if (smc_pnet_match(pnetid, pe->pnetid)) { refcount_inc(&pi->refcnt); kfree(pe); goto unlock; } } refcount_set(&pe->refcnt, 1); memcpy(pe->pnetid, pnetid, SMC_MAX_PNETID_LEN); list_add_tail(&pe->list, &sn->pnetids_ndev.list); unlock: write_unlock(&sn->pnetids_ndev.lock); return 0; } static void smc_pnet_remove_pnetid(struct net *net, u8 *pnetid) { struct smc_net *sn = net_generic(net, smc_net_id); struct smc_pnetids_ndev_entry *pe, *pe2; write_lock(&sn->pnetids_ndev.lock); list_for_each_entry_safe(pe, pe2, &sn->pnetids_ndev.list, list) { if (smc_pnet_match(pnetid, pe->pnetid)) { if (refcount_dec_and_test(&pe->refcnt)) { list_del(&pe->list); kfree(pe); } break; } } write_unlock(&sn->pnetids_ndev.lock); } static void smc_pnet_add_base_pnetid(struct net *net, struct net_device *dev, u8 *ndev_pnetid) { struct net_device *base_dev; base_dev = __pnet_find_base_ndev(dev); if (base_dev->flags & IFF_UP && !smc_pnetid_by_dev_port(base_dev->dev.parent, base_dev->dev_port, ndev_pnetid)) { /* add to PNETIDs list */ smc_pnet_add_pnetid(net, ndev_pnetid); } } /* create initial list of netdevice pnetids */ static void smc_pnet_create_pnetids_list(struct net *net) { u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; struct net_device *dev; rtnl_lock(); for_each_netdev(net, dev) smc_pnet_add_base_pnetid(net, dev, ndev_pnetid); rtnl_unlock(); } /* clean up list of netdevice pnetids */ static void smc_pnet_destroy_pnetids_list(struct net *net) { struct smc_net *sn = net_generic(net, smc_net_id); struct smc_pnetids_ndev_entry *pe, *temp_pe; write_lock(&sn->pnetids_ndev.lock); list_for_each_entry_safe(pe, temp_pe, &sn->pnetids_ndev.list, list) { list_del(&pe->list); kfree(pe); } write_unlock(&sn->pnetids_ndev.lock); } |
6812baabf smc: establish pn... |
799 800 801 802 |
static int smc_pnet_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); |
e888a2e83 net/smc: introduc... |
803 804 |
struct net *net = dev_net(event_dev); u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; |
6812baabf smc: establish pn... |
805 806 807 808 809 |
switch (event) { case NETDEV_REBOOT: case NETDEV_UNREGISTER: smc_pnet_remove_by_ndev(event_dev); |
be6a3f38f net/smc: determin... |
810 |
return NOTIFY_OK; |
fdff704dc net/smc: rework p... |
811 812 813 |
case NETDEV_REGISTER: smc_pnet_add_by_ndev(event_dev); return NOTIFY_OK; |
e888a2e83 net/smc: introduc... |
814 815 816 817 818 819 820 821 822 823 824 |
case NETDEV_UP: smc_pnet_add_base_pnetid(net, event_dev, ndev_pnetid); return NOTIFY_OK; case NETDEV_DOWN: event_dev = __pnet_find_base_ndev(event_dev); if (!smc_pnetid_by_dev_port(event_dev->dev.parent, event_dev->dev_port, ndev_pnetid)) { /* remove from PNETIDs list */ smc_pnet_remove_pnetid(net, ndev_pnetid); } return NOTIFY_OK; |
6812baabf smc: establish pn... |
825 |
default: |
be6a3f38f net/smc: determin... |
826 |
return NOTIFY_DONE; |
6812baabf smc: establish pn... |
827 |
} |
6812baabf smc: establish pn... |
828 829 830 831 832 |
} static struct notifier_block smc_netdev_notifier = { .notifier_call = smc_pnet_netdev_event }; |
64e28b52c net/smc: add pnet... |
833 834 835 836 837 |
/* init network namespace */ int smc_pnet_net_init(struct net *net) { struct smc_net *sn = net_generic(net, smc_net_id); struct smc_pnettable *pnettable = &sn->pnettable; |
e888a2e83 net/smc: introduc... |
838 |
struct smc_pnetids_ndev *pnetids_ndev = &sn->pnetids_ndev; |
64e28b52c net/smc: add pnet... |
839 840 841 |
INIT_LIST_HEAD(&pnettable->pnetlist); rwlock_init(&pnettable->lock); |
e888a2e83 net/smc: introduc... |
842 843 844 845 |
INIT_LIST_HEAD(&pnetids_ndev->list); rwlock_init(&pnetids_ndev->lock); smc_pnet_create_pnetids_list(net); |
64e28b52c net/smc: add pnet... |
846 847 848 |
return 0; } |
6812baabf smc: establish pn... |
849 850 851 852 853 854 855 856 857 858 |
int __init smc_pnet_init(void) { int rc; rc = genl_register_family(&smc_pnet_nl_family); if (rc) return rc; rc = register_netdevice_notifier(&smc_netdev_notifier); if (rc) genl_unregister_family(&smc_pnet_nl_family); |
e888a2e83 net/smc: introduc... |
859 |
|
6812baabf smc: establish pn... |
860 861 |
return rc; } |
64e28b52c net/smc: add pnet... |
862 863 864 865 866 |
/* exit network namespace */ void smc_pnet_net_exit(struct net *net) { /* flush pnet table */ smc_pnet_remove_by_pnetid(net, NULL); |
e888a2e83 net/smc: introduc... |
867 |
smc_pnet_destroy_pnetids_list(net); |
64e28b52c net/smc: add pnet... |
868 |
} |
6812baabf smc: establish pn... |
869 870 |
void smc_pnet_exit(void) { |
6812baabf smc: establish pn... |
871 872 873 |
unregister_netdevice_notifier(&smc_netdev_notifier); genl_unregister_family(&smc_pnet_nl_family); } |
e888a2e83 net/smc: introduc... |
874 |
static struct net_device *__pnet_find_base_ndev(struct net_device *ndev) |
6812baabf smc: establish pn... |
875 |
{ |
0afff91c6 net/smc: add pnet... |
876 |
int i, nest_lvl; |
6812baabf smc: establish pn... |
877 |
|
e888a2e83 net/smc: introduc... |
878 |
ASSERT_RTNL(); |
f3b0a18bb net: remove unnec... |
879 |
nest_lvl = ndev->lower_level; |
0afff91c6 net/smc: add pnet... |
880 881 882 883 884 885 886 887 |
for (i = 0; i < nest_lvl; i++) { struct list_head *lower = &ndev->adj_list.lower; if (list_empty(lower)) break; lower = lower->next; ndev = netdev_lower_get_next(ndev, &lower); } |
e888a2e83 net/smc: introduc... |
888 889 890 891 892 893 894 895 896 897 898 899 |
return ndev; } /* Determine one base device for stacked net devices. * If the lower device level contains more than one devices * (for instance with bonding slaves), just the first device * is used to reach a base device. */ static struct net_device *pnet_find_base_ndev(struct net_device *ndev) { rtnl_lock(); ndev = __pnet_find_base_ndev(ndev); |
0afff91c6 net/smc: add pnet... |
900 901 902 |
rtnl_unlock(); return ndev; } |
64e28b52c net/smc: add pnet... |
903 |
static int smc_pnet_find_ndev_pnetid_by_table(struct net_device *ndev, |
890a2cb4a net/smc: rework p... |
904 905 |
u8 *pnetid) { |
64e28b52c net/smc: add pnet... |
906 907 |
struct smc_pnettable *pnettable; struct net *net = dev_net(ndev); |
890a2cb4a net/smc: rework p... |
908 |
struct smc_pnetentry *pnetelem; |
64e28b52c net/smc: add pnet... |
909 |
struct smc_net *sn; |
890a2cb4a net/smc: rework p... |
910 |
int rc = -ENOENT; |
64e28b52c net/smc: add pnet... |
911 912 913 914 915 916 |
/* get pnettable for namespace */ sn = net_generic(net, smc_net_id); pnettable = &sn->pnettable; read_lock(&pnettable->lock); list_for_each_entry(pnetelem, &pnettable->pnetlist, list) { |
fdff704dc net/smc: rework p... |
917 |
if (pnetelem->type == SMC_PNET_ETH && ndev == pnetelem->ndev) { |
890a2cb4a net/smc: rework p... |
918 919 920 921 922 923 |
/* get pnetid of netdev device */ memcpy(pnetid, pnetelem->pnet_name, SMC_MAX_PNETID_LEN); rc = 0; break; } } |
64e28b52c net/smc: add pnet... |
924 |
read_unlock(&pnettable->lock); |
890a2cb4a net/smc: rework p... |
925 926 |
return rc; } |
fdff704dc net/smc: rework p... |
927 928 |
/* find a roce device for the given pnetid */ static void _smc_pnet_find_roce_by_pnetid(u8 *pnet_id, |
6c868a3ed net/smc: introduc... |
929 930 |
struct smc_init_info *ini, struct smc_ib_device *known_dev) |
fdff704dc net/smc: rework p... |
931 932 933 934 935 |
{ struct smc_ib_device *ibdev; int i; ini->ib_dev = NULL; |
92f3cb0e1 net/smc: fix slee... |
936 |
mutex_lock(&smc_ib_devices.mutex); |
fdff704dc net/smc: rework p... |
937 |
list_for_each_entry(ibdev, &smc_ib_devices.list, list) { |
6c868a3ed net/smc: introduc... |
938 939 |
if (ibdev == known_dev) continue; |
fdff704dc net/smc: rework p... |
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 |
for (i = 1; i <= SMC_MAX_PORTS; i++) { if (!rdma_is_port_valid(ibdev->ibdev, i)) continue; if (smc_pnet_match(ibdev->pnetid[i - 1], pnet_id) && smc_ib_port_active(ibdev, i) && !test_bit(i - 1, ibdev->ports_going_away) && !smc_ib_determine_gid(ibdev, i, ini->vlan_id, ini->ib_gid, NULL)) { ini->ib_dev = ibdev; ini->ib_port = i; goto out; } } } out: |
92f3cb0e1 net/smc: fix slee... |
955 |
mutex_unlock(&smc_ib_devices.mutex); |
fdff704dc net/smc: rework p... |
956 |
} |
6c868a3ed net/smc: introduc... |
957 958 959 960 961 962 963 |
/* find alternate roce device with same pnet_id and vlan_id */ void smc_pnet_find_alt_roce(struct smc_link_group *lgr, struct smc_init_info *ini, struct smc_ib_device *known_dev) { _smc_pnet_find_roce_by_pnetid(lgr->pnet_id, ini, known_dev); } |
54903572c net/smc: allow pn... |
964 965 966 967 |
/* if handshake network device belongs to a roce device, return its * IB device and port */ static void smc_pnet_find_rdma_dev(struct net_device *netdev, |
bc36d2fc9 net/smc: consolid... |
968 |
struct smc_init_info *ini) |
54903572c net/smc: allow pn... |
969 970 |
{ struct smc_ib_device *ibdev; |
92f3cb0e1 net/smc: fix slee... |
971 |
mutex_lock(&smc_ib_devices.mutex); |
54903572c net/smc: allow pn... |
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 |
list_for_each_entry(ibdev, &smc_ib_devices.list, list) { struct net_device *ndev; int i; for (i = 1; i <= SMC_MAX_PORTS; i++) { if (!rdma_is_port_valid(ibdev->ibdev, i)) continue; if (!ibdev->ibdev->ops.get_netdev) continue; ndev = ibdev->ibdev->ops.get_netdev(ibdev->ibdev, i); if (!ndev) continue; dev_put(ndev); if (netdev == ndev && smc_ib_port_active(ibdev, i) && |
c3d9494e6 net/smc: no new c... |
987 |
!test_bit(i - 1, ibdev->ports_going_away) && |
bc36d2fc9 net/smc: consolid... |
988 989 990 991 |
!smc_ib_determine_gid(ibdev, i, ini->vlan_id, ini->ib_gid, NULL)) { ini->ib_dev = ibdev; ini->ib_port = i; |
54903572c net/smc: allow pn... |
992 993 994 995 |
break; } } } |
92f3cb0e1 net/smc: fix slee... |
996 |
mutex_unlock(&smc_ib_devices.mutex); |
54903572c net/smc: allow pn... |
997 |
} |
0afff91c6 net/smc: add pnet... |
998 |
/* Determine the corresponding IB device port based on the hardware PNETID. |
7005ada68 net/smc: use corr... |
999 1000 |
* Searching stops at the first matching active IB device port with vlan_id * configured. |
54903572c net/smc: allow pn... |
1001 1002 |
* If nothing found, check pnetid table. * If nothing found, try to use handshake device |
0afff91c6 net/smc: add pnet... |
1003 1004 |
*/ static void smc_pnet_find_roce_by_pnetid(struct net_device *ndev, |
bc36d2fc9 net/smc: consolid... |
1005 |
struct smc_init_info *ini) |
0afff91c6 net/smc: add pnet... |
1006 1007 |
{ u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; |
0afff91c6 net/smc: add pnet... |
1008 1009 1010 |
ndev = pnet_find_base_ndev(ndev); if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port, |
890a2cb4a net/smc: rework p... |
1011 |
ndev_pnetid) && |
54903572c net/smc: allow pn... |
1012 |
smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid)) { |
bc36d2fc9 net/smc: consolid... |
1013 |
smc_pnet_find_rdma_dev(ndev, ini); |
0afff91c6 net/smc: add pnet... |
1014 |
return; /* pnetid could not be determined */ |
54903572c net/smc: allow pn... |
1015 |
} |
6c868a3ed net/smc: introduc... |
1016 |
_smc_pnet_find_roce_by_pnetid(ndev_pnetid, ini, NULL); |
0afff91c6 net/smc: add pnet... |
1017 |
} |
1619f7705 net/smc: add pnet... |
1018 |
static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev, |
bc36d2fc9 net/smc: consolid... |
1019 |
struct smc_init_info *ini) |
1619f7705 net/smc: add pnet... |
1020 1021 1022 1023 1024 1025 |
{ u8 ndev_pnetid[SMC_MAX_PNETID_LEN]; struct smcd_dev *ismdev; ndev = pnet_find_base_ndev(ndev); if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port, |
f3d74b224 net/smc: add smcd... |
1026 1027 |
ndev_pnetid) && smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid)) |
1619f7705 net/smc: add pnet... |
1028 |
return; /* pnetid could not be determined */ |
82087c033 net/smc: switch s... |
1029 |
mutex_lock(&smcd_dev_list.mutex); |
1619f7705 net/smc: add pnet... |
1030 |
list_for_each_entry(ismdev, &smcd_dev_list.list, list) { |
c3d9494e6 net/smc: no new c... |
1031 |
if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) && |
7b2977d08 net/smc: improve ... |
1032 |
!ismdev->going_away && |
3fc649376 net/smc: prepare ... |
1033 1034 |
(!ini->ism_peer_gid[0] || !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id, |
7b2977d08 net/smc: improve ... |
1035 |
ismdev))) { |
3fc649376 net/smc: prepare ... |
1036 |
ini->ism_dev[0] = ismdev; |
1619f7705 net/smc: add pnet... |
1037 1038 1039 |
break; } } |
82087c033 net/smc: switch s... |
1040 |
mutex_unlock(&smcd_dev_list.mutex); |
1619f7705 net/smc: add pnet... |
1041 |
} |
0afff91c6 net/smc: add pnet... |
1042 1043 1044 1045 |
/* PNET table analysis for a given sock: * determine ib_device and port belonging to used internal TCP socket * ethernet interface. */ |
bc36d2fc9 net/smc: consolid... |
1046 |
void smc_pnet_find_roce_resource(struct sock *sk, struct smc_init_info *ini) |
0afff91c6 net/smc: add pnet... |
1047 1048 |
{ struct dst_entry *dst = sk_dst_get(sk); |
bc36d2fc9 net/smc: consolid... |
1049 1050 |
ini->ib_dev = NULL; ini->ib_port = 0; |
0afff91c6 net/smc: add pnet... |
1051 1052 1053 1054 |
if (!dst) goto out; if (!dst->dev) goto out_rel; |
bc36d2fc9 net/smc: consolid... |
1055 |
smc_pnet_find_roce_by_pnetid(dst->dev, ini); |
0afff91c6 net/smc: add pnet... |
1056 |
|
6812baabf smc: establish pn... |
1057 1058 |
out_rel: dst_release(dst); |
0afff91c6 net/smc: add pnet... |
1059 1060 |
out: return; |
6812baabf smc: establish pn... |
1061 |
} |
1619f7705 net/smc: add pnet... |
1062 |
|
bc36d2fc9 net/smc: consolid... |
1063 |
void smc_pnet_find_ism_resource(struct sock *sk, struct smc_init_info *ini) |
1619f7705 net/smc: add pnet... |
1064 1065 |
{ struct dst_entry *dst = sk_dst_get(sk); |
3fc649376 net/smc: prepare ... |
1066 |
ini->ism_dev[0] = NULL; |
1619f7705 net/smc: add pnet... |
1067 1068 1069 1070 |
if (!dst) goto out; if (!dst->dev) goto out_rel; |
bc36d2fc9 net/smc: consolid... |
1071 |
smc_pnet_find_ism_by_pnetid(dst->dev, ini); |
1619f7705 net/smc: add pnet... |
1072 1073 1074 1075 1076 1077 |
out_rel: dst_release(dst); out: return; } |
fdff704dc net/smc: rework p... |
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 |
/* Lookup and apply a pnet table entry to the given ib device. */ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port) { char *ib_name = smcibdev->ibdev->name; struct smc_pnettable *pnettable; struct smc_pnetentry *tmp_pe; struct smc_net *sn; int rc = -ENOENT; /* get pnettable for init namespace */ sn = net_generic(&init_net, smc_net_id); pnettable = &sn->pnettable; read_lock(&pnettable->lock); list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { if (tmp_pe->type == SMC_PNET_IB && !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX) && tmp_pe->ib_port == ib_port) { smc_pnet_apply_ib(smcibdev, ib_port, tmp_pe->pnet_name); rc = 0; break; } } read_unlock(&pnettable->lock); return rc; } /* Lookup and apply a pnet table entry to the given smcd device. */ int smc_pnetid_by_table_smcd(struct smcd_dev *smcddev) { const char *ib_name = dev_name(&smcddev->dev); struct smc_pnettable *pnettable; struct smc_pnetentry *tmp_pe; struct smc_net *sn; int rc = -ENOENT; /* get pnettable for init namespace */ sn = net_generic(&init_net, smc_net_id); pnettable = &sn->pnettable; read_lock(&pnettable->lock); list_for_each_entry(tmp_pe, &pnettable->pnetlist, list) { if (tmp_pe->type == SMC_PNET_IB && !strncmp(tmp_pe->ib_name, ib_name, IB_DEVICE_NAME_MAX)) { smc_pnet_apply_smcd(smcddev, tmp_pe->pnet_name); rc = 0; break; } } read_unlock(&pnettable->lock); return rc; } |