aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Vesker <valex@mellanox.com>2016-07-06 09:36:35 -0400
committerDoug Ledford <dledford@redhat.com>2016-08-03 21:06:46 -0400
commitab15c95a17b3fe8c0e01bb7ce1dd0b657598eb61 (patch)
tree980ba25528b581526fe924f80516038d7697bd2b
parent3d3fd74239db7a6f7e07a762f5ee7140215aafc5 (diff)
IB/core: Support for CMA multicast join flags
Added UCMA and CMA support for multicast join flags. Flags are passed using UCMA CM join command previously reserved fields. Currently supporting two join flags indicating two different multicast JoinStates: 1. Full Member: The initiator creates the Multicast group(MCG) if it wasn't previously created, can send Multicast messages to the group and receive messages from the MCG. 2. Send Only Full Member: The initiator creates the Multicast group(MCG) if it wasn't previously created, can send Multicast messages to the group but doesn't receive any messages from the MCG. IB: Send Only Full Member requires a query of ClassPortInfo to determine if SM/SA supports this option. If SM/SA doesn't support Send-Only there will be no join request sent and an error will be returned. ETH: When Send Only Full Member is requested no IGMP join will be sent. Signed-off-by: Alex Vesker <valex@mellanox.com> Reviewed by: Hal Rosenstock <hal@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/cma.c100
-rw-r--r--drivers/infiniband/core/multicast.c12
-rw-r--r--drivers/infiniband/core/ucma.c18
-rw-r--r--include/rdma/ib_sa.h13
-rw-r--r--include/rdma/rdma_cm.h4
-rw-r--r--include/uapi/rdma/rdma_user_cm.h9
6 files changed, 131 insertions, 25 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index f0c91ba3178a..0451307bea18 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -68,6 +68,7 @@ MODULE_DESCRIPTION("Generic RDMA CM Agent");
68MODULE_LICENSE("Dual BSD/GPL"); 68MODULE_LICENSE("Dual BSD/GPL");
69 69
70#define CMA_CM_RESPONSE_TIMEOUT 20 70#define CMA_CM_RESPONSE_TIMEOUT 20
71#define CMA_QUERY_CLASSPORT_INFO_TIMEOUT 3000
71#define CMA_MAX_CM_RETRIES 15 72#define CMA_MAX_CM_RETRIES 15
72#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24) 73#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
73#define CMA_IBOE_PACKET_LIFETIME 18 74#define CMA_IBOE_PACKET_LIFETIME 18
@@ -162,6 +163,14 @@ struct rdma_bind_list {
162 unsigned short port; 163 unsigned short port;
163}; 164};
164 165
166struct class_port_info_context {
167 struct ib_class_port_info *class_port_info;
168 struct ib_device *device;
169 struct completion done;
170 struct ib_sa_query *sa_query;
171 u8 port_num;
172};
173
165static int cma_ps_alloc(struct net *net, enum rdma_port_space ps, 174static int cma_ps_alloc(struct net *net, enum rdma_port_space ps,
166 struct rdma_bind_list *bind_list, int snum) 175 struct rdma_bind_list *bind_list, int snum)
167{ 176{
@@ -306,6 +315,7 @@ struct cma_multicast {
306 struct sockaddr_storage addr; 315 struct sockaddr_storage addr;
307 struct kref mcref; 316 struct kref mcref;
308 bool igmp_joined; 317 bool igmp_joined;
318 u8 join_state;
309}; 319};
310 320
311struct cma_work { 321struct cma_work {
@@ -3754,10 +3764,63 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
3754 } 3764 }
3755} 3765}
3756 3766
3767static void cma_query_sa_classport_info_cb(int status,
3768 struct ib_class_port_info *rec,
3769 void *context)
3770{
3771 struct class_port_info_context *cb_ctx = context;
3772
3773 WARN_ON(!context);
3774
3775 if (status || !rec) {
3776 pr_debug("RDMA CM: %s port %u failed query ClassPortInfo status: %d\n",
3777 cb_ctx->device->name, cb_ctx->port_num, status);
3778 goto out;
3779 }
3780
3781 memcpy(cb_ctx->class_port_info, rec, sizeof(struct ib_class_port_info));
3782
3783out:
3784 complete(&cb_ctx->done);
3785}
3786
3787static int cma_query_sa_classport_info(struct ib_device *device, u8 port_num,
3788 struct ib_class_port_info *class_port_info)
3789{
3790 struct class_port_info_context *cb_ctx;
3791 int ret;
3792
3793 cb_ctx = kmalloc(sizeof(*cb_ctx), GFP_KERNEL);
3794 if (!cb_ctx)
3795 return -ENOMEM;
3796
3797 cb_ctx->device = device;
3798 cb_ctx->class_port_info = class_port_info;
3799 cb_ctx->port_num = port_num;
3800 init_completion(&cb_ctx->done);
3801
3802 ret = ib_sa_classport_info_rec_query(&sa_client, device, port_num,
3803 CMA_QUERY_CLASSPORT_INFO_TIMEOUT,
3804 GFP_KERNEL, cma_query_sa_classport_info_cb,
3805 cb_ctx, &cb_ctx->sa_query);
3806 if (ret < 0) {
3807 pr_err("RDMA CM: %s port %u failed to send ClassPortInfo query, ret: %d\n",
3808 device->name, port_num, ret);
3809 goto out;
3810 }
3811
3812 wait_for_completion(&cb_ctx->done);
3813
3814out:
3815 kfree(cb_ctx);
3816 return ret;
3817}
3818
3757static int cma_join_ib_multicast(struct rdma_id_private *id_priv, 3819static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
3758 struct cma_multicast *mc) 3820 struct cma_multicast *mc)
3759{ 3821{
3760 struct ib_sa_mcmember_rec rec; 3822 struct ib_sa_mcmember_rec rec;
3823 struct ib_class_port_info class_port_info;
3761 struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; 3824 struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
3762 ib_sa_comp_mask comp_mask; 3825 ib_sa_comp_mask comp_mask;
3763 int ret; 3826 int ret;
@@ -3776,7 +3839,24 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
3776 rec.qkey = cpu_to_be32(id_priv->qkey); 3839 rec.qkey = cpu_to_be32(id_priv->qkey);
3777 rdma_addr_get_sgid(dev_addr, &rec.port_gid); 3840 rdma_addr_get_sgid(dev_addr, &rec.port_gid);
3778 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); 3841 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
3779 rec.join_state = 1; 3842 rec.join_state = mc->join_state;
3843
3844 if (rec.join_state == BIT(SENDONLY_FULLMEMBER_JOIN)) {
3845 ret = cma_query_sa_classport_info(id_priv->id.device,
3846 id_priv->id.port_num,
3847 &class_port_info);
3848
3849 if (ret)
3850 return ret;
3851
3852 if (!(ib_get_cpi_capmask2(&class_port_info) &
3853 IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT)) {
3854 pr_warn("RDMA CM: %s port %u Unable to multicast join\n"
3855 "RDMA CM: SM doesn't support Send Only Full Member option\n",
3856 id_priv->id.device->name, id_priv->id.port_num);
3857 return -EOPNOTSUPP;
3858 }
3859 }
3780 3860
3781 comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID | 3861 comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
3782 IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE | 3862 IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
@@ -3845,6 +3925,9 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
3845 struct sockaddr *addr = (struct sockaddr *)&mc->addr; 3925 struct sockaddr *addr = (struct sockaddr *)&mc->addr;
3846 struct net_device *ndev = NULL; 3926 struct net_device *ndev = NULL;
3847 enum ib_gid_type gid_type; 3927 enum ib_gid_type gid_type;
3928 bool send_only;
3929
3930 send_only = mc->join_state == BIT(SENDONLY_FULLMEMBER_JOIN);
3848 3931
3849 if (cma_zero_addr((struct sockaddr *)&mc->addr)) 3932 if (cma_zero_addr((struct sockaddr *)&mc->addr))
3850 return -EINVAL; 3933 return -EINVAL;
@@ -3878,12 +3961,14 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
3878 gid_type = id_priv->cma_dev->default_gid_type[id_priv->id.port_num - 3961 gid_type = id_priv->cma_dev->default_gid_type[id_priv->id.port_num -
3879 rdma_start_port(id_priv->cma_dev->device)]; 3962 rdma_start_port(id_priv->cma_dev->device)];
3880 if (addr->sa_family == AF_INET) { 3963 if (addr->sa_family == AF_INET) {
3881 if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) 3964 if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
3882 err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
3883 true);
3884 if (!err) {
3885 mc->igmp_joined = true;
3886 mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT; 3965 mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
3966 if (!send_only) {
3967 err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
3968 true);
3969 if (!err)
3970 mc->igmp_joined = true;
3971 }
3887 } 3972 }
3888 } else { 3973 } else {
3889 if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) 3974 if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
@@ -3913,7 +3998,7 @@ out1:
3913} 3998}
3914 3999
3915int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, 4000int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
3916 void *context) 4001 u8 join_state, void *context)
3917{ 4002{
3918 struct rdma_id_private *id_priv; 4003 struct rdma_id_private *id_priv;
3919 struct cma_multicast *mc; 4004 struct cma_multicast *mc;
@@ -3932,6 +4017,7 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
3932 mc->context = context; 4017 mc->context = context;
3933 mc->id_priv = id_priv; 4018 mc->id_priv = id_priv;
3934 mc->igmp_joined = false; 4019 mc->igmp_joined = false;
4020 mc->join_state = join_state;
3935 spin_lock(&id_priv->lock); 4021 spin_lock(&id_priv->lock);
3936 list_add(&mc->list, &id_priv->mc_list); 4022 list_add(&mc->list, &id_priv->mc_list);
3937 spin_unlock(&id_priv->lock); 4023 spin_unlock(&id_priv->lock);
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a83ec28a147b..3a3c5d73bbfc 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -93,18 +93,6 @@ enum {
93 93
94struct mcast_member; 94struct mcast_member;
95 95
96/*
97* There are 4 types of join states:
98* FullMember, NonMember, SendOnlyNonMember, SendOnlyFullMember.
99*/
100enum {
101 FULLMEMBER_JOIN,
102 NONMEMBER_JOIN,
103 SENDONLY_NONMEBER_JOIN,
104 SENDONLY_FULLMEMBER_JOIN,
105 NUM_JOIN_MEMBERSHIP_TYPES,
106};
107
108struct mcast_group { 96struct mcast_group {
109 struct ib_sa_mcmember_rec rec; 97 struct ib_sa_mcmember_rec rec;
110 struct rb_node node; 98 struct rb_node node;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index c0f3826abb30..2825ece91d3c 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -106,6 +106,7 @@ struct ucma_multicast {
106 int events_reported; 106 int events_reported;
107 107
108 u64 uid; 108 u64 uid;
109 u8 join_state;
109 struct list_head list; 110 struct list_head list;
110 struct sockaddr_storage addr; 111 struct sockaddr_storage addr;
111}; 112};
@@ -1317,12 +1318,20 @@ static ssize_t ucma_process_join(struct ucma_file *file,
1317 struct ucma_multicast *mc; 1318 struct ucma_multicast *mc;
1318 struct sockaddr *addr; 1319 struct sockaddr *addr;
1319 int ret; 1320 int ret;
1321 u8 join_state;
1320 1322
1321 if (out_len < sizeof(resp)) 1323 if (out_len < sizeof(resp))
1322 return -ENOSPC; 1324 return -ENOSPC;
1323 1325
1324 addr = (struct sockaddr *) &cmd->addr; 1326 addr = (struct sockaddr *) &cmd->addr;
1325 if (cmd->reserved || !cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr))) 1327 if (!cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
1328 return -EINVAL;
1329
1330 if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER)
1331 join_state = BIT(FULLMEMBER_JOIN);
1332 else if (cmd->join_flags == RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER)
1333 join_state = BIT(SENDONLY_FULLMEMBER_JOIN);
1334 else
1326 return -EINVAL; 1335 return -EINVAL;
1327 1336
1328 ctx = ucma_get_ctx(file, cmd->id); 1337 ctx = ucma_get_ctx(file, cmd->id);
@@ -1335,10 +1344,11 @@ static ssize_t ucma_process_join(struct ucma_file *file,
1335 ret = -ENOMEM; 1344 ret = -ENOMEM;
1336 goto err1; 1345 goto err1;
1337 } 1346 }
1338 1347 mc->join_state = join_state;
1339 mc->uid = cmd->uid; 1348 mc->uid = cmd->uid;
1340 memcpy(&mc->addr, addr, cmd->addr_size); 1349 memcpy(&mc->addr, addr, cmd->addr_size);
1341 ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc); 1350 ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr,
1351 join_state, mc);
1342 if (ret) 1352 if (ret)
1343 goto err2; 1353 goto err2;
1344 1354
@@ -1382,7 +1392,7 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
1382 join_cmd.uid = cmd.uid; 1392 join_cmd.uid = cmd.uid;
1383 join_cmd.id = cmd.id; 1393 join_cmd.id = cmd.id;
1384 join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); 1394 join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
1385 join_cmd.reserved = 0; 1395 join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER;
1386 memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size); 1396 memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);
1387 1397
1388 return ucma_process_join(file, &join_cmd, out_len); 1398 return ucma_process_join(file, &join_cmd, out_len);
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 384041669489..5ee7aab95eb8 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -94,6 +94,19 @@ enum ib_sa_selector {
94 IB_SA_BEST = 3 94 IB_SA_BEST = 3
95}; 95};
96 96
97/*
98 * There are 4 types of join states:
99 * FullMember, NonMember, SendOnlyNonMember, SendOnlyFullMember.
100 * The order corresponds to JoinState bits in MCMemberRecord.
101 */
102enum ib_sa_mc_join_states {
103 FULLMEMBER_JOIN,
104 NONMEMBER_JOIN,
105 SENDONLY_NONMEBER_JOIN,
106 SENDONLY_FULLMEMBER_JOIN,
107 NUM_JOIN_MEMBERSHIP_TYPES,
108};
109
97#define IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT BIT(12) 110#define IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT BIT(12)
98 111
99/* 112/*
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index afe44fde72a5..81fb1d15e8bb 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -333,11 +333,13 @@ int rdma_disconnect(struct rdma_cm_id *id);
333 * address. 333 * address.
334 * @id: Communication identifier associated with the request. 334 * @id: Communication identifier associated with the request.
335 * @addr: Multicast address identifying the group to join. 335 * @addr: Multicast address identifying the group to join.
336 * @join_state: Multicast JoinState bitmap requested by port.
337 * Bitmap is based on IB_SA_MCMEMBER_REC_JOIN_STATE bits.
336 * @context: User-defined context associated with the join request, returned 338 * @context: User-defined context associated with the join request, returned
337 * to the user through the private_data pointer in multicast events. 339 * to the user through the private_data pointer in multicast events.
338 */ 340 */
339int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, 341int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
340 void *context); 342 u8 join_state, void *context);
341 343
342/** 344/**
343 * rdma_leave_multicast - Leave the multicast group specified by the given 345 * rdma_leave_multicast - Leave the multicast group specified by the given
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
index 3066718eb120..01923d463673 100644
--- a/include/uapi/rdma/rdma_user_cm.h
+++ b/include/uapi/rdma/rdma_user_cm.h
@@ -244,12 +244,19 @@ struct rdma_ucm_join_ip_mcast {
244 __u32 id; 244 __u32 id;
245}; 245};
246 246
247/* Multicast join flags */
248enum {
249 RDMA_MC_JOIN_FLAG_FULLMEMBER,
250 RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER,
251 RDMA_MC_JOIN_FLAG_RESERVED,
252};
253
247struct rdma_ucm_join_mcast { 254struct rdma_ucm_join_mcast {
248 __u64 response; /* rdma_ucma_create_id_resp */ 255 __u64 response; /* rdma_ucma_create_id_resp */
249 __u64 uid; 256 __u64 uid;
250 __u32 id; 257 __u32 id;
251 __u16 addr_size; 258 __u16 addr_size;
252 __u16 reserved; 259 __u16 join_flags;
253 struct sockaddr_storage addr; 260 struct sockaddr_storage addr;
254}; 261};
255 262