From patchwork Wed Mar 25 21:20:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Somnath Kotur X-Patchwork-Id: 6088061 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 52CFEBF90F for ; Wed, 25 Mar 2015 04:56:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 346CE202C8 for ; Wed, 25 Mar 2015 04:56:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 10E6C2035C for ; Wed, 25 Mar 2015 04:56:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752230AbbCYE4U (ORCPT ); Wed, 25 Mar 2015 00:56:20 -0400 Received: from cmexedge2.emulex.com ([138.239.224.100]:2440 "EHLO CMEXEDGE2.ext.emulex.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752249AbbCYE4U (ORCPT ); Wed, 25 Mar 2015 00:56:20 -0400 Received: from CMEXHTCAS2.ad.emulex.com (138.239.115.218) by CMEXEDGE2.ext.emulex.com (138.239.224.100) with Microsoft SMTP Server (TLS) id 14.3.210.2; Tue, 24 Mar 2015 21:56:35 -0700 Received: from codebrowse.emulex.com (10.192.207.129) by smtp.emulex.com (138.239.115.208) with Microsoft SMTP Server id 14.3.210.2; Tue, 24 Mar 2015 21:56:13 -0700 From: Somnath Kotur To: CC: , Moni Shoua , "Somnath Kotur" Subject: [PATCH v3 for-next 33/33] IB/cma: Join and leave multicast groups with IGMP Date: Thu, 26 Mar 2015 02:50:22 +0530 X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1427318422-12004-1-git-send-email-somnath.kotur@emulex.com> References: <1427318422-12004-1-git-send-email-somnath.kotur@emulex.com> MIME-Version: 1.0 Message-ID: <2334f3f5-0847-433b-ae77-1712894775a7@CMEXHTCAS2.ad.emulex.com> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DATE_IN_FUTURE_12_24, RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Moni Shoua Since RoCEv2 is a protocol over IP header it is required to send IGMP join and leave requests to the network when joining and leaving multicast groups. Signed-off-by: Moni Shoua Signed-off-by: Somnath Kotur --- drivers/infiniband/core/cma.c | 78 ++++++++++++++++++++++++++++++++++--- drivers/infiniband/core/multicast.c | 18 ++++++++- include/rdma/ib_sa.h | 3 ++ 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 6f345e2..8f997d7 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,7 @@ struct cma_multicast { void *context; struct sockaddr_storage addr; struct kref mcref; + bool igmp_joined; }; struct cma_work { @@ -283,6 +285,26 @@ static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); } +static int cma_igmp_send(struct net_device *ndev, union ib_gid *mgid, bool join) +{ + struct in_device *in_dev = NULL; + + if (ndev) { + rtnl_lock(); + in_dev = __in_dev_get_rtnl(ndev); + if (in_dev) { + if (join) + ip_mc_inc_group(in_dev, + *(__be32 *)(mgid->raw+12)); + else + ip_mc_dec_group(in_dev, + *(__be32 *)(mgid->raw+12)); + } + rtnl_unlock(); + } + return (in_dev) ? 0 : -ENODEV; +} + static void cma_attach_to_dev(struct rdma_id_private *id_priv, struct cma_device *cma_dev) { @@ -1076,6 +1098,20 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv) kfree(mc); break; case IB_LINK_LAYER_ETHERNET: + if (mc->igmp_joined) { + struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; + struct net_device *ndev = NULL; + + if (dev_addr->bound_dev_if) + ndev = dev_get_by_index(&init_net, + dev_addr->bound_dev_if); + if (ndev) { + cma_igmp_send(ndev, + &mc->multicast.ib->rec.mgid, + false); + dev_put(ndev); + } + } kref_put(&mc->mcref, release_mc); break; default: @@ -3356,7 +3392,7 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, { struct iboe_mcast_work *work; struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; - int err; + int err = 0; struct sockaddr *addr = (struct sockaddr *)&mc->addr; struct net_device *ndev = NULL; @@ -3388,13 +3424,30 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, mc->multicast.ib->rec.rate = iboe_get_rate(ndev); mc->multicast.ib->rec.hop_limit = 1; mc->multicast.ib->rec.mtu = iboe_get_mtu(ndev->mtu); + mc->multicast.ib->rec.ifindex = dev_addr->bound_dev_if; + mc->multicast.ib->rec.net = &init_net; + rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr, + &mc->multicast.ib->rec.port_gid); + + if (addr->sa_family == AF_INET) { + mc->multicast.ib->rec.gid_type = + id_priv->cma_dev->default_gid_type; + if (mc->multicast.ib->rec.gid_type == IB_GID_TYPE_ROCE_V2) + err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, + true); + if (!err) { + mc->igmp_joined = true; + mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT; + } + } else { + mc->multicast.ib->rec.gid_type = IB_GID_TYPE_IB; + } dev_put(ndev); - if (!mc->multicast.ib->rec.mtu) { + if (err || !mc->multicast.ib->rec.mtu) { err = -EINVAL; goto out2; } - rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr, - &mc->multicast.ib->rec.port_gid); + work->id = id_priv; work->mc = mc; INIT_WORK(&work->work, iboe_mcast_work_handler); @@ -3429,7 +3482,7 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, memcpy(&mc->addr, addr, rdma_addr_size(addr)); mc->context = context; mc->id_priv = id_priv; - + mc->igmp_joined = false; spin_lock(&id_priv->lock); list_add(&mc->list, &id_priv->mc_list); spin_unlock(&id_priv->lock); @@ -3486,6 +3539,21 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) kfree(mc); break; case IB_LINK_LAYER_ETHERNET: + if (mc->igmp_joined) { + struct rdma_dev_addr *dev_addr = &id->route.addr.dev_addr; + struct net_device *ndev = NULL; + + if (dev_addr->bound_dev_if) + ndev = dev_get_by_index(&init_net, + dev_addr->bound_dev_if); + if (ndev) { + cma_igmp_send(ndev, + &mc->multicast.ib->rec.mgid, + false); + dev_put(ndev); + } + mc->igmp_joined = false; + } kref_put(&mc->mcref, release_mc); break; default: diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index f1927f1..9cbee6c 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c @@ -729,8 +729,22 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num, u16 gid_index; u8 p; - ret = ib_find_cached_gid(device, &rec->port_gid, IB_GID_TYPE_IB, - NULL, 0, &p, &gid_index); + switch (rdma_port_get_link_layer(device, port_num)) { + case IB_LINK_LAYER_ETHERNET: + ret = ib_find_cached_gid_by_port(device, &rec->port_gid, + rec->gid_type, port_num, + rec->net, rec->ifindex, + &gid_index); + break; + case IB_LINK_LAYER_INFINIBAND: + ret = ib_find_cached_gid(device, &rec->port_gid, + IB_GID_TYPE_IB, NULL, 0, &p, + &gid_index); + break; + default: + ret = -EINVAL; + } + if (ret) return ret; diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index 61bc231..653d538 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -198,6 +198,9 @@ struct ib_sa_mcmember_rec { u8 scope; u8 join_state; int proxy_join; + int ifindex; + struct net *net; + enum ib_gid_type gid_type; }; /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1 */