2005-04-17 05:20:36 +07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
2005-08-11 13:03:10 +07:00
|
|
|
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
|
|
|
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
|
2005-04-17 05:20:36 +07:00
|
|
|
*
|
|
|
|
* This software is available to you under a choice of one of two
|
|
|
|
* licenses. You may choose to be licensed under the terms of the GNU
|
|
|
|
* General Public License (GPL) Version 2, available from the file
|
|
|
|
* COPYING in the main directory of this source tree, or the
|
|
|
|
* OpenIB.org BSD license below:
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or
|
|
|
|
* without modification, are permitted provided that the following
|
|
|
|
* conditions are met:
|
|
|
|
*
|
|
|
|
* - Redistributions of source code must retain the above
|
|
|
|
* copyright notice, this list of conditions and the following
|
|
|
|
* disclaimer.
|
|
|
|
*
|
|
|
|
* - Redistributions in binary form must reproduce the above
|
|
|
|
* copyright notice, this list of conditions and the following
|
|
|
|
* disclaimer in the documentation and/or other materials
|
|
|
|
* provided with the distribution.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <linux/rtnetlink.h>
|
2011-08-30 23:32:52 +07:00
|
|
|
#include <linux/moduleparam.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <linux/ip.h>
|
|
|
|
#include <linux/in.h>
|
|
|
|
#include <linux/igmp.h>
|
|
|
|
#include <linux/inetdevice.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/completion.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 15:04:11 +07:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2005-12-27 11:43:12 +07:00
|
|
|
#include <net/dst.h>
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
#include "ipoib.h"
|
|
|
|
|
|
|
|
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
|
|
|
|
static int mcast_debug_level;
|
|
|
|
|
|
|
|
module_param(mcast_debug_level, int, 0644);
|
|
|
|
MODULE_PARM_DESC(mcast_debug_level,
|
|
|
|
"Enable multicast debug tracing if > 0");
|
|
|
|
#endif
|
|
|
|
|
2006-01-14 05:51:39 +07:00
|
|
|
static DEFINE_MUTEX(mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
struct ipoib_mcast_iter {
|
|
|
|
struct net_device *dev;
|
|
|
|
union ib_gid mgid;
|
|
|
|
unsigned long created;
|
|
|
|
unsigned int queuelen;
|
|
|
|
unsigned int complete;
|
|
|
|
unsigned int send_only;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ipoib_mcast_free(struct ipoib_mcast *mcast)
|
|
|
|
{
|
|
|
|
struct net_device *dev = mcast->dev;
|
2006-01-18 03:19:40 +07:00
|
|
|
int tx_dropped = 0;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
IPoIB: Use a private hash table for path lookup in xmit path
Dave Miller <davem@davemloft.net> provided a detailed description of
why the way IPoIB is using neighbours for its own ipoib_neigh struct
is buggy:
Any time an ipoib_neigh is changed, a sequence like the following is made:
spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
* path->ah will always hold one more reference,
* so ipoib_put_ah() will never do more than
* decrement the ref count.
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, n, dev);
This doesn't work, because you're leaving a stale pointer to the freed up
ipoib_neigh in the special neigh->ha pointer cookie. Yes, it even fails
with all the locking done to protect _changes_ to *ipoib_neigh(n), and
with the code in ipoib_neigh_free() that NULLs out the pointer.
The core issue is that read side calls to *to_ipoib_neigh(n) are not
being synchronized at all, they are performed without any locking. So
whether we hold the lock or not when making changes to *ipoib_neigh(n)
you still can have threads see references to freed up ipoib_neigh
objects.
cpu 1 cpu 2
n = *ipoib_neigh()
*ipoib_neigh() = NULL
kfree(n)
n->foo == OOPS
[..]
Perhaps the ipoib code can have a private path database it manages
entirely itself, which holds all the necessary information and is
looked up by some generic key which is available easily at transmit
time and does not involve generic neighbour entries.
See <http://marc.info/?l=linux-rdma&m=132812793105624&w=2> and
<http://marc.info/?l=linux-rdma&w=2&r=1&s=allows+references+to+freed+memory&q=b>
for the full discussion.
This patch aims to solve the race conditions found in the IPoIB driver.
The patch removes the connection between the core networking neighbour
structure and the ipoib_neigh structure. In addition to avoiding the
race described above, it allows us to handle SKBs carrying IP packets
that don't have any associated neighbour.
We add an ipoib_neigh hash table with N buckets where the key is the
destination hardware address. The ipoib_neigh is fetched from the
hash table and instead of the stashed location in the neighbour
structure. The hash table uses both RCU and reference counting to
guarantee that no ipoib_neigh instance is ever deleted while in use.
Fetching the ipoib_neigh structure instance from the hash also makes
the special code in ipoib_start_xmit that handles remote and local
bonding failover redundant.
Aged ipoib_neigh instances are deleted by a garbage collection task
that runs every M seconds and deletes every ipoib_neigh instance that
was idle for at least 2*M seconds. The deletion is safe since the
ipoib_neigh instances are protected using RCU and reference count
mechanisms.
The number of buckets (N) and frequency of running the GC thread (M),
are taken from the exported arb_tbl.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2012-07-25 00:05:22 +07:00
|
|
|
/* remove all neigh connected to this mcast */
|
|
|
|
ipoib_del_neighs_by_gid(dev, mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
if (mcast->ah)
|
|
|
|
ipoib_put_ah(mcast->ah);
|
|
|
|
|
2006-01-18 03:19:40 +07:00
|
|
|
while (!skb_queue_empty(&mcast->pkt_queue)) {
|
|
|
|
++tx_dropped;
|
2005-11-08 01:49:38 +07:00
|
|
|
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
|
2006-01-18 03:19:40 +07:00
|
|
|
}
|
|
|
|
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_lock_bh(dev);
|
2007-09-29 05:33:51 +07:00
|
|
|
dev->stats.tx_dropped += tx_dropped;
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_unlock_bh(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
kfree(mcast);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
|
|
|
|
int can_sleep)
|
|
|
|
{
|
|
|
|
struct ipoib_mcast *mcast;
|
|
|
|
|
2005-11-02 22:23:14 +07:00
|
|
|
mcast = kzalloc(sizeof *mcast, can_sleep ? GFP_KERNEL : GFP_ATOMIC);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (!mcast)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
mcast->dev = dev;
|
|
|
|
mcast->created = jiffies;
|
2005-09-19 03:47:53 +07:00
|
|
|
mcast->backoff = 1;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
INIT_LIST_HEAD(&mcast->list);
|
|
|
|
INIT_LIST_HEAD(&mcast->neigh_list);
|
|
|
|
skb_queue_head_init(&mcast->pkt_queue);
|
|
|
|
|
|
|
|
return mcast;
|
|
|
|
}
|
|
|
|
|
2006-05-29 23:14:05 +07:00
|
|
|
static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
struct rb_node *n = priv->multicast_tree.rb_node;
|
|
|
|
|
|
|
|
while (n) {
|
|
|
|
struct ipoib_mcast *mcast;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
mcast = rb_entry(n, struct ipoib_mcast, rb_node);
|
|
|
|
|
2006-05-29 23:14:05 +07:00
|
|
|
ret = memcmp(mgid, mcast->mcmember.mgid.raw,
|
2005-04-17 05:20:36 +07:00
|
|
|
sizeof (union ib_gid));
|
|
|
|
if (ret < 0)
|
|
|
|
n = n->rb_left;
|
|
|
|
else if (ret > 0)
|
|
|
|
n = n->rb_right;
|
|
|
|
else
|
|
|
|
return mcast;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __ipoib_mcast_add(struct net_device *dev, struct ipoib_mcast *mcast)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
struct rb_node **n = &priv->multicast_tree.rb_node, *pn = NULL;
|
|
|
|
|
|
|
|
while (*n) {
|
|
|
|
struct ipoib_mcast *tmcast;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
pn = *n;
|
|
|
|
tmcast = rb_entry(pn, struct ipoib_mcast, rb_node);
|
|
|
|
|
|
|
|
ret = memcmp(mcast->mcmember.mgid.raw, tmcast->mcmember.mgid.raw,
|
|
|
|
sizeof (union ib_gid));
|
|
|
|
if (ret < 0)
|
|
|
|
n = &pn->rb_left;
|
|
|
|
else if (ret > 0)
|
|
|
|
n = &pn->rb_right;
|
|
|
|
else
|
|
|
|
return -EEXIST;
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_link_node(&mcast->rb_node, pn, n);
|
|
|
|
rb_insert_color(&mcast->rb_node, &priv->multicast_tree);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
|
|
|
|
struct ib_sa_mcmember_rec *mcmember)
|
|
|
|
{
|
|
|
|
struct net_device *dev = mcast->dev;
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
2006-02-28 11:47:43 +07:00
|
|
|
struct ipoib_ah *ah;
|
2005-04-17 05:20:36 +07:00
|
|
|
int ret;
|
2008-07-15 13:48:50 +07:00
|
|
|
int set_qkey = 0;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
mcast->mcmember = *mcmember;
|
|
|
|
|
2012-08-30 14:01:30 +07:00
|
|
|
/* Set the multicast MTU and cached Q_Key before we attach if it's
|
|
|
|
* the broadcast group.
|
|
|
|
*/
|
2005-04-17 05:20:36 +07:00
|
|
|
if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
|
|
|
|
sizeof (union ib_gid))) {
|
2008-05-21 05:41:09 +07:00
|
|
|
spin_lock_irq(&priv->lock);
|
|
|
|
if (!priv->broadcast) {
|
|
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
return -EAGAIN;
|
|
|
|
}
|
2012-08-30 14:01:30 +07:00
|
|
|
priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
|
2005-04-17 05:20:36 +07:00
|
|
|
priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
|
2008-05-21 05:41:09 +07:00
|
|
|
spin_unlock_irq(&priv->lock);
|
2005-04-17 05:20:36 +07:00
|
|
|
priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
|
2008-07-15 13:48:50 +07:00
|
|
|
set_qkey = 1;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
|
|
|
|
if (test_and_set_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_warn(priv, "multicast group %pI6 already attached\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ipoib_mcast_attach(dev, be16_to_cpu(mcast->mcmember.mlid),
|
2008-07-15 13:48:50 +07:00
|
|
|
&mcast->mcmember.mgid, set_qkey);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (ret < 0) {
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_warn(priv, "couldn't attach QP to multicast group %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct ib_ah_attr av = {
|
|
|
|
.dlid = be16_to_cpu(mcast->mcmember.mlid),
|
|
|
|
.port_num = priv->port,
|
|
|
|
.sl = mcast->mcmember.sl,
|
|
|
|
.ah_flags = IB_AH_GRH,
|
2006-04-10 23:43:47 +07:00
|
|
|
.static_rate = mcast->mcmember.rate,
|
2005-04-17 05:20:36 +07:00
|
|
|
.grh = {
|
|
|
|
.flow_label = be32_to_cpu(mcast->mcmember.flow_label),
|
|
|
|
.hop_limit = mcast->mcmember.hop_limit,
|
|
|
|
.sgid_index = 0,
|
|
|
|
.traffic_class = mcast->mcmember.traffic_class
|
|
|
|
}
|
|
|
|
};
|
|
|
|
av.grh.dgid = mcast->mcmember.mgid;
|
|
|
|
|
2006-02-28 11:47:43 +07:00
|
|
|
ah = ipoib_create_ah(dev, priv->pd, &av);
|
2011-11-21 20:43:54 +07:00
|
|
|
if (IS_ERR(ah)) {
|
|
|
|
ipoib_warn(priv, "ib_address_create failed %ld\n",
|
|
|
|
-PTR_ERR(ah));
|
|
|
|
/* use original error */
|
|
|
|
return PTR_ERR(ah);
|
2005-04-17 05:20:36 +07:00
|
|
|
} else {
|
2006-07-24 14:42:00 +07:00
|
|
|
spin_lock_irq(&priv->lock);
|
|
|
|
mcast->ah = ah;
|
|
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "MGID %pI6 AV %p, LID 0x%04x, SL %d\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw,
|
2005-04-17 05:20:36 +07:00
|
|
|
mcast->ah->ah,
|
|
|
|
be16_to_cpu(mcast->mcmember.mlid),
|
|
|
|
mcast->mcmember.sl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* actually send any queued packets */
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_lock_bh(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
while (!skb_queue_empty(&mcast->pkt_queue)) {
|
|
|
|
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
|
2011-07-18 13:09:49 +07:00
|
|
|
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_unlock_bh(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
skb->dev = dev;
|
|
|
|
if (dev_queue_xmit(skb))
|
|
|
|
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
|
2012-02-07 21:51:21 +07:00
|
|
|
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_lock_bh(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_unlock_bh(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
static int
|
2005-04-17 05:20:36 +07:00
|
|
|
ipoib_mcast_sendonly_join_complete(int status,
|
2007-02-16 08:00:17 +07:00
|
|
|
struct ib_sa_multicast *multicast)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
2007-02-16 08:00:17 +07:00
|
|
|
struct ipoib_mcast *mcast = multicast->context;
|
2005-04-17 05:20:36 +07:00
|
|
|
struct net_device *dev = mcast->dev;
|
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
/* We trap for port events ourselves. */
|
|
|
|
if (status == -ENETRESET)
|
2015-01-31 06:39:20 +07:00
|
|
|
return 0;
|
2007-02-16 08:00:17 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
if (!status)
|
2007-02-16 08:00:17 +07:00
|
|
|
status = ipoib_mcast_join_finish(mcast, &multicast->rec);
|
|
|
|
|
|
|
|
if (status) {
|
2005-04-17 05:20:36 +07:00
|
|
|
if (mcast->logcount++ < 20)
|
2015-01-31 06:39:20 +07:00
|
|
|
ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for %pI6, status %d\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw, status);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* Flush out any queued packets */
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_lock_bh(dev);
|
2006-01-18 03:19:40 +07:00
|
|
|
while (!skb_queue_empty(&mcast->pkt_queue)) {
|
2007-09-29 05:33:51 +07:00
|
|
|
++dev->stats.tx_dropped;
|
2005-11-08 01:49:38 +07:00
|
|
|
dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
|
2006-01-18 03:19:40 +07:00
|
|
|
}
|
2008-10-01 00:36:21 +07:00
|
|
|
netif_tx_unlock_bh(dev);
|
2015-01-31 06:39:20 +07:00
|
|
|
|
|
|
|
/* Clear the busy flag so we try again */
|
|
|
|
status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
|
|
|
|
&mcast->flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
2007-02-16 08:00:17 +07:00
|
|
|
return status;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
|
|
|
|
{
|
|
|
|
struct net_device *dev = mcast->dev;
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
struct ib_sa_mcmember_rec rec = {
|
|
|
|
#if 0 /* Some SMs don't support send-only yet */
|
|
|
|
.join_state = 4
|
|
|
|
#else
|
|
|
|
.join_state = 1
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
|
2015-01-31 06:39:20 +07:00
|
|
|
ipoib_dbg_mcast(priv, "device shutting down, no multicast joins\n");
|
2005-04-17 05:20:36 +07:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2015-01-31 06:39:20 +07:00
|
|
|
if (test_and_set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) {
|
|
|
|
ipoib_dbg_mcast(priv, "multicast entry busy, skipping\n");
|
2005-04-17 05:20:36 +07:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
|
|
|
rec.mgid = mcast->mcmember.mgid;
|
|
|
|
rec.port_gid = priv->local_gid;
|
2005-08-14 11:05:57 +07:00
|
|
|
rec.pkey = cpu_to_be16(priv->pkey);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,
|
|
|
|
priv->port, &rec,
|
|
|
|
IB_SA_MCMEMBER_REC_MGID |
|
|
|
|
IB_SA_MCMEMBER_REC_PORT_GID |
|
|
|
|
IB_SA_MCMEMBER_REC_PKEY |
|
|
|
|
IB_SA_MCMEMBER_REC_JOIN_STATE,
|
|
|
|
GFP_ATOMIC,
|
|
|
|
ipoib_mcast_sendonly_join_complete,
|
|
|
|
mcast);
|
|
|
|
if (IS_ERR(mcast->mc)) {
|
|
|
|
ret = PTR_ERR(mcast->mc);
|
|
|
|
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
2015-01-31 06:39:20 +07:00
|
|
|
ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
|
|
|
|
ret);
|
2005-04-17 05:20:36 +07:00
|
|
|
} else {
|
2015-01-31 06:39:20 +07:00
|
|
|
ipoib_dbg_mcast(priv, "no multicast record for %pI6, starting join\n",
|
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-09-17 01:57:45 +07:00
|
|
|
void ipoib_mcast_carrier_on_task(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
|
|
|
|
carrier_on_task);
|
2009-09-25 02:01:05 +07:00
|
|
|
struct ib_port_attr attr;
|
2008-09-17 01:57:45 +07:00
|
|
|
|
2009-09-25 02:01:05 +07:00
|
|
|
if (ib_query_port(priv->ca, priv->port, &attr) ||
|
|
|
|
attr.state != IB_PORT_ACTIVE) {
|
|
|
|
ipoib_dbg(priv, "Keeping carrier off until IB port is active\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-02-22 07:27:02 +07:00
|
|
|
/*
|
|
|
|
* Take rtnl_lock to avoid racing with ipoib_stop() and
|
|
|
|
* turning the carrier back on while a device is being
|
|
|
|
* removed. However, ipoib_stop() will attempt to flush
|
|
|
|
* the workqueue while holding the rtnl lock, so loop
|
|
|
|
* on trylock until either we get the lock or we see
|
|
|
|
* FLAG_OPER_UP go away as that signals that we are bailing
|
|
|
|
* and can safely ignore the carrier on work.
|
|
|
|
*/
|
|
|
|
while (!rtnl_trylock()) {
|
|
|
|
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
msleep(20);
|
|
|
|
}
|
2015-02-22 07:27:01 +07:00
|
|
|
if (!ipoib_cm_admin_enabled(priv->dev))
|
|
|
|
dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu));
|
2008-09-17 01:57:45 +07:00
|
|
|
netif_carrier_on(priv->dev);
|
|
|
|
rtnl_unlock();
|
|
|
|
}
|
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
static int ipoib_mcast_join_complete(int status,
|
|
|
|
struct ib_sa_multicast *multicast)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
2007-02-16 08:00:17 +07:00
|
|
|
struct ipoib_mcast *mcast = multicast->context;
|
2005-04-17 05:20:36 +07:00
|
|
|
struct net_device *dev = mcast->dev;
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "join completion for %pI6 (status %d)\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw, status);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
/* We trap for port events ourselves. */
|
2015-01-31 06:39:20 +07:00
|
|
|
if (status == -ENETRESET) {
|
|
|
|
status = 0;
|
2013-10-16 21:37:51 +07:00
|
|
|
goto out;
|
2015-01-31 06:39:20 +07:00
|
|
|
}
|
2007-02-16 08:00:17 +07:00
|
|
|
|
|
|
|
if (!status)
|
|
|
|
status = ipoib_mcast_join_finish(mcast, &multicast->rec);
|
|
|
|
|
|
|
|
if (!status) {
|
2005-09-19 03:47:53 +07:00
|
|
|
mcast->backoff = 1;
|
2015-01-31 06:39:20 +07:00
|
|
|
mutex_lock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_delayed_work(priv->wq, &priv->mcast_task, 0);
|
2015-01-31 06:39:20 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2007-03-09 05:59:30 +07:00
|
|
|
|
2008-09-17 01:57:45 +07:00
|
|
|
/*
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
* Defer carrier on work to priv->wq to avoid a
|
2008-09-17 01:57:45 +07:00
|
|
|
* deadlock on rtnl_lock here.
|
|
|
|
*/
|
|
|
|
if (mcast == priv->broadcast)
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_work(priv->wq, &priv->carrier_on_task);
|
2006-03-03 02:07:47 +07:00
|
|
|
|
2015-01-31 06:39:20 +07:00
|
|
|
status = 0;
|
|
|
|
goto out;
|
IPoIB: fix MCAST_FLAG_BUSY usage
Commit a9c8ba5884 ("IPoIB: Fix usage of uninitialized multicast
objects") added a new flag MCAST_JOIN_STARTED, but was not very strict
in how it was used. We didn't always initialize the completion struct
before we set the flag, and we didn't always call complete on the
completion struct from all paths that complete it. This made it less
than totally effective, and certainly made its use confusing. And in
the flush function we would use the presence of this flag to signal
that we should wait on the completion struct, but we never cleared
this flag, ever. This is further muddied by the fact that we overload
the MCAST_FLAG_BUSY flag to mean two different things: we have a join
in flight, and we have succeeded in getting an ib_sa_join_multicast.
In order to make things clearer and aid in resolving the rtnl deadlock
bug I've been chasing, I cleaned this up a bit.
1) Remove the MCAST_JOIN_STARTED flag entirely
2) Un-overload MCAST_FLAG_BUSY so it now only means a join is in-flight
3) Test on mcast->mc directly to see if we have completed
ib_sa_join_multicast (using IS_ERR_OR_NULL)
4) Make sure that before setting MCAST_FLAG_BUSY we always initialize
the mcast->done completion struct
5) Make sure that before calling complete(&mcast->done), we always clear
the MCAST_FLAG_BUSY bit
6) Take the mcast_mutex before we call ib_sa_multicast_join and also
take the mutex in our join callback. This forces
ib_sa_multicast_join to return and set mcast->mc before we process
the callback. This way, our callback can safely clear mcast->mc
if there is an error on the join and we will do the right thing as
a result in mcast_dev_flush.
7) Because we need the mutex to synchronize mcast->mc, we can no
longer call mcast_sendonly_join directly from mcast_send and
instead must add sendonly join processing to the mcast_join_task
A number of different races are resolved with these changes. These
races existed with the old MCAST_FLAG_BUSY usage, the
MCAST_JOIN_STARTED flag was an attempt to address them, and while it
helped, a determined effort could still trip things up.
One race looks something like this:
Thread 1 Thread 2
ib_sa_join_multicast (as part of running restart mcast task)
alloc member
call callback
ifconfig ib0 down
wait_for_completion
callback call completes
wait_for_completion in
mcast_dev_flush completes
mcast->mc is PTR_ERR_OR_NULL
so we skip ib_sa_leave_multicast
return from callback
return from ib_sa_join_multicast
set mcast->mc = return from ib_sa_multicast
We now have a permanently unbalanced join/leave issue that trips up the
refcounting in core/multicast.c
Another like this:
Thread 1 Thread 2 Thread 3
ib_sa_multicast_join
ifconfig ib0 down
priv->broadcast = NULL
join_complete
wait_for_completion
mcast->mc is not yet set, so don't clear
return from ib_sa_join_multicast and set mcast->mc
complete
return -EAGAIN (making mcast->mc invalid)
call ib_sa_multicast_leave
on invalid mcast->mc, hang
forever
By holding the mutex around ib_sa_multicast_join and taking the mutex
early in the callback, we force mcast->mc to be valid at the time we
run the callback. This allows us to clear mcast->mc if there is an
error and the join is going to fail. We do this before we complete
the mcast. In this way, mcast_dev_flush always sees consistent state
in regards to mcast->mc membership at the time that the
wait_for_completion() returns.
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2014-12-10 23:47:00 +07:00
|
|
|
}
|
2015-01-31 06:39:20 +07:00
|
|
|
|
|
|
|
if (mcast->logcount++ < 20) {
|
|
|
|
if (status == -ETIMEDOUT || status == -EAGAIN) {
|
|
|
|
ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n",
|
|
|
|
mcast->mcmember.mgid.raw, status);
|
|
|
|
} else {
|
|
|
|
ipoib_warn(priv, "multicast join failed for %pI6, status %d\n",
|
|
|
|
mcast->mcmember.mgid.raw, status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mcast->backoff *= 2;
|
|
|
|
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
|
|
|
|
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
|
|
|
|
|
|
|
|
/* Clear the busy flag so we try again */
|
|
|
|
status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
|
|
|
|
|
|
|
mutex_lock(&mcast_mutex);
|
2006-03-03 02:07:47 +07:00
|
|
|
spin_lock_irq(&priv->lock);
|
2015-01-31 06:39:20 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_delayed_work(priv->wq, &priv->mcast_task,
|
2007-02-16 08:00:17 +07:00
|
|
|
mcast->backoff * HZ);
|
2006-03-03 02:07:47 +07:00
|
|
|
spin_unlock_irq(&priv->lock);
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2015-01-31 06:39:20 +07:00
|
|
|
out:
|
|
|
|
complete(&mcast->done);
|
2007-02-16 08:00:17 +07:00
|
|
|
return status;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
|
|
|
|
int create)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
struct ib_sa_mcmember_rec rec = {
|
|
|
|
.join_state = 1
|
|
|
|
};
|
|
|
|
ib_sa_comp_mask comp_mask;
|
|
|
|
int ret = 0;
|
|
|
|
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
rec.mgid = mcast->mcmember.mgid;
|
|
|
|
rec.port_gid = priv->local_gid;
|
2005-08-14 11:05:57 +07:00
|
|
|
rec.pkey = cpu_to_be16(priv->pkey);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
comp_mask =
|
|
|
|
IB_SA_MCMEMBER_REC_MGID |
|
|
|
|
IB_SA_MCMEMBER_REC_PORT_GID |
|
|
|
|
IB_SA_MCMEMBER_REC_PKEY |
|
|
|
|
IB_SA_MCMEMBER_REC_JOIN_STATE;
|
|
|
|
|
|
|
|
if (create) {
|
|
|
|
comp_mask |=
|
2006-09-23 05:22:56 +07:00
|
|
|
IB_SA_MCMEMBER_REC_QKEY |
|
|
|
|
IB_SA_MCMEMBER_REC_MTU_SELECTOR |
|
|
|
|
IB_SA_MCMEMBER_REC_MTU |
|
|
|
|
IB_SA_MCMEMBER_REC_TRAFFIC_CLASS |
|
|
|
|
IB_SA_MCMEMBER_REC_RATE_SELECTOR |
|
|
|
|
IB_SA_MCMEMBER_REC_RATE |
|
|
|
|
IB_SA_MCMEMBER_REC_SL |
|
|
|
|
IB_SA_MCMEMBER_REC_FLOW_LABEL |
|
|
|
|
IB_SA_MCMEMBER_REC_HOP_LIMIT;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
rec.qkey = priv->broadcast->mcmember.qkey;
|
2006-09-23 05:22:56 +07:00
|
|
|
rec.mtu_selector = IB_SA_EQ;
|
|
|
|
rec.mtu = priv->broadcast->mcmember.mtu;
|
|
|
|
rec.traffic_class = priv->broadcast->mcmember.traffic_class;
|
|
|
|
rec.rate_selector = IB_SA_EQ;
|
|
|
|
rec.rate = priv->broadcast->mcmember.rate;
|
2005-04-17 05:20:36 +07:00
|
|
|
rec.sl = priv->broadcast->mcmember.sl;
|
|
|
|
rec.flow_label = priv->broadcast->mcmember.flow_label;
|
2006-09-23 05:22:56 +07:00
|
|
|
rec.hop_limit = priv->broadcast->mcmember.hop_limit;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
IPoIB: fix MCAST_FLAG_BUSY usage
Commit a9c8ba5884 ("IPoIB: Fix usage of uninitialized multicast
objects") added a new flag MCAST_JOIN_STARTED, but was not very strict
in how it was used. We didn't always initialize the completion struct
before we set the flag, and we didn't always call complete on the
completion struct from all paths that complete it. This made it less
than totally effective, and certainly made its use confusing. And in
the flush function we would use the presence of this flag to signal
that we should wait on the completion struct, but we never cleared
this flag, ever. This is further muddied by the fact that we overload
the MCAST_FLAG_BUSY flag to mean two different things: we have a join
in flight, and we have succeeded in getting an ib_sa_join_multicast.
In order to make things clearer and aid in resolving the rtnl deadlock
bug I've been chasing, I cleaned this up a bit.
1) Remove the MCAST_JOIN_STARTED flag entirely
2) Un-overload MCAST_FLAG_BUSY so it now only means a join is in-flight
3) Test on mcast->mc directly to see if we have completed
ib_sa_join_multicast (using IS_ERR_OR_NULL)
4) Make sure that before setting MCAST_FLAG_BUSY we always initialize
the mcast->done completion struct
5) Make sure that before calling complete(&mcast->done), we always clear
the MCAST_FLAG_BUSY bit
6) Take the mcast_mutex before we call ib_sa_multicast_join and also
take the mutex in our join callback. This forces
ib_sa_multicast_join to return and set mcast->mc before we process
the callback. This way, our callback can safely clear mcast->mc
if there is an error on the join and we will do the right thing as
a result in mcast_dev_flush.
7) Because we need the mutex to synchronize mcast->mc, we can no
longer call mcast_sendonly_join directly from mcast_send and
instead must add sendonly join processing to the mcast_join_task
A number of different races are resolved with these changes. These
races existed with the old MCAST_FLAG_BUSY usage, the
MCAST_JOIN_STARTED flag was an attempt to address them, and while it
helped, a determined effort could still trip things up.
One race looks something like this:
Thread 1 Thread 2
ib_sa_join_multicast (as part of running restart mcast task)
alloc member
call callback
ifconfig ib0 down
wait_for_completion
callback call completes
wait_for_completion in
mcast_dev_flush completes
mcast->mc is PTR_ERR_OR_NULL
so we skip ib_sa_leave_multicast
return from callback
return from ib_sa_join_multicast
set mcast->mc = return from ib_sa_multicast
We now have a permanently unbalanced join/leave issue that trips up the
refcounting in core/multicast.c
Another like this:
Thread 1 Thread 2 Thread 3
ib_sa_multicast_join
ifconfig ib0 down
priv->broadcast = NULL
join_complete
wait_for_completion
mcast->mc is not yet set, so don't clear
return from ib_sa_join_multicast and set mcast->mc
complete
return -EAGAIN (making mcast->mc invalid)
call ib_sa_multicast_leave
on invalid mcast->mc, hang
forever
By holding the mutex around ib_sa_multicast_join and taking the mutex
early in the callback, we force mcast->mc to be valid at the time we
run the callback. This allows us to clear mcast->mc if there is an
error and the join is going to fail. We do this before we complete
the mcast. In this way, mcast_dev_flush always sees consistent state
in regards to mcast->mc membership at the time that the
wait_for_completion() returns.
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2014-12-10 23:47:00 +07:00
|
|
|
set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
2015-01-31 06:39:20 +07:00
|
|
|
init_completion(&mcast->done);
|
|
|
|
set_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags);
|
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
|
|
|
|
&rec, comp_mask, GFP_KERNEL,
|
|
|
|
ipoib_mcast_join_complete, mcast);
|
|
|
|
if (IS_ERR(mcast->mc)) {
|
|
|
|
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
|
2013-10-16 21:37:51 +07:00
|
|
|
complete(&mcast->done);
|
2007-02-16 08:00:17 +07:00
|
|
|
ret = PTR_ERR(mcast->mc);
|
|
|
|
ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
mcast->backoff *= 2;
|
|
|
|
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
|
|
|
|
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
|
|
|
|
|
2015-01-31 06:39:20 +07:00
|
|
|
mutex_lock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_delayed_work(priv->wq, &priv->mcast_task,
|
2005-09-19 03:47:53 +07:00
|
|
|
mcast->backoff * HZ);
|
2015-01-31 06:39:20 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2007-02-16 08:00:17 +07:00
|
|
|
}
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
2006-11-22 21:57:56 +07:00
|
|
|
void ipoib_mcast_join_task(struct work_struct *work)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
2006-11-22 21:57:56 +07:00
|
|
|
struct ipoib_dev_priv *priv =
|
|
|
|
container_of(work, struct ipoib_dev_priv, mcast_task.work);
|
|
|
|
struct net_device *dev = priv->dev;
|
2013-10-16 21:37:53 +07:00
|
|
|
struct ib_port_attr port_attr;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
|
|
|
|
return;
|
|
|
|
|
2013-10-16 21:37:53 +07:00
|
|
|
if (ib_query_port(priv->ca, priv->port, &port_attr) ||
|
|
|
|
port_attr.state != IB_PORT_ACTIVE) {
|
|
|
|
ipoib_dbg(priv, "port state is not ACTIVE (state = %d) suspending join task\n",
|
|
|
|
port_attr.state);
|
|
|
|
return;
|
|
|
|
}
|
2014-08-20 22:15:08 +07:00
|
|
|
priv->local_lid = port_attr.lid;
|
2013-10-16 21:37:53 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
|
2007-05-18 20:12:54 +07:00
|
|
|
ipoib_warn(priv, "ib_query_gid() failed\n");
|
2005-04-17 05:20:36 +07:00
|
|
|
else
|
|
|
|
memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
|
|
|
|
|
|
|
|
if (!priv->broadcast) {
|
2006-02-12 03:22:12 +07:00
|
|
|
struct ipoib_mcast *broadcast;
|
|
|
|
|
2015-02-22 07:27:02 +07:00
|
|
|
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
|
2009-01-13 10:28:42 +07:00
|
|
|
return;
|
|
|
|
|
2006-02-12 03:22:12 +07:00
|
|
|
broadcast = ipoib_mcast_alloc(dev, 1);
|
|
|
|
if (!broadcast) {
|
2005-04-17 05:20:36 +07:00
|
|
|
ipoib_warn(priv, "failed to allocate broadcast group\n");
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_lock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_delayed_work(priv->wq, &priv->mcast_task,
|
|
|
|
HZ);
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-02-12 03:22:12 +07:00
|
|
|
spin_lock_irq(&priv->lock);
|
|
|
|
memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
|
2005-04-17 05:20:36 +07:00
|
|
|
sizeof (union ib_gid));
|
2006-02-12 03:22:12 +07:00
|
|
|
priv->broadcast = broadcast;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
__ipoib_mcast_add(dev, priv->broadcast);
|
|
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
|
2015-01-31 06:39:20 +07:00
|
|
|
if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
|
2007-02-16 08:00:17 +07:00
|
|
|
ipoib_mcast_join(dev, priv->broadcast, 0);
|
2005-04-17 05:20:36 +07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
struct ipoib_mcast *mcast = NULL;
|
|
|
|
|
|
|
|
spin_lock_irq(&priv->lock);
|
|
|
|
list_for_each_entry(mcast, &priv->multicast_list, list) {
|
2015-01-31 06:39:20 +07:00
|
|
|
if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)
|
|
|
|
&& !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)
|
|
|
|
&& !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
|
2005-04-17 05:20:36 +07:00
|
|
|
/* Found the next unjoined group */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
|
|
|
|
if (&mcast->list == &priv->multicast_list) {
|
|
|
|
/* All done */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-01-31 06:39:20 +07:00
|
|
|
ipoib_mcast_join(dev, mcast, 1);
|
2005-04-17 05:20:36 +07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
|
|
|
|
|
|
|
|
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ipoib_mcast_start_thread(struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
|
|
|
|
ipoib_dbg_mcast(priv, "starting multicast thread\n");
|
|
|
|
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_lock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
|
IB/ipoib: Use dedicated workqueues per interface
During my recent work on the rtnl lock deadlock in the IPoIB driver, I
saw that even once I fixed the apparent races for a single device, as
soon as that device had any children, new races popped up. It turns
out that this is because no matter how well we protect against races
on a single device, the fact that all devices use the same workqueue,
and flush_workqueue() flushes *everything* from that workqueue means
that we would also have to prevent all races between different devices
(for instance, ipoib_mcast_restart_task on interface ib0 can race with
ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
the rtnl_lock).
There are several possible solutions to this problem:
Make carrier_on_task and mcast_restart_task try to take the rtnl for
some set period of time and if they fail, then bail. This runs the
real risk of dropping work on the floor, which can end up being its
own separate kind of deadlock.
Set some global flag in the driver that says some device is in the
middle of going down, letting all tasks know to bail. Again, this can
drop work on the floor.
Or the method this patch attempts to use, which is when we bring an
interface up, create a workqueue specifically for that interface, so
that when we take it back down, we are flushing only those tasks
associated with our interface. In addition, keep the global
workqueue, but now limit it to only flush tasks. In this way, the
flush tasks can always flush the device specific work queues without
having deadlock issues.
Signed-off-by: Doug Ledford <dledford@redhat.com>
2015-02-22 07:27:03 +07:00
|
|
|
queue_delayed_work(priv->wq, &priv->mcast_task, 0);
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-22 07:27:04 +07:00
|
|
|
int ipoib_mcast_stop_thread(struct net_device *dev)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
|
|
|
|
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
|
|
|
|
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_lock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
|
|
|
|
cancel_delayed_work(&priv->mcast_task);
|
2006-01-14 05:51:39 +07:00
|
|
|
mutex_unlock(&mcast_mutex);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2015-02-22 07:27:04 +07:00
|
|
|
flush_workqueue(priv->wq);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
int ret = 0;
|
|
|
|
|
2007-03-20 05:31:36 +07:00
|
|
|
if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
|
|
|
|
ib_sa_free_multicast(mcast->mc);
|
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "leaving MGID %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
/* Remove ourselves from the multicast group */
|
2008-07-15 13:48:50 +07:00
|
|
|
ret = ib_detach_mcast(priv->qp, &mcast->mcmember.mgid,
|
|
|
|
be16_to_cpu(mcast->mcmember.mlid));
|
2007-02-16 08:00:17 +07:00
|
|
|
if (ret)
|
2008-07-15 13:48:50 +07:00
|
|
|
ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
|
2007-02-16 08:00:17 +07:00
|
|
|
}
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
IPoIB: Use a private hash table for path lookup in xmit path
Dave Miller <davem@davemloft.net> provided a detailed description of
why the way IPoIB is using neighbours for its own ipoib_neigh struct
is buggy:
Any time an ipoib_neigh is changed, a sequence like the following is made:
spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
* path->ah will always hold one more reference,
* so ipoib_put_ah() will never do more than
* decrement the ref count.
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, n, dev);
This doesn't work, because you're leaving a stale pointer to the freed up
ipoib_neigh in the special neigh->ha pointer cookie. Yes, it even fails
with all the locking done to protect _changes_ to *ipoib_neigh(n), and
with the code in ipoib_neigh_free() that NULLs out the pointer.
The core issue is that read side calls to *to_ipoib_neigh(n) are not
being synchronized at all, they are performed without any locking. So
whether we hold the lock or not when making changes to *ipoib_neigh(n)
you still can have threads see references to freed up ipoib_neigh
objects.
cpu 1 cpu 2
n = *ipoib_neigh()
*ipoib_neigh() = NULL
kfree(n)
n->foo == OOPS
[..]
Perhaps the ipoib code can have a private path database it manages
entirely itself, which holds all the necessary information and is
looked up by some generic key which is available easily at transmit
time and does not involve generic neighbour entries.
See <http://marc.info/?l=linux-rdma&m=132812793105624&w=2> and
<http://marc.info/?l=linux-rdma&w=2&r=1&s=allows+references+to+freed+memory&q=b>
for the full discussion.
This patch aims to solve the race conditions found in the IPoIB driver.
The patch removes the connection between the core networking neighbour
structure and the ipoib_neigh structure. In addition to avoiding the
race described above, it allows us to handle SKBs carrying IP packets
that don't have any associated neighbour.
We add an ipoib_neigh hash table with N buckets where the key is the
destination hardware address. The ipoib_neigh is fetched from the
hash table and instead of the stashed location in the neighbour
structure. The hash table uses both RCU and reference counting to
guarantee that no ipoib_neigh instance is ever deleted while in use.
Fetching the ipoib_neigh structure instance from the hash also makes
the special code in ipoib_start_xmit that handles remote and local
bonding failover redundant.
Aged ipoib_neigh instances are deleted by a garbage collection task
that runs every M seconds and deletes every ipoib_neigh instance that
was idle for at least 2*M seconds. The deletion is safe since the
ipoib_neigh instances are protected using RCU and reference count
mechanisms.
The number of buckets (N) and frequency of running the GC thread (M),
are taken from the exported arb_tbl.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2012-07-25 00:05:22 +07:00
|
|
|
void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
struct ipoib_mcast *mcast;
|
2008-10-01 00:36:21 +07:00
|
|
|
unsigned long flags;
|
IPoIB: Use a private hash table for path lookup in xmit path
Dave Miller <davem@davemloft.net> provided a detailed description of
why the way IPoIB is using neighbours for its own ipoib_neigh struct
is buggy:
Any time an ipoib_neigh is changed, a sequence like the following is made:
spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
* path->ah will always hold one more reference,
* so ipoib_put_ah() will never do more than
* decrement the ref count.
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, n, dev);
This doesn't work, because you're leaving a stale pointer to the freed up
ipoib_neigh in the special neigh->ha pointer cookie. Yes, it even fails
with all the locking done to protect _changes_ to *ipoib_neigh(n), and
with the code in ipoib_neigh_free() that NULLs out the pointer.
The core issue is that read side calls to *to_ipoib_neigh(n) are not
being synchronized at all, they are performed without any locking. So
whether we hold the lock or not when making changes to *ipoib_neigh(n)
you still can have threads see references to freed up ipoib_neigh
objects.
cpu 1 cpu 2
n = *ipoib_neigh()
*ipoib_neigh() = NULL
kfree(n)
n->foo == OOPS
[..]
Perhaps the ipoib code can have a private path database it manages
entirely itself, which holds all the necessary information and is
looked up by some generic key which is available easily at transmit
time and does not involve generic neighbour entries.
See <http://marc.info/?l=linux-rdma&m=132812793105624&w=2> and
<http://marc.info/?l=linux-rdma&w=2&r=1&s=allows+references+to+freed+memory&q=b>
for the full discussion.
This patch aims to solve the race conditions found in the IPoIB driver.
The patch removes the connection between the core networking neighbour
structure and the ipoib_neigh structure. In addition to avoiding the
race described above, it allows us to handle SKBs carrying IP packets
that don't have any associated neighbour.
We add an ipoib_neigh hash table with N buckets where the key is the
destination hardware address. The ipoib_neigh is fetched from the
hash table and instead of the stashed location in the neighbour
structure. The hash table uses both RCU and reference counting to
guarantee that no ipoib_neigh instance is ever deleted while in use.
Fetching the ipoib_neigh structure instance from the hash also makes
the special code in ipoib_start_xmit that handles remote and local
bonding failover redundant.
Aged ipoib_neigh instances are deleted by a garbage collection task
that runs every M seconds and deletes every ipoib_neigh instance that
was idle for at least 2*M seconds. The deletion is safe since the
ipoib_neigh instances are protected using RCU and reference count
mechanisms.
The number of buckets (N) and frequency of running the GC thread (M),
are taken from the exported arb_tbl.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2012-07-25 00:05:22 +07:00
|
|
|
void *mgid = daddr + 4;
|
2012-07-06 11:08:05 +07:00
|
|
|
|
2008-10-01 00:36:21 +07:00
|
|
|
spin_lock_irqsave(&priv->lock, flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-03-11 21:10:02 +07:00
|
|
|
if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags) ||
|
2006-02-12 03:22:12 +07:00
|
|
|
!priv->broadcast ||
|
|
|
|
!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
|
2007-09-29 05:33:51 +07:00
|
|
|
++dev->stats.tx_dropped;
|
2006-02-08 07:37:08 +07:00
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
mcast = __ipoib_mcast_find(dev, mgid);
|
|
|
|
if (!mcast) {
|
|
|
|
/* Let's create a new send only group now */
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mgid);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
mcast = ipoib_mcast_alloc(dev, 0);
|
|
|
|
if (!mcast) {
|
|
|
|
ipoib_warn(priv, "unable to allocate memory for "
|
|
|
|
"multicast structure\n");
|
2007-09-29 05:33:51 +07:00
|
|
|
++dev->stats.tx_dropped;
|
2005-04-17 05:20:36 +07:00
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
|
2006-05-29 23:14:05 +07:00
|
|
|
memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));
|
2005-04-17 05:20:36 +07:00
|
|
|
__ipoib_mcast_add(dev, mcast);
|
|
|
|
list_add_tail(&mcast->list, &priv->multicast_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mcast->ah) {
|
|
|
|
if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
|
|
|
|
skb_queue_tail(&mcast->pkt_queue, skb);
|
2006-01-18 03:19:40 +07:00
|
|
|
else {
|
2007-09-29 05:33:51 +07:00
|
|
|
++dev->stats.tx_dropped;
|
2005-04-17 05:20:36 +07:00
|
|
|
dev_kfree_skb_any(skb);
|
2006-01-18 03:19:40 +07:00
|
|
|
}
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2007-02-16 08:00:17 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
|
2005-04-17 05:20:36 +07:00
|
|
|
ipoib_dbg_mcast(priv, "no address vector, "
|
|
|
|
"but multicast join already started\n");
|
2015-01-31 06:39:20 +07:00
|
|
|
else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
|
|
|
|
ipoib_mcast_sendonly_join(mcast);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If lookup completes between here and out:, don't
|
|
|
|
* want to send packet twice.
|
|
|
|
*/
|
|
|
|
mcast = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (mcast && mcast->ah) {
|
IPoIB: Use a private hash table for path lookup in xmit path
Dave Miller <davem@davemloft.net> provided a detailed description of
why the way IPoIB is using neighbours for its own ipoib_neigh struct
is buggy:
Any time an ipoib_neigh is changed, a sequence like the following is made:
spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
* path->ah will always hold one more reference,
* so ipoib_put_ah() will never do more than
* decrement the ref count.
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, n, dev);
This doesn't work, because you're leaving a stale pointer to the freed up
ipoib_neigh in the special neigh->ha pointer cookie. Yes, it even fails
with all the locking done to protect _changes_ to *ipoib_neigh(n), and
with the code in ipoib_neigh_free() that NULLs out the pointer.
The core issue is that read side calls to *to_ipoib_neigh(n) are not
being synchronized at all, they are performed without any locking. So
whether we hold the lock or not when making changes to *ipoib_neigh(n)
you still can have threads see references to freed up ipoib_neigh
objects.
cpu 1 cpu 2
n = *ipoib_neigh()
*ipoib_neigh() = NULL
kfree(n)
n->foo == OOPS
[..]
Perhaps the ipoib code can have a private path database it manages
entirely itself, which holds all the necessary information and is
looked up by some generic key which is available easily at transmit
time and does not involve generic neighbour entries.
See <http://marc.info/?l=linux-rdma&m=132812793105624&w=2> and
<http://marc.info/?l=linux-rdma&w=2&r=1&s=allows+references+to+freed+memory&q=b>
for the full discussion.
This patch aims to solve the race conditions found in the IPoIB driver.
The patch removes the connection between the core networking neighbour
structure and the ipoib_neigh structure. In addition to avoiding the
race described above, it allows us to handle SKBs carrying IP packets
that don't have any associated neighbour.
We add an ipoib_neigh hash table with N buckets where the key is the
destination hardware address. The ipoib_neigh is fetched from the
hash table and instead of the stashed location in the neighbour
structure. The hash table uses both RCU and reference counting to
guarantee that no ipoib_neigh instance is ever deleted while in use.
Fetching the ipoib_neigh structure instance from the hash also makes
the special code in ipoib_start_xmit that handles remote and local
bonding failover redundant.
Aged ipoib_neigh instances are deleted by a garbage collection task
that runs every M seconds and deletes every ipoib_neigh instance that
was idle for at least 2*M seconds. The deletion is safe since the
ipoib_neigh instances are protected using RCU and reference count
mechanisms.
The number of buckets (N) and frequency of running the GC thread (M),
are taken from the exported arb_tbl.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2012-07-25 00:05:22 +07:00
|
|
|
struct ipoib_neigh *neigh;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
|
neigh = ipoib_neigh_get(dev, daddr);
|
|
|
|
spin_lock_irqsave(&priv->lock, flags);
|
|
|
|
if (!neigh) {
|
|
|
|
neigh = ipoib_neigh_alloc(daddr, dev);
|
|
|
|
if (neigh) {
|
|
|
|
kref_get(&mcast->ah->ref);
|
|
|
|
neigh->ah = mcast->ah;
|
|
|
|
list_add_tail(&neigh->list, &mcast->neigh_list);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
}
|
2009-09-06 10:23:40 +07:00
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
|
IPoIB: Use a private hash table for path lookup in xmit path
Dave Miller <davem@davemloft.net> provided a detailed description of
why the way IPoIB is using neighbours for its own ipoib_neigh struct
is buggy:
Any time an ipoib_neigh is changed, a sequence like the following is made:
spin_lock_irqsave(&priv->lock, flags);
/*
* It's safe to call ipoib_put_ah() inside
* priv->lock here, because we know that
* path->ah will always hold one more reference,
* so ipoib_put_ah() will never do more than
* decrement the ref count.
*/
if (neigh->ah)
ipoib_put_ah(neigh->ah);
list_del(&neigh->list);
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, n, dev);
This doesn't work, because you're leaving a stale pointer to the freed up
ipoib_neigh in the special neigh->ha pointer cookie. Yes, it even fails
with all the locking done to protect _changes_ to *ipoib_neigh(n), and
with the code in ipoib_neigh_free() that NULLs out the pointer.
The core issue is that read side calls to *to_ipoib_neigh(n) are not
being synchronized at all, they are performed without any locking. So
whether we hold the lock or not when making changes to *ipoib_neigh(n)
you still can have threads see references to freed up ipoib_neigh
objects.
cpu 1 cpu 2
n = *ipoib_neigh()
*ipoib_neigh() = NULL
kfree(n)
n->foo == OOPS
[..]
Perhaps the ipoib code can have a private path database it manages
entirely itself, which holds all the necessary information and is
looked up by some generic key which is available easily at transmit
time and does not involve generic neighbour entries.
See <http://marc.info/?l=linux-rdma&m=132812793105624&w=2> and
<http://marc.info/?l=linux-rdma&w=2&r=1&s=allows+references+to+freed+memory&q=b>
for the full discussion.
This patch aims to solve the race conditions found in the IPoIB driver.
The patch removes the connection between the core networking neighbour
structure and the ipoib_neigh structure. In addition to avoiding the
race described above, it allows us to handle SKBs carrying IP packets
that don't have any associated neighbour.
We add an ipoib_neigh hash table with N buckets where the key is the
destination hardware address. The ipoib_neigh is fetched from the
hash table and instead of the stashed location in the neighbour
structure. The hash table uses both RCU and reference counting to
guarantee that no ipoib_neigh instance is ever deleted while in use.
Fetching the ipoib_neigh structure instance from the hash also makes
the special code in ipoib_start_xmit that handles remote and local
bonding failover redundant.
Aged ipoib_neigh instances are deleted by a garbage collection task
that runs every M seconds and deletes every ipoib_neigh instance that
was idle for at least 2*M seconds. The deletion is safe since the
ipoib_neigh instances are protected using RCU and reference count
mechanisms.
The number of buckets (N) and frequency of running the GC thread (M),
are taken from the exported arb_tbl.
Signed-off-by: Shlomo Pongratz <shlomop@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
2012-07-25 00:05:22 +07:00
|
|
|
if (neigh)
|
|
|
|
ipoib_neigh_put(neigh);
|
2009-09-06 10:23:40 +07:00
|
|
|
return;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
2006-02-08 07:37:08 +07:00
|
|
|
unlock:
|
2008-10-01 00:36:21 +07:00
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void ipoib_mcast_dev_flush(struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
|
|
|
LIST_HEAD(remove_list);
|
2006-01-13 05:32:20 +07:00
|
|
|
struct ipoib_mcast *mcast, *tmcast;
|
2005-04-17 05:20:36 +07:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
ipoib_dbg_mcast(priv, "flushing multicast list\n");
|
|
|
|
|
|
|
|
spin_lock_irqsave(&priv->lock, flags);
|
|
|
|
|
2006-01-13 05:32:20 +07:00
|
|
|
list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
|
|
|
|
list_del(&mcast->list);
|
|
|
|
rb_erase(&mcast->rb_node, &priv->multicast_tree);
|
|
|
|
list_add_tail(&mcast->list, &remove_list);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->broadcast) {
|
2006-09-23 05:22:46 +07:00
|
|
|
rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
|
2006-01-13 05:32:20 +07:00
|
|
|
list_add_tail(&priv->broadcast->list, &remove_list);
|
|
|
|
priv->broadcast = NULL;
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
|
|
2015-01-31 06:39:11 +07:00
|
|
|
/* seperate between the wait to the leave*/
|
2013-10-16 21:37:51 +07:00
|
|
|
list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
|
2015-01-31 06:39:20 +07:00
|
|
|
if (test_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags))
|
2013-10-16 21:37:51 +07:00
|
|
|
wait_for_completion(&mcast->done);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
|
|
|
|
ipoib_mcast_leave(dev, mcast);
|
|
|
|
ipoib_mcast_free(mcast);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-22 10:21:39 +07:00
|
|
|
static int ipoib_mcast_addr_is_valid(const u8 *addr, const u8 *broadcast)
|
2009-09-06 10:23:40 +07:00
|
|
|
{
|
|
|
|
/* reserved QPN, prefix, scope */
|
|
|
|
if (memcmp(addr, broadcast, 6))
|
|
|
|
return 0;
|
|
|
|
/* signature lower, pkey */
|
|
|
|
if (memcmp(addr + 7, broadcast + 7, 3))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-11-22 21:57:56 +07:00
|
|
|
void ipoib_mcast_restart_task(struct work_struct *work)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
2006-11-22 21:57:56 +07:00
|
|
|
struct ipoib_dev_priv *priv =
|
|
|
|
container_of(work, struct ipoib_dev_priv, restart_task);
|
|
|
|
struct net_device *dev = priv->dev;
|
2010-04-02 04:22:57 +07:00
|
|
|
struct netdev_hw_addr *ha;
|
2005-04-17 05:20:36 +07:00
|
|
|
struct ipoib_mcast *mcast, *tmcast;
|
|
|
|
LIST_HEAD(remove_list);
|
|
|
|
unsigned long flags;
|
IPoIB: Allow setting policy to ignore multicast groups
The kernel IB stack allows (through the RDMA CM) userspace
applications to join and use multicast groups from the IPoIB MGID
range. This allows multicast traffic to be handled directly from
userspace QPs, without going through the kernel stack, which gives
better performance for some applications.
However, to fully interoperate with IP multicast, such userspace
applications need to participate in IGMP reports and queries, or else
routers may not forward the multicast traffic to the system where the
application is running. The simplest way to do this is to share the
kernel IGMP implementation by using the IP_ADD_MEMBERSHIP option to
join multicast groups that are being handled directly in userspace.
However, in such cases, the actual multicast traffic should not also
be handled by the IPoIB interface, because that would burn resources
handling multicast packets that will just be discarded in the kernel.
To handle this, this patch adds lookup on the database used for IB
multicast group reference counting when IPoIB is joining multicast
groups, and if a multicast group is already handled by user space,
then the IPoIB kernel driver ignores the group. This is controlled by
a per-interface policy flag. When the flag is set, IPoIB will not
join and attach its QP to a multicast group which already has an entry
in the database; when the flag is cleared, IPoIB will behave as before
this change.
For each IPoIB interface, the /sys/class/net/$intf/umcast attribute
controls the policy flag. The default value is off/0.
Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
2007-10-08 15:13:00 +07:00
|
|
|
struct ib_sa_mcmember_rec rec;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
ipoib_dbg_mcast(priv, "restarting multicast task\n");
|
|
|
|
|
2015-02-22 07:27:04 +07:00
|
|
|
/*
|
|
|
|
* We're running on the priv->wq right now, so we can't call
|
|
|
|
* mcast_stop_thread as it wants to flush the wq and that
|
|
|
|
* will deadlock. We don't actually *need* to stop the
|
|
|
|
* thread here anyway, so just clear the run flag, cancel
|
|
|
|
* any delayed work, do our work, remove the old entries,
|
|
|
|
* then restart the thread.
|
|
|
|
*/
|
|
|
|
mutex_lock(&mcast_mutex);
|
|
|
|
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
|
|
|
|
cancel_delayed_work(&priv->mcast_task);
|
|
|
|
mutex_unlock(&mcast_mutex);
|
2015-01-31 06:38:46 +07:00
|
|
|
|
2006-06-10 02:20:56 +07:00
|
|
|
local_irq_save(flags);
|
2008-07-15 14:13:44 +07:00
|
|
|
netif_addr_lock(dev);
|
2006-01-12 02:47:34 +07:00
|
|
|
spin_lock(&priv->lock);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Unfortunately, the networking core only gives us a list of all of
|
|
|
|
* the multicast hardware addresses. We need to figure out which ones
|
|
|
|
* are new and which ones have been removed
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Clear out the found flag */
|
|
|
|
list_for_each_entry(mcast, &priv->multicast_list, list)
|
|
|
|
clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
|
|
|
|
|
|
|
|
/* Mark all of the entries that are found or don't exist */
|
2010-04-02 04:22:57 +07:00
|
|
|
netdev_for_each_mc_addr(ha, dev) {
|
2005-04-17 05:20:36 +07:00
|
|
|
union ib_gid mgid;
|
|
|
|
|
2010-04-02 04:22:57 +07:00
|
|
|
if (!ipoib_mcast_addr_is_valid(ha->addr, dev->broadcast))
|
2009-09-06 10:23:40 +07:00
|
|
|
continue;
|
|
|
|
|
2010-04-02 04:22:57 +07:00
|
|
|
memcpy(mgid.raw, ha->addr + 4, sizeof mgid);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
mcast = __ipoib_mcast_find(dev, &mgid);
|
|
|
|
if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
|
|
|
|
struct ipoib_mcast *nmcast;
|
|
|
|
|
IPoIB: Allow setting policy to ignore multicast groups
The kernel IB stack allows (through the RDMA CM) userspace
applications to join and use multicast groups from the IPoIB MGID
range. This allows multicast traffic to be handled directly from
userspace QPs, without going through the kernel stack, which gives
better performance for some applications.
However, to fully interoperate with IP multicast, such userspace
applications need to participate in IGMP reports and queries, or else
routers may not forward the multicast traffic to the system where the
application is running. The simplest way to do this is to share the
kernel IGMP implementation by using the IP_ADD_MEMBERSHIP option to
join multicast groups that are being handled directly in userspace.
However, in such cases, the actual multicast traffic should not also
be handled by the IPoIB interface, because that would burn resources
handling multicast packets that will just be discarded in the kernel.
To handle this, this patch adds lookup on the database used for IB
multicast group reference counting when IPoIB is joining multicast
groups, and if a multicast group is already handled by user space,
then the IPoIB kernel driver ignores the group. This is controlled by
a per-interface policy flag. When the flag is set, IPoIB will not
join and attach its QP to a multicast group which already has an entry
in the database; when the flag is cleared, IPoIB will behave as before
this change.
For each IPoIB interface, the /sys/class/net/$intf/umcast attribute
controls the policy flag. The default value is off/0.
Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
2007-10-08 15:13:00 +07:00
|
|
|
/* ignore group which is directly joined by userspace */
|
|
|
|
if (test_bit(IPOIB_FLAG_UMCAST, &priv->flags) &&
|
|
|
|
!ib_sa_get_mcmember_rec(priv->ca, priv->port, &mgid, &rec)) {
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mgid.raw);
|
IPoIB: Allow setting policy to ignore multicast groups
The kernel IB stack allows (through the RDMA CM) userspace
applications to join and use multicast groups from the IPoIB MGID
range. This allows multicast traffic to be handled directly from
userspace QPs, without going through the kernel stack, which gives
better performance for some applications.
However, to fully interoperate with IP multicast, such userspace
applications need to participate in IGMP reports and queries, or else
routers may not forward the multicast traffic to the system where the
application is running. The simplest way to do this is to share the
kernel IGMP implementation by using the IP_ADD_MEMBERSHIP option to
join multicast groups that are being handled directly in userspace.
However, in such cases, the actual multicast traffic should not also
be handled by the IPoIB interface, because that would burn resources
handling multicast packets that will just be discarded in the kernel.
To handle this, this patch adds lookup on the database used for IB
multicast group reference counting when IPoIB is joining multicast
groups, and if a multicast group is already handled by user space,
then the IPoIB kernel driver ignores the group. This is controlled by
a per-interface policy flag. When the flag is set, IPoIB will not
join and attach its QP to a multicast group which already has an entry
in the database; when the flag is cleared, IPoIB will behave as before
this change.
For each IPoIB interface, the /sys/class/net/$intf/umcast attribute
controls the policy flag. The default value is off/0.
Signed-off-by: Or Gerlitz <ogerlitz@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
2007-10-08 15:13:00 +07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* Not found or send-only group, let's add a new entry */
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "adding multicast entry for mgid %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
nmcast = ipoib_mcast_alloc(dev, 0);
|
|
|
|
if (!nmcast) {
|
|
|
|
ipoib_warn(priv, "unable to allocate memory for multicast structure\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_bit(IPOIB_MCAST_FLAG_FOUND, &nmcast->flags);
|
|
|
|
|
|
|
|
nmcast->mcmember.mgid = mgid;
|
|
|
|
|
|
|
|
if (mcast) {
|
|
|
|
/* Destroy the send only entry */
|
2006-06-26 14:24:41 +07:00
|
|
|
list_move_tail(&mcast->list, &remove_list);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
rb_replace_node(&mcast->rb_node,
|
|
|
|
&nmcast->rb_node,
|
|
|
|
&priv->multicast_tree);
|
|
|
|
} else
|
|
|
|
__ipoib_mcast_add(dev, nmcast);
|
|
|
|
|
|
|
|
list_add_tail(&nmcast->list, &priv->multicast_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mcast)
|
|
|
|
set_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove all of the entries don't exist anymore */
|
|
|
|
list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
|
|
|
|
if (!test_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags) &&
|
|
|
|
!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
|
2008-10-30 02:52:50 +07:00
|
|
|
ipoib_dbg_mcast(priv, "deleting multicast group %pI6\n",
|
2008-10-29 12:37:22 +07:00
|
|
|
mcast->mcmember.mgid.raw);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
rb_erase(&mcast->rb_node, &priv->multicast_tree);
|
|
|
|
|
|
|
|
/* Move to the remove list */
|
2006-06-26 14:24:41 +07:00
|
|
|
list_move_tail(&mcast->list, &remove_list);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
}
|
2006-01-12 02:47:34 +07:00
|
|
|
|
|
|
|
spin_unlock(&priv->lock);
|
2008-07-15 14:13:44 +07:00
|
|
|
netif_addr_unlock(dev);
|
2006-06-10 02:20:56 +07:00
|
|
|
local_irq_restore(flags);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2015-01-31 06:39:11 +07:00
|
|
|
/* We have to cancel outside of the spinlock */
|
2005-04-17 05:20:36 +07:00
|
|
|
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
|
|
|
|
ipoib_mcast_leave(mcast->dev, mcast);
|
|
|
|
ipoib_mcast_free(mcast);
|
|
|
|
}
|
2015-01-31 06:39:11 +07:00
|
|
|
|
2015-02-22 07:27:02 +07:00
|
|
|
if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
|
2015-01-31 06:39:11 +07:00
|
|
|
ipoib_mcast_start_thread(dev);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
2005-11-03 11:51:01 +07:00
|
|
|
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct ipoib_mcast_iter *iter;
|
|
|
|
|
|
|
|
iter = kmalloc(sizeof *iter, GFP_KERNEL);
|
|
|
|
if (!iter)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
iter->dev = dev;
|
2005-11-08 01:33:11 +07:00
|
|
|
memset(iter->mgid.raw, 0, 16);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
if (ipoib_mcast_iter_next(iter)) {
|
2005-11-08 01:33:11 +07:00
|
|
|
kfree(iter);
|
2005-04-17 05:20:36 +07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter)
|
|
|
|
{
|
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(iter->dev);
|
|
|
|
struct rb_node *n;
|
|
|
|
struct ipoib_mcast *mcast;
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
spin_lock_irq(&priv->lock);
|
|
|
|
|
|
|
|
n = rb_first(&priv->multicast_tree);
|
|
|
|
|
|
|
|
while (n) {
|
|
|
|
mcast = rb_entry(n, struct ipoib_mcast, rb_node);
|
|
|
|
|
|
|
|
if (memcmp(iter->mgid.raw, mcast->mcmember.mgid.raw,
|
|
|
|
sizeof (union ib_gid)) < 0) {
|
|
|
|
iter->mgid = mcast->mcmember.mgid;
|
|
|
|
iter->created = mcast->created;
|
|
|
|
iter->queuelen = skb_queue_len(&mcast->pkt_queue);
|
|
|
|
iter->complete = !!mcast->ah;
|
|
|
|
iter->send_only = !!(mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY));
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = rb_next(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_irq(&priv->lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,
|
|
|
|
union ib_gid *mgid,
|
|
|
|
unsigned long *created,
|
|
|
|
unsigned int *queuelen,
|
|
|
|
unsigned int *complete,
|
|
|
|
unsigned int *send_only)
|
|
|
|
{
|
|
|
|
*mgid = iter->mgid;
|
|
|
|
*created = iter->created;
|
|
|
|
*queuelen = iter->queuelen;
|
|
|
|
*complete = iter->complete;
|
|
|
|
*send_only = iter->send_only;
|
|
|
|
}
|
2005-11-03 11:51:01 +07:00
|
|
|
|
|
|
|
#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */
|