ipoib_multicast.c 25.1 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
/*
 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3
4
 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
 * Copyright (c) 2004 Voltaire, Inc. All rights reserved.
Linus Torvalds's avatar
Linus Torvalds committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 *
 * 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>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/igmp.h>
#include <linux/inetdevice.h>
#include <linux/delay.h>
#include <linux/completion.h>

44
45
#include <net/dst.h>

Linus Torvalds's avatar
Linus Torvalds committed
46
47
48
49
50
51
52
53
54
55
#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

56
static DEFINE_MUTEX(mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

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;
	struct ipoib_dev_priv *priv = netdev_priv(dev);
	struct ipoib_neigh *neigh, *tmp;
72
	int tx_dropped = 0;
Linus Torvalds's avatar
Linus Torvalds committed
73

Harvey Harrison's avatar
Harvey Harrison committed
74
	ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group %pI6\n",
75
			mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
76

77
	spin_lock_irq(&priv->lock);
Linus Torvalds's avatar
Linus Torvalds committed
78
79

	list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
80
81
82
83
84
85
		/*
		 * It's safe to call ipoib_put_ah() inside priv->lock
		 * here, because we know that mcast->ah will always
		 * hold one more reference, so ipoib_put_ah() will
		 * never do more than decrement the ref count.
		 */
Linus Torvalds's avatar
Linus Torvalds committed
86
		if (neigh->ah)
87
			ipoib_put_ah(neigh->ah);
88
		ipoib_neigh_free(dev, neigh);
Linus Torvalds's avatar
Linus Torvalds committed
89
90
	}

91
	spin_unlock_irq(&priv->lock);
Linus Torvalds's avatar
Linus Torvalds committed
92
93
94
95

	if (mcast->ah)
		ipoib_put_ah(mcast->ah);

96
97
	while (!skb_queue_empty(&mcast->pkt_queue)) {
		++tx_dropped;
98
		dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
99
100
	}

101
	netif_tx_lock_bh(dev);
102
	dev->stats.tx_dropped += tx_dropped;
103
	netif_tx_unlock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
104
105
106
107
108
109
110
111
112

	kfree(mcast);
}

static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
					     int can_sleep)
{
	struct ipoib_mcast *mcast;

Roland Dreier's avatar
Roland Dreier committed
113
	mcast = kzalloc(sizeof *mcast, can_sleep ? GFP_KERNEL : GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
114
115
116
117
118
	if (!mcast)
		return NULL;

	mcast->dev = dev;
	mcast->created = jiffies;
119
	mcast->backoff = 1;
Linus Torvalds's avatar
Linus Torvalds committed
120
121
122
123
124
125
126
127

	INIT_LIST_HEAD(&mcast->list);
	INIT_LIST_HEAD(&mcast->neigh_list);
	skb_queue_head_init(&mcast->pkt_queue);

	return mcast;
}

128
static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
Linus Torvalds's avatar
Linus Torvalds committed
129
130
131
132
133
134
135
136
137
138
{
	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);

139
		ret = memcmp(mgid, mcast->mcmember.mgid.raw,
Linus Torvalds's avatar
Linus Torvalds committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
			     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);
185
	struct ipoib_ah *ah;
Linus Torvalds's avatar
Linus Torvalds committed
186
	int ret;
187
	int set_qkey = 0;
Linus Torvalds's avatar
Linus Torvalds committed
188
189
190
191
192
193

	mcast->mcmember = *mcmember;

	/* Set the cached Q_Key before we attach if it's the broadcast group */
	if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
		    sizeof (union ib_gid))) {
194
195
196
197
198
		spin_lock_irq(&priv->lock);
		if (!priv->broadcast) {
			spin_unlock_irq(&priv->lock);
			return -EAGAIN;
		}
Linus Torvalds's avatar
Linus Torvalds committed
199
		priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
200
		spin_unlock_irq(&priv->lock);
Linus Torvalds's avatar
Linus Torvalds committed
201
		priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
202
		set_qkey = 1;
Linus Torvalds's avatar
Linus Torvalds committed
203
204
205
206
	}

	if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
		if (test_and_set_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
Harvey Harrison's avatar
Harvey Harrison committed
207
			ipoib_warn(priv, "multicast group %pI6 already attached\n",
208
				   mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
209
210
211
212
213

			return 0;
		}

		ret = ipoib_mcast_attach(dev, be16_to_cpu(mcast->mcmember.mlid),
214
					 &mcast->mcmember.mgid, set_qkey);
Linus Torvalds's avatar
Linus Torvalds committed
215
		if (ret < 0) {
Harvey Harrison's avatar
Harvey Harrison committed
216
			ipoib_warn(priv, "couldn't attach QP to multicast group %pI6\n",
217
				   mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
218
219
220
221
222
223
224
225
226
227
228
229

			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,
230
			.static_rate   = mcast->mcmember.rate,
Linus Torvalds's avatar
Linus Torvalds committed
231
232
233
234
235
236
237
238
239
			.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;

240
241
		ah = ipoib_create_ah(dev, priv->pd, &av);
		if (!ah) {
Linus Torvalds's avatar
Linus Torvalds committed
242
243
			ipoib_warn(priv, "ib_address_create failed\n");
		} else {
244
245
246
247
			spin_lock_irq(&priv->lock);
			mcast->ah = ah;
			spin_unlock_irq(&priv->lock);

Harvey Harrison's avatar
Harvey Harrison committed
248
			ipoib_dbg_mcast(priv, "MGID %pI6 AV %p, LID 0x%04x, SL %d\n",
249
					mcast->mcmember.mgid.raw,
Linus Torvalds's avatar
Linus Torvalds committed
250
251
252
253
254
255
256
					mcast->ah->ah,
					be16_to_cpu(mcast->mcmember.mlid),
					mcast->mcmember.sl);
		}
	}

	/* actually send any queued packets */
257
	netif_tx_lock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
258
259
	while (!skb_queue_empty(&mcast->pkt_queue)) {
		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
260
		netif_tx_unlock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
261
262
263

		skb->dev = dev;

Eric Dumazet's avatar
Eric Dumazet committed
264
		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
Linus Torvalds's avatar
Linus Torvalds committed
265
266
267
268
269
270
			/* put pseudoheader back on for next time */
			skb_push(skb, sizeof (struct ipoib_pseudoheader));
		}

		if (dev_queue_xmit(skb))
			ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
271
		netif_tx_lock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
272
	}
273
	netif_tx_unlock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
274
275
276
277

	return 0;
}

