Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/iwcm: Allow AFONLY binding for IPv6 addresses

Binding IPv6 address/port to AF_INET6 domain only is provided via
rdma_set_afonly(), but was not signalled to the provider. Applications
like NFS/RDMA bind the same port to both IPv4 and IPv6 addresses
simultaneously and thus rely on it working correctly.

Link: https://lore.kernel.org/r/20210219143441.1068-1-bmt@zurich.ibm.com
Tested-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Bernard Metzler and committed by
Jason Gunthorpe
e35ecb46 0f00571f

+19 -2
+1
drivers/infiniband/core/cma.c
··· 2474 2474 2475 2475 id->tos = id_priv->tos; 2476 2476 id->tos_set = id_priv->tos_set; 2477 + id->afonly = id_priv->afonly; 2477 2478 id_priv->cm_id.iw = id; 2478 2479 2479 2480 memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
+17 -2
drivers/infiniband/sw/siw/siw_cm.c
··· 1300 1300 } 1301 1301 1302 1302 static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr, 1303 - struct sockaddr *raddr) 1303 + struct sockaddr *raddr, bool afonly) 1304 1304 { 1305 1305 int rv, flags = 0; 1306 1306 size_t size = laddr->sa_family == AF_INET ? ··· 1310 1310 * Make address available again asap. 1311 1311 */ 1312 1312 sock_set_reuseaddr(s->sk); 1313 + 1314 + if (afonly) { 1315 + rv = ip6_sock_set_v6only(s->sk); 1316 + if (rv) 1317 + return rv; 1318 + } 1313 1319 1314 1320 rv = s->ops->bind(s, laddr, size); 1315 1321 if (rv < 0) ··· 1377 1371 * mode. Might be reconsidered for async connection setup at 1378 1372 * TCP level. 1379 1373 */ 1380 - rv = kernel_bindconnect(s, laddr, raddr); 1374 + rv = kernel_bindconnect(s, laddr, raddr, id->afonly); 1381 1375 if (rv != 0) { 1382 1376 siw_dbg_qp(qp, "kernel_bindconnect: error %d\n", rv); 1383 1377 goto error; ··· 1791 1785 sizeof(struct sockaddr_in)); 1792 1786 } else { 1793 1787 struct sockaddr_in6 *laddr = &to_sockaddr_in6(id->local_addr); 1788 + 1789 + if (id->afonly) { 1790 + rv = ip6_sock_set_v6only(s->sk); 1791 + if (rv) { 1792 + siw_dbg(id->device, 1793 + "ip6_sock_set_v6only erro: %d\n", rv); 1794 + goto error; 1795 + } 1796 + } 1794 1797 1795 1798 /* For wildcard addr, limit binding to current device only */ 1796 1799 if (ipv6_addr_any(&laddr->sin6_addr))
+1
include/rdma/iw_cm.h
··· 70 70 u8 tos; 71 71 bool tos_set:1; 72 72 bool mapped:1; 73 + bool afonly:1; 73 74 }; 74 75 75 76 struct iw_cm_conn_param {