From patchwork Thu Feb 19 22:02:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Somnath Kotur X-Patchwork-Id: 5850461 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 A07FEBF440 for ; Thu, 19 Feb 2015 05:39:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B76DE200F4 for ; Thu, 19 Feb 2015 05:39:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BFF7620211 for ; Thu, 19 Feb 2015 05:39:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751491AbbBSFji (ORCPT ); Thu, 19 Feb 2015 00:39:38 -0500 Received: from cmexedge1.emulex.com ([138.239.224.99]:59837 "EHLO CMEXEDGE1.ext.emulex.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750848AbbBSFjh (ORCPT ); Thu, 19 Feb 2015 00:39:37 -0500 Received: from CMEXHTCAS2.ad.emulex.com (138.239.115.218) by CMEXEDGE1.ext.emulex.com (138.239.224.99) with Microsoft SMTP Server (TLS) id 14.3.174.1; Wed, 18 Feb 2015 21:39:38 -0800 Received: from codebrowse.emulex.com (10.192.207.129) by smtp.emulex.com (138.239.115.208) with Microsoft SMTP Server id 14.3.174.1; Wed, 18 Feb 2015 21:39:28 -0800 From: Somnath Kotur To: CC: , Moni Shoua , "Somnath Kotur" Subject: [PATCH 30/30] IB/cma: Join and leave multicast groups with IGMP Date: Fri, 20 Feb 2015 03:32:45 +0530 X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1424383365-19337-1-git-send-email-somnath.kotur@emulex.com> References: <1424383365-19337-1-git-send-email-somnath.kotur@emulex.com> MIME-Version: 1.0 Message-ID: <91da5137-4651-4991-852e-d57faeabe6a5@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 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 74 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 50635fe..6e658e8 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,7 @@ struct rdma_id_private { u8 reuseaddr; u8 afonly; enum ib_gid_type gid_type; + bool igmp_joined; }; struct cma_multicast { @@ -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) { @@ -585,6 +607,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, INIT_LIST_HEAD(&id_priv->listen_list); INIT_LIST_HEAD(&id_priv->mc_list); get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); + id_priv->igmp_joined = false; return &id_priv->id; } @@ -1076,6 +1099,20 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv) kfree(mc); break; case IB_LINK_LAYER_ETHERNET: + if (id_priv->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 +3393,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 +3425,31 @@ 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); + rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr, + &mc->multicast.ib->rec.port_gid); + + if (addr->sa_family == AF_INET) { + u16 sgid_index; + + err = ib_find_cached_gid_by_port(id_priv->cma_dev->device, + &mc->multicast.ib->rec.port_gid, + IB_GID_TYPE_ROCE_V2, + id_priv->id.port_num, + &init_net, dev_addr->bound_dev_if, + &sgid_index); + if (!err) + err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, true); + if (!err) { + id_priv->igmp_joined = true; + mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT; + } + } 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); @@ -3486,6 +3541,21 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) kfree(mc); break; case IB_LINK_LAYER_ETHERNET: + if (id_priv->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); + } + id_priv->igmp_joined = false; + } kref_put(&mc->mcref, release_mc); break; default: