| From eab53982661841d2b981130b307531708c637ea5 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 8 Sep 2021 13:43:28 +0200 |
| Subject: IB/cma: Do not send IGMP leaves for sendonly Multicast groups |
| |
| From: Christoph Lameter <cl@gentwo.de> |
| |
| [ Upstream commit 2cc74e1ee31d00393b6698ec80b322fd26523da4 ] |
| |
| ROCE uses IGMP for Multicast instead of the native Infiniband system where |
| joins are required in order to post messages on the Multicast group. On |
| Ethernet one can send Multicast messages to arbitrary addresses without |
| the need to subscribe to a group. |
| |
| So ROCE correctly does not send IGMP joins during rdma_join_multicast(). |
| |
| F.e. in cma_iboe_join_multicast() we see: |
| |
| if (addr->sa_family == AF_INET) { |
| if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) { |
| ib.rec.hop_limit = IPV6_DEFAULT_HOPLIMIT; |
| if (!send_only) { |
| err = cma_igmp_send(ndev, &ib.rec.mgid, |
| true); |
| } |
| } |
| } else { |
| |
| So the IGMP join is suppressed as it is unnecessary. |
| |
| However no such check is done in destroy_mc(). And therefore leaving a |
| sendonly multicast group will send an IGMP leave. |
| |
| This means that the following scenario can lead to a multicast receiver |
| unexpectedly being unsubscribed from a MC group: |
| |
| 1. Sender thread does a sendonly join on MC group X. No IGMP join |
| is sent. |
| |
| 2. Receiver thread does a regular join on the same MC Group x. |
| IGMP join is sent and the receiver begins to get messages. |
| |
| 3. Sender thread terminates and destroys MC group X. |
| IGMP leave is sent and the receiver no longer receives data. |
| |
| This patch adds the same logic for sendonly joins to destroy_mc() that is |
| also used in cma_iboe_join_multicast(). |
| |
| Fixes: ab15c95a17b3 ("IB/core: Support for CMA multicast join flags") |
| Link: https://lore.kernel.org/r/alpine.DEB.2.22.394.2109081340540.668072@gentwo.de |
| Signed-off-by: Christoph Lameter <cl@linux.com> |
| Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/infiniband/core/cma.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c |
| index a4962b499b61..3029e96161b5 100644 |
| --- a/drivers/infiniband/core/cma.c |
| +++ b/drivers/infiniband/core/cma.c |
| @@ -1814,6 +1814,8 @@ static void cma_release_port(struct rdma_id_private *id_priv) |
| static void destroy_mc(struct rdma_id_private *id_priv, |
| struct cma_multicast *mc) |
| { |
| + bool send_only = mc->join_state == BIT(SENDONLY_FULLMEMBER_JOIN); |
| + |
| if (rdma_cap_ib_mcast(id_priv->id.device, id_priv->id.port_num)) |
| ib_sa_free_multicast(mc->sa_mc); |
| |
| @@ -1830,7 +1832,10 @@ static void destroy_mc(struct rdma_id_private *id_priv, |
| |
| cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, |
| &mgid); |
| - cma_igmp_send(ndev, &mgid, false); |
| + |
| + if (!send_only) |
| + cma_igmp_send(ndev, &mgid, false); |
| + |
| dev_put(ndev); |
| } |
| |
| -- |
| 2.33.0 |
| |