forked from Minki/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>
This commit is contained in:
parent
0f00571f94
commit
e35ecb466e
@ -2474,6 +2474,7 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
|
|||||||
|
|
||||||
id->tos = id_priv->tos;
|
id->tos = id_priv->tos;
|
||||||
id->tos_set = id_priv->tos_set;
|
id->tos_set = id_priv->tos_set;
|
||||||
|
id->afonly = id_priv->afonly;
|
||||||
id_priv->cm_id.iw = id;
|
id_priv->cm_id.iw = id;
|
||||||
|
|
||||||
memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
|
memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
|
||||||
|
@ -1300,7 +1300,7 @@ static void siw_cm_llp_state_change(struct sock *sk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr,
|
static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr,
|
||||||
struct sockaddr *raddr)
|
struct sockaddr *raddr, bool afonly)
|
||||||
{
|
{
|
||||||
int rv, flags = 0;
|
int rv, flags = 0;
|
||||||
size_t size = laddr->sa_family == AF_INET ?
|
size_t size = laddr->sa_family == AF_INET ?
|
||||||
@ -1311,6 +1311,12 @@ static int kernel_bindconnect(struct socket *s, struct sockaddr *laddr,
|
|||||||
*/
|
*/
|
||||||
sock_set_reuseaddr(s->sk);
|
sock_set_reuseaddr(s->sk);
|
||||||
|
|
||||||
|
if (afonly) {
|
||||||
|
rv = ip6_sock_set_v6only(s->sk);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
rv = s->ops->bind(s, laddr, size);
|
rv = s->ops->bind(s, laddr, size);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
return rv;
|
return rv;
|
||||||
@ -1371,7 +1377,7 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
|
|||||||
* mode. Might be reconsidered for async connection setup at
|
* mode. Might be reconsidered for async connection setup at
|
||||||
* TCP level.
|
* TCP level.
|
||||||
*/
|
*/
|
||||||
rv = kernel_bindconnect(s, laddr, raddr);
|
rv = kernel_bindconnect(s, laddr, raddr, id->afonly);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
siw_dbg_qp(qp, "kernel_bindconnect: error %d\n", rv);
|
siw_dbg_qp(qp, "kernel_bindconnect: error %d\n", rv);
|
||||||
goto error;
|
goto error;
|
||||||
@ -1786,6 +1792,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
|
|||||||
} else {
|
} else {
|
||||||
struct sockaddr_in6 *laddr = &to_sockaddr_in6(id->local_addr);
|
struct sockaddr_in6 *laddr = &to_sockaddr_in6(id->local_addr);
|
||||||
|
|
||||||
|
if (id->afonly) {
|
||||||
|
rv = ip6_sock_set_v6only(s->sk);
|
||||||
|
if (rv) {
|
||||||
|
siw_dbg(id->device,
|
||||||
|
"ip6_sock_set_v6only erro: %d\n", rv);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* For wildcard addr, limit binding to current device only */
|
/* For wildcard addr, limit binding to current device only */
|
||||||
if (ipv6_addr_any(&laddr->sin6_addr))
|
if (ipv6_addr_any(&laddr->sin6_addr))
|
||||||
s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
|
s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
|
||||||
|
@ -70,6 +70,7 @@ struct iw_cm_id {
|
|||||||
u8 tos;
|
u8 tos;
|
||||||
bool tos_set:1;
|
bool tos_set:1;
|
||||||
bool mapped:1;
|
bool mapped:1;
|
||||||
|
bool afonly:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iw_cm_conn_param {
|
struct iw_cm_conn_param {
|
||||||
|
Loading…
Reference in New Issue
Block a user