Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b36f170b authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Roland Dreier
Browse files

IPoIB: Lock accesses to multicast packet queues



Avoid corrupting mcast->pkt_queue by serializing access with
priv->tx_lock.  Also, update dropped packet statistics to count
multicast packets removed from pkt_queue as dropped.

Signed-off-by: default avatarMichael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 0f47ae0b
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
	struct ipoib_dev_priv *priv = netdev_priv(dev);
	struct ipoib_neigh *neigh, *tmp;
	unsigned long flags;
	int tx_dropped = 0;

	ipoib_dbg_mcast(netdev_priv(dev),
			"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -123,8 +124,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
	if (mcast->ah)
		ipoib_put_ah(mcast->ah);

	while (!skb_queue_empty(&mcast->pkt_queue))
	while (!skb_queue_empty(&mcast->pkt_queue)) {
		++tx_dropped;
		dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
	}

	spin_lock_irqsave(&priv->tx_lock, flags);
	priv->stats.tx_dropped += tx_dropped;
	spin_unlock_irqrestore(&priv->tx_lock, flags);

	kfree(mcast);
}
@@ -276,8 +283,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
	}

	/* actually send any queued packets */
	spin_lock_irq(&priv->tx_lock);
	while (!skb_queue_empty(&mcast->pkt_queue)) {
		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
		spin_unlock_irq(&priv->tx_lock);

		skb->dev = dev;

@@ -288,7 +297,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,

		if (dev_queue_xmit(skb))
			ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
		spin_lock_irq(&priv->tx_lock);
	}
	spin_unlock_irq(&priv->tx_lock);

	return 0;
}
@@ -300,6 +311,7 @@ ipoib_mcast_sendonly_join_complete(int status,
{
	struct ipoib_mcast *mcast = mcast_ptr;
	struct net_device *dev = mcast->dev;
	struct ipoib_dev_priv *priv = netdev_priv(dev);

	if (!status)
		ipoib_mcast_join_finish(mcast, mcmember);
@@ -310,8 +322,12 @@ ipoib_mcast_sendonly_join_complete(int status,
					IPOIB_GID_ARG(mcast->mcmember.mgid), status);

		/* Flush out any queued packets */
		while (!skb_queue_empty(&mcast->pkt_queue))
		spin_lock_irq(&priv->tx_lock);
		while (!skb_queue_empty(&mcast->pkt_queue)) {
			++priv->stats.tx_dropped;
			dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
		}
		spin_unlock_irq(&priv->tx_lock);

		/* Clear the busy flag so we try again */
		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
@@ -687,6 +703,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
		if (!mcast) {
			ipoib_warn(priv, "unable to allocate memory for "
				   "multicast structure\n");
			++priv->stats.tx_dropped;
			dev_kfree_skb_any(skb);
			goto out;
		}
@@ -700,8 +717,10 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
	if (!mcast->ah) {
		if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
			skb_queue_tail(&mcast->pkt_queue, skb);
		else
		else {
			++priv->stats.tx_dropped;
			dev_kfree_skb_any(skb);
		}

		if (mcast->query)
			ipoib_dbg_mcast(priv, "no address vector, "