Skip to content

Commit

Permalink
RDMA/cma: Allow user to restrict listens to bound address family
Browse files Browse the repository at this point in the history
Provide an option for the user to specify that listens should only
accept connections where the incoming address family matches that of
the locally bound address.  This is used to support the equivalent of
IPV6_V6ONLY socket option, which allows an app to only accept
connection requests directed to IPv6 addresses.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Sean Hefty authored and Roland Dreier committed Jul 9, 2012
1 parent 406b6a2 commit 6860212
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 4 deletions.
35 changes: 31 additions & 4 deletions drivers/infiniband/core/cma.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ struct rdma_bind_list {
unsigned short port;
};

enum {
CMA_OPTION_AFONLY,
};

/*
* Device removal can occur at anytime, so we need extra handling to
* serialize notifying the user of device removal with other callbacks.
Expand Down Expand Up @@ -137,6 +141,7 @@ struct rdma_id_private {
u32 qkey;
u32 qp_num;
pid_t owner;
u32 options;
u8 srq;
u8 tos;
u8 reuseaddr;
Expand Down Expand Up @@ -2104,6 +2109,26 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse)
}
EXPORT_SYMBOL(rdma_set_reuseaddr);

int rdma_set_afonly(struct rdma_cm_id *id, int afonly)
{
struct rdma_id_private *id_priv;
unsigned long flags;
int ret;

id_priv = container_of(id, struct rdma_id_private, id);
spin_lock_irqsave(&id_priv->lock, flags);
if (id_priv->state == RDMA_CM_IDLE || id_priv->state == RDMA_CM_ADDR_BOUND) {
id_priv->options |= (1 << CMA_OPTION_AFONLY);
id_priv->afonly = afonly;
ret = 0;
} else {
ret = -EINVAL;
}
spin_unlock_irqrestore(&id_priv->lock, flags);
return ret;
}
EXPORT_SYMBOL(rdma_set_afonly);

static void cma_bind_port(struct rdma_bind_list *bind_list,
struct rdma_id_private *id_priv)
{
Expand Down Expand Up @@ -2379,12 +2404,14 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
}

memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
if (addr->sa_family == AF_INET)
id_priv->afonly = 1;
if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) {
if (addr->sa_family == AF_INET)
id_priv->afonly = 1;
#if IS_ENABLED(CONFIG_IPV6)
else if (addr->sa_family == AF_INET6)
id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
else if (addr->sa_family == AF_INET6)
id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
#endif
}
ret = cma_get_port(id_priv);
if (ret)
goto err2;
Expand Down
7 changes: 7 additions & 0 deletions drivers/infiniband/core/ucma.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,13 @@ static int ucma_set_option_id(struct ucma_context *ctx, int optname,
}
ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
break;
case RDMA_OPTION_ID_AFONLY:
if (optlen != sizeof(int)) {
ret = -EINVAL;
break;
}
ret = rdma_set_afonly(ctx->cm_id, *((int *) optval) ? 1 : 0);
break;
default:
ret = -ENOSYS;
}
Expand Down
10 changes: 10 additions & 0 deletions include/rdma/rdma_cm.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,14 @@ void rdma_set_service_type(struct rdma_cm_id *id, int tos);
*/
int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse);

/**
* rdma_set_afonly - Specify that listens are restricted to the
* bound address family only.
* @id: Communication identifer to configure.
* @afonly: Value indicating if listens are restricted.
*
* Must be set before identifier is in the listening state.
*/
int rdma_set_afonly(struct rdma_cm_id *id, int afonly);

#endif /* RDMA_CM_H */
1 change: 1 addition & 0 deletions include/rdma/rdma_user_cm.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ enum {
enum {
RDMA_OPTION_ID_TOS = 0,
RDMA_OPTION_ID_REUSEADDR = 1,
RDMA_OPTION_ID_AFONLY = 2,
RDMA_OPTION_IB_PATH = 1
};

Expand Down

0 comments on commit 6860212

Please sign in to comment.