278
static int
Linus Torvalds's avatar
Linus Torvalds committed
279
ipoib_mcast_sendonly_join_complete(int status,
280
				   struct ib_sa_multicast *multicast)
Linus Torvalds's avatar
Linus Torvalds committed
281
{
282
	struct ipoib_mcast *mcast = multicast->context;
Linus Torvalds's avatar
Linus Torvalds committed
283
284
	struct net_device *dev = mcast->dev;

285
286
287
288
	/* We trap for port events ourselves. */
	if (status == -ENETRESET)
		return 0;

Linus Torvalds's avatar
Linus Torvalds committed
289
	if (!status)
290
291
292
		status = ipoib_mcast_join_finish(mcast, &multicast->rec);

	if (status) {
Linus Torvalds's avatar
Linus Torvalds committed
293
		if (mcast->logcount++ < 20)
Harvey Harrison's avatar
Harvey Harrison committed
294
			ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for %pI6, status %d\n",
295
					mcast->mcmember.mgid.raw, status);
Linus Torvalds's avatar
Linus Torvalds committed
296
297

		/* Flush out any queued packets */
298
		netif_tx_lock_bh(dev);
299
		while (!skb_queue_empty(&mcast->pkt_queue)) {
300
			++dev->stats.tx_dropped;
301
			dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
302
		}
303
		netif_tx_unlock_bh(dev);
Linus Torvalds's avatar
Linus Torvalds committed
304
305

		/* Clear the busy flag so we try again */
306
307
		status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
					    &mcast->flags);
Linus Torvalds's avatar
Linus Torvalds committed
308
	}
309
	return status;
Linus Torvalds's avatar
Linus Torvalds committed
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
}

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)) {
		ipoib_dbg_mcast(priv, "device shutting down, no multicast joins\n");
		return -ENODEV;
	}

	if (test_and_set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) {
		ipoib_dbg_mcast(priv, "multicast entry busy, skipping\n");
		return -EBUSY;
	}

	rec.mgid     = mcast->mcmember.mgid;
	rec.port_gid = priv->local_gid;
337
	rec.pkey     = cpu_to_be16(priv->pkey);
Linus Torvalds's avatar
Linus Torvalds committed
338

339
340
341
342
343
344
345
346
347
348
349
350
351
	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);
		ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
Linus Torvalds's avatar
Linus Torvalds committed
352
353
			   ret);
	} else {
Harvey Harrison's avatar
Harvey Harrison committed
354
		ipoib_dbg_mcast(priv, "no multicast record for %pI6, starting join\n",
355
				mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
356
357
358
359
360
	}

	return ret;
}

361
362
363
364
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);
365
	struct ib_port_attr attr;
366
367
368
369
370
371

	/*
	 * Take rtnl_lock to avoid racing with ipoib_stop() and
	 * turning the carrier back on while a device is being
	 * removed.
	 */
372
373
374
375
376
377
	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;
	}

378
379
380
381
382
	rtnl_lock();
	netif_carrier_on(priv->dev);
	rtnl_unlock();
}

383
384
static int ipoib_mcast_join_complete(int status,
				     struct ib_sa_multicast *multicast)
Linus Torvalds's avatar
Linus Torvalds committed
385
{
386
	struct ipoib_mcast *mcast = multicast->context;
Linus Torvalds's avatar
Linus Torvalds committed
387
388
389
	struct net_device *dev = mcast->dev;
	struct ipoib_dev_priv *priv = netdev_priv(dev);

Harvey Harrison's avatar
Harvey Harrison committed
390
	ipoib_dbg_mcast(priv, "join completion for %pI6 (status %d)\n",
391
			mcast->mcmember.mgid.raw, status);
Linus Torvalds's avatar
Linus Torvalds committed
392

393
394
395
396
397
398
399
400
	/* We trap for port events ourselves. */
	if (status == -ENETRESET)
		return 0;

	if (!status)
		status = ipoib_mcast_join_finish(mcast, &multicast->rec);

	if (!status) {
401
		mcast->backoff = 1;
402
		mutex_lock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
403
		if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
David Howells's avatar
David Howells committed
404
405
			queue_delayed_work(ipoib_workqueue,
					   &priv->mcast_task, 0);
406
		mutex_unlock(&mcast_mutex);
407

408
409
410
411
412
413
		/*
		 * Defer carrier on work to ipoib_workqueue to avoid a
		 * deadlock on rtnl_lock here.
		 */
		if (mcast == priv->broadcast)
			queue_work(ipoib_workqueue, &priv->carrier_on_task);
414

415
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
416
417
	}

418
	if (mcast->logcount++ < 20) {
419
		if (status == -ETIMEDOUT || status == -EAGAIN) {
Harvey Harrison's avatar
Harvey Harrison committed
420
			ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n",
421
					mcast->mcmember.mgid.raw, status);
Linus Torvalds's avatar
Linus Torvalds committed
422
		} else {
Harvey Harrison's avatar
Harvey Harrison committed
423
			ipoib_warn(priv, "multicast join failed for %pI6, status %d\n",
424
				   mcast->mcmember.mgid.raw, status);
Linus Torvalds's avatar
Linus Torvalds committed
425
426
427
428
429
430
431
		}
	}

	mcast->backoff *= 2;
	if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
		mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;

432
433
	/* Clear the busy flag so we try again */
	status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
434

435
	mutex_lock(&mcast_mutex);
436
	spin_lock_irq(&priv->lock);
437
438
439
	if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
		queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
				   mcast->backoff * HZ);
440
	spin_unlock_irq(&priv->lock);
441
	mutex_unlock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
442

443
	return status;
Linus Torvalds's avatar
Linus Torvalds committed
444
445
446
447
448
449
450
451
452
453
454
455
}

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;

Harvey Harrison's avatar
Harvey Harrison committed
456
	ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
457
458
459

	rec.mgid     = mcast->mcmember.mgid;
	rec.port_gid = priv->local_gid;
460
	rec.pkey     = cpu_to_be16(priv->pkey);
Linus Torvalds's avatar
Linus Torvalds committed
461
462
463
464
465
466
467
468
469

	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 |=
470
471
472
473
474
475
476
477
478
			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;
Linus Torvalds's avatar
Linus Torvalds committed
479
480

		rec.qkey	  = priv->broadcast->mcmember.qkey;
481
482
483
484
485
		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;
Linus Torvalds's avatar
Linus Torvalds committed
486
487
		rec.sl		  = priv->broadcast->mcmember.sl;
		rec.flow_label	  = priv->broadcast->mcmember.flow_label;
488
		rec.hop_limit	  = priv->broadcast->mcmember.hop_limit;
Linus Torvalds's avatar
Linus Torvalds committed
489
490
	}

491
492
493
494
495
496
497
498
	set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
	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);
		ret = PTR_ERR(mcast->mc);
		ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
Linus Torvalds's avatar
Linus Torvalds committed
499
500
501
502
503

		mcast->backoff *= 2;
		if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
			mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;

504
		mutex_lock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
505
506
507
		if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
			queue_delayed_work(ipoib_workqueue,
					   &priv->mcast_task,
508
					   mcast->backoff * HZ);
509
		mutex_unlock(&mcast_mutex);
510
	}
Linus Torvalds's avatar
Linus Torvalds committed
511
512
}

David Howells's avatar
David Howells committed
513
void ipoib_mcast_join_task(struct work_struct *work)
Linus Torvalds's avatar
Linus Torvalds committed
514
{
David Howells's avatar
David Howells committed
515
516
517
	struct ipoib_dev_priv *priv =
		container_of(work, struct ipoib_dev_priv, mcast_task.work);
	struct net_device *dev = priv->dev;
Linus Torvalds's avatar
Linus Torvalds committed
518
519
520
521
522

	if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
		return;

	if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid))
523
		ipoib_warn(priv, "ib_query_gid() failed\n");
Linus Torvalds's avatar
Linus Torvalds committed
524
525
526
527
528
529
	else
		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));

	{
		struct ib_port_attr attr;

530
531
532
		if (!ib_query_port(priv->ca, priv->port, &attr))
			priv->local_lid = attr.lid;
		else
533
			ipoib_warn(priv, "ib_query_port failed\n");
Linus Torvalds's avatar
Linus Torvalds committed
534
535
536
	}

	if (!priv->broadcast) {
537
538
		struct ipoib_mcast *broadcast;

539
540
541
		if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
			return;

542
543
		broadcast = ipoib_mcast_alloc(dev, 1);
		if (!broadcast) {
Linus Torvalds's avatar
Linus Torvalds committed
544
			ipoib_warn(priv, "failed to allocate broadcast group\n");
545
			mutex_lock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
546
547
548
			if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
				queue_delayed_work(ipoib_workqueue,
						   &priv->mcast_task, HZ);
549
			mutex_unlock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
550
551
552
			return;
		}

553
554
		spin_lock_irq(&priv->lock);
		memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
Linus Torvalds's avatar
Linus Torvalds committed
555
		       sizeof (union ib_gid));
556
		priv->broadcast = broadcast;
Linus Torvalds's avatar
Linus Torvalds committed
557
558
559
560
561
562

		__ipoib_mcast_add(dev, priv->broadcast);
		spin_unlock_irq(&priv->lock);
	}

	if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
563
564
		if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
			ipoib_mcast_join(dev, priv->broadcast, 0);
Linus Torvalds's avatar
Linus Torvalds committed
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
		return;
	}

	while (1) {
		struct ipoib_mcast *mcast = NULL;

		spin_lock_irq(&priv->lock);
		list_for_each_entry(mcast, &priv->multicast_list, list) {
			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)) {
				/* Found the next unjoined group */
				break;
			}
		}
		spin_unlock_irq(&priv->lock);

		if (&mcast->list == &priv->multicast_list) {
			/* All done */
			break;
		}

		ipoib_mcast_join(dev, mcast, 1);
		return;
	}

591
	priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
592

593
594
	if (!ipoib_cm_admin_enabled(dev)) {
		rtnl_lock();
595
		dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
596
597
		rtnl_unlock();
	}
Linus Torvalds's avatar
Linus Torvalds committed
598
599
600
601
602
603
604
605
606
607
608
609

	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");

610
	mutex_lock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
611
	if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
David Howells's avatar
David Howells committed
612
		queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);
613
	mutex_unlock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
614
615
616
617

	return 0;
}

618
int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
Linus Torvalds's avatar
Linus Torvalds committed
619
620
621
622
623
{
	struct ipoib_dev_priv *priv = netdev_priv(dev);

	ipoib_dbg_mcast(priv, "stopping multicast thread\n");

624
	mutex_lock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
625
626
	clear_bit(IPOIB_MCAST_RUN, &priv->flags);
	cancel_delayed_work(&priv->mcast_task);
627
	mutex_unlock(&mcast_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
628

629
630
	if (flush)
		flush_workqueue(ipoib_workqueue);
Linus Torvalds's avatar
Linus Torvalds committed
631
632
633
634
635
636
637
638
639

	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;

640
641
642
	if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
		ib_sa_free_multicast(mcast->mc);

643
	if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
Harvey Harrison's avatar
Harvey Harrison committed
644
		ipoib_dbg_mcast(priv, "leaving MGID %pI6\n",
645
				mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
646

647
		/* Remove ourselves from the multicast group */
648
649
		ret = ib_detach_mcast(priv->qp, &mcast->mcmember.mgid,
				      be16_to_cpu(mcast->mcmember.mlid));
650
		if (ret)
651
			ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
652
	}
Linus Torvalds's avatar
Linus Torvalds committed
653
654
655
656

	return 0;
}

657
void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
658
659
660
{
	struct ipoib_dev_priv *priv = netdev_priv(dev);
	struct ipoib_mcast *mcast;
661
	unsigned long flags;
Linus Torvalds's avatar
Linus Torvalds committed
662

663
	spin_lock_irqsave(&priv->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
664

665
	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)		||
666
667
	    !priv->broadcast					||
	    !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
668
		++dev->stats.tx_dropped;
669
670
671
672
		dev_kfree_skb_any(skb);
		goto unlock;
	}

Linus Torvalds's avatar
Linus Torvalds committed
673
674
675
	mcast = __ipoib_mcast_find(dev, mgid);
	if (!mcast) {
		/* Let's create a new send only group now */
Harvey Harrison's avatar
Harvey Harrison committed
676
		ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n",
677
				mgid);
Linus Torvalds's avatar
Linus Torvalds committed
678
679
680
681
682

		mcast = ipoib_mcast_alloc(dev, 0);
		if (!mcast) {
			ipoib_warn(priv, "unable to allocate memory for "
				   "multicast structure\n");
683
			++dev->stats.tx_dropped;
Linus Torvalds's avatar
Linus Torvalds committed
684
685
686
687
688
			dev_kfree_skb_any(skb);
			goto out;
		}

		set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
689
		memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));
Linus Torvalds's avatar
Linus Torvalds committed
690
691
692
693
694
695
696
		__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);
697
		else {
698
			++dev->stats.tx_dropped;
Linus Torvalds's avatar
Linus Torvalds committed
699
			dev_kfree_skb_any(skb);
700
		}
Linus Torvalds's avatar
Linus Torvalds committed
701

702
		if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
Linus Torvalds's avatar
Linus Torvalds committed
703
704
705
706
707
708
709
710
711
712
713
714
715
716
			ipoib_dbg_mcast(priv, "no address vector, "
					"but multicast join already started\n");
		else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
			ipoib_mcast_sendonly_join(mcast);

		/*
		 * If lookup completes between here and out:, don't
		 * want to send packet twice.
		 */
		mcast = NULL;
	}

out:
	if (mcast && mcast->ah) {
Eric Dumazet's avatar
Eric Dumazet committed
717
718
719
720
		if (skb_dst(skb)		&&
		    skb_dst(skb)->neighbour &&
		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
721
									skb->dev);
Linus Torvalds's avatar
Linus Torvalds committed
722
723
724

			if (neigh) {
				kref_get(&mcast->ah->ref);
725
				neigh->ah	= mcast->ah;
Linus Torvalds's avatar
Linus Torvalds committed
726
727
728
729
				list_add_tail(&neigh->list, &mcast->neigh_list);
			}
		}

730
		spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
731
		ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
732
		return;
Linus Torvalds's avatar
Linus Torvalds committed
733
734
	}

735
unlock:
736
	spin_unlock_irqrestore(&priv->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
737
738
739
740
741
742
}

void ipoib_mcast_dev_flush(struct net_device *dev)
{
	struct ipoib_dev_priv *priv = netdev_priv(dev);
	LIST_HEAD(remove_list);
743
	struct ipoib_mcast *mcast, *tmcast;
Linus Torvalds's avatar
Linus Torvalds committed
744
745
746
747
748
749
	unsigned long flags;

	ipoib_dbg_mcast(priv, "flushing multicast list\n");

	spin_lock_irqsave(&priv->lock, flags);

750
751
752
753
	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);
Linus Torvalds's avatar
Linus Torvalds committed
754
755
756
	}

	if (priv->broadcast) {
Roland Dreier's avatar
Roland Dreier committed
757
		rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
758
759
		list_add_tail(&priv->broadcast->list, &remove_list);
		priv->broadcast = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
760
761
762
763
764
765
766
767
768
769
	}

	spin_unlock_irqrestore(&priv->lock, flags);

	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
		ipoib_mcast_leave(dev, mcast);
		ipoib_mcast_free(mcast);
	}
}

770
771
772
773
774
775
776
777
778
779
780
781
782
783
static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen,
				     const u8 *broadcast)
{
	if (addrlen != INFINIBAND_ALEN)
		return 0;
	/* 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;
}

David Howells's avatar
David Howells committed
784
void ipoib_mcast_restart_task(struct work_struct *work)
Linus Torvalds's avatar
Linus Torvalds committed
785
{
David Howells's avatar
David Howells committed
786
787
788
	struct ipoib_dev_priv *priv =
		container_of(work, struct ipoib_dev_priv, restart_task);
	struct net_device *dev = priv->dev;
Linus Torvalds's avatar
Linus Torvalds committed
789
790
791
792
	struct dev_mc_list *mclist;
	struct ipoib_mcast *mcast, *tmcast;
	LIST_HEAD(remove_list);
	unsigned long flags;
793
	struct ib_sa_mcmember_rec rec;
Linus Torvalds's avatar
Linus Torvalds committed
794
795
796

	ipoib_dbg_mcast(priv, "restarting multicast task\n");

797
	ipoib_mcast_stop_thread(dev, 0);
Linus Torvalds's avatar
Linus Torvalds committed
798

Herbert Xu's avatar
Herbert Xu committed
799
	local_irq_save(flags);
800
	netif_addr_lock(dev);
801
	spin_lock(&priv->lock);
Linus Torvalds's avatar
Linus Torvalds committed
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816

	/*
	 * 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 */
	for (mclist = dev->mc_list; mclist; mclist = mclist->next) {
		union ib_gid mgid;

817
818
819
820
821
		if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr,
					       mclist->dmi_addrlen,
					       dev->broadcast))
			continue;

Linus Torvalds's avatar
Linus Torvalds committed
822
823
824
825
826
827
		memcpy(mgid.raw, mclist->dmi_addr + 4, sizeof mgid);

		mcast = __ipoib_mcast_find(dev, &mgid);
		if (!mcast || test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
			struct ipoib_mcast *nmcast;

828
829
830
			/* 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)) {
Harvey Harrison's avatar
Harvey Harrison committed
831
				ipoib_dbg_mcast(priv, "ignoring multicast entry for mgid %pI6\n",
832
						mgid.raw);
833
834
835
				continue;
			}

Linus Torvalds's avatar
Linus Torvalds committed
836
			/* Not found or send-only group, let's add a new entry */
Harvey Harrison's avatar
Harvey Harrison committed
837
			ipoib_dbg_mcast(priv, "adding multicast entry for mgid %pI6\n",
838
					mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
839
840
841
842
843
844
845
846
847
848
849
850
851

			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 */
852
				list_move_tail(&mcast->list, &remove_list);
Linus Torvalds's avatar
Linus Torvalds committed
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

				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)) {
Harvey Harrison's avatar
Harvey Harrison committed
871
			ipoib_dbg_mcast(priv, "deleting multicast group %pI6\n",
872
					mcast->mcmember.mgid.raw);
Linus Torvalds's avatar
Linus Torvalds committed
873
874
875
876

			rb_erase(&mcast->rb_node, &priv->multicast_tree);

			/* Move to the remove list */
877
			list_move_tail(&mcast->list, &remove_list);
Linus Torvalds's avatar
Linus Torvalds committed
878
879
		}
	}
880
881

	spin_unlock(&priv->lock);
882
	netif_addr_unlock(dev);
Herbert Xu's avatar
Herbert Xu committed
883
	local_irq_restore(flags);
Linus Torvalds's avatar
Linus Torvalds committed
884
885
886
887
888
889
890
891
892
893
894

	/* We have to cancel outside of the spinlock */
	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
		ipoib_mcast_leave(mcast->dev, mcast);
		ipoib_mcast_free(mcast);
	}

	if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
		ipoib_mcast_start_thread(dev);
}

895
896
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG

Linus Torvalds's avatar
Linus Torvalds committed
897
898
899
900
901
902
903
904
905
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;
906
	memset(iter->mgid.raw, 0, 16);
Linus Torvalds's avatar
Linus Torvalds committed
907
908

	if (ipoib_mcast_iter_next(iter)) {
909
		kfree(iter);
Linus Torvalds's avatar
Linus Torvalds committed
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
		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;
}
964
965

#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */