[openib-general] [PATCH] Better IPoIB multicast handling

Roland Dreier roland at topspin.com
Fri Oct 22 11:15:31 PDT 2004


This patch improves how IPoIB handles multicasts.  It should fix the
crash that Andras saw; unfortunately I don't think it will help with
Tom's crash (although I don't understand that crash so it might fix
it).  Unfortunately it still probably doesn't work with some SMs.

Also, with this patch, multicast seems to work (tested only with
"ping -I ib0 224.0.0.1") although the way I handle multicast
neighbours needs cleanup.

Any test feedback is appreciated...

Thanks,
  Roland

Index: infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- infiniband/ulp/ipoib/ipoib_main.c	(revision 952)
+++ infiniband/ulp/ipoib/ipoib_main.c	(working copy)
@@ -435,6 +435,16 @@
 	struct ipoib_path *path;
 
 	if (skb->dst && skb->dst->neighbour) {
+		if (unlikely(skb->dst->neighbour->ha[4] == 0xff)) {
+			/* Add in the P_Key */
+			skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
+			skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
+			ipoib_mcast_send(dev,
+					 (union ib_gid *) (skb->dst->neighbour->ha + 4),
+					 skb);
+			return 0;
+		}
+
 		if (unlikely(!IPOIB_PATH(skb->dst->neighbour)))
 			return path_rec_start(skb, dev);
 
@@ -455,26 +465,13 @@
 		skb_pull(skb, sizeof *phdr);
 
 		if (phdr->hwaddr[4] == 0xff) {
-			/* multicast/broadcast GID */
-			if (!memcmp(phdr->hwaddr, dev->broadcast, IPOIB_HW_ADDR_LEN))
-				ipoib_mcast_send(dev, priv->broadcast, skb);
-			else {
-				ipoib_dbg(priv, "Dropping (no %s): type %04x, QPN %06x "
-					  IPOIB_GID_FMT "\n",
-					  skb->dst ? "neigh" : "dst",
-					  be16_to_cpup((u16 *) skb->data),
-					  be32_to_cpup((u32 *) phdr->hwaddr),
-					  phdr->hwaddr[ 4], phdr->hwaddr[ 5],
-					  phdr->hwaddr[ 6], phdr->hwaddr[ 7],
-					  phdr->hwaddr[ 8], phdr->hwaddr[ 9],
-					  phdr->hwaddr[10], phdr->hwaddr[11],
-					  phdr->hwaddr[12], phdr->hwaddr[13],
-					  phdr->hwaddr[14], phdr->hwaddr[15],
-					  phdr->hwaddr[16], phdr->hwaddr[17],
-					  phdr->hwaddr[18], phdr->hwaddr[19]);
-				goto err;
-			}
-		} else {
+			/* Add in the P_Key */
+			phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+			phdr->hwaddr[9] = priv->pkey & 0xff;
+
+			ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
+		}
+		else {
 			/* unicast GID -- ARP reply?? */
 
 			/*
Index: infiniband/ulp/ipoib/ipoib.h
===================================================================
--- infiniband/ulp/ipoib/ipoib.h	(revision 1031)
+++ infiniband/ulp/ipoib/ipoib.h	(working copy)
@@ -57,6 +57,7 @@
 	IPOIB_NUM_WC 		  = 4,
 
 	IPOIB_MAX_PATH_REC_QUEUE  = 3,
+	IPOIB_MAX_MCAST_QUEUE     = 3,
 
 	IPOIB_FLAG_TX_FULL 	  = 0,
 	IPOIB_FLAG_OPER_UP 	  = 1,
@@ -191,10 +192,7 @@
 
 void ipoib_mcast_join_task(void *dev_ptr);
 void ipoib_mcast_put(struct ipoib_mcast *mcast);
-int ipoib_mcast_lookup(struct net_device *dev, union ib_gid *mgid,
-		       struct ipoib_mcast **mcast);
-int ipoib_mcast_queue_packet(struct ipoib_mcast *mcast, struct sk_buff *skb);
-void ipoib_mcast_send(struct net_device *dev, struct ipoib_mcast *mcast,
+void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
 		      struct sk_buff *skb);
 
 void ipoib_mcast_restart_task(void *dev_ptr);
Index: infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- infiniband/ulp/ipoib/ipoib_multicast.c	(revision 952)
+++ infiniband/ulp/ipoib/ipoib_multicast.c	(working copy)
@@ -618,15 +618,13 @@
 }
 
 /* =============================================================== */
-/*..ipoib_mcast_lookup -- return reference to multicast            */
-int ipoib_mcast_lookup(struct net_device *dev,
-		       union ib_gid *mgid,
-		       struct ipoib_mcast **mmcast)
+/*..ipoib_mcast_send -- handle sending mcast packet                */
+void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
+		      struct sk_buff *skb)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_mcast *mcast;
 	unsigned long flags;
-	int ret = 0;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	mcast = __ipoib_mcast_find(dev, mgid);
@@ -637,57 +635,41 @@
 
 		mcast = ipoib_mcast_alloc(dev, 0);
 		if (!mcast) {
-			ipoib_warn(priv, "unable to allocate memory for multicast structure\n");
-			ret = -ENOMEM;
+			ipoib_warn(priv, "unable to allocate memory for "
+				   "multicast structure\n");
+			dev_kfree_skb_any(skb);
 			goto out;
 		}
 
 		set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
-
 		mcast->mgid = *mgid;
-
 		__ipoib_mcast_add(dev, mcast);
-
 		list_add_tail(&mcast->list, &priv->multicast_list);
-
-		/* Leave references for the calling application */
 	}
 
-	if (mcast->address_handle == NULL) {
+	if (!mcast->address_handle) {
 		if (mcast->tid != TS_IB_CLIENT_QUERY_TID_INVALID)
-			ipoib_dbg_mcast(priv, "no address vector, but multicast join already started\n");
+			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);
 
-		ret = -EAGAIN;
+		if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
+			skb_queue_tail(&mcast->pkt_queue, skb);
+		else
+			dev_kfree_skb_any(skb);
 	}
 
-	*mmcast = mcast;
-
 out:
 	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return ret;
+	if (mcast) {
+		if (mcast->address_handle)
+			ipoib_send(dev, skb, mcast->address_handle, IB_MULTICAST_QPN);
+		ipoib_mcast_put(mcast);
+	}
 }
 
 /* =============================================================== */
-/*..ipoib_mcast_send -- send skb to multicast group                */
-void ipoib_mcast_send(struct net_device *dev, struct ipoib_mcast *mcast,
-		      struct sk_buff *skb)
-{
-	ipoib_send(dev, skb, mcast->address_handle, IB_MULTICAST_QPN);
-}
-
-/* =============================================================== */
-/*..ipoib_mcast_queue_packet -- queue skb pending join             */
-int ipoib_mcast_queue_packet(struct ipoib_mcast *mcast, struct sk_buff *skb)
-{
-	skb_queue_tail(&mcast->pkt_queue, skb);
-
-	return 0;
-}
-
-/* =============================================================== */
 /*..ipoib_mcast_dev_flush -- flush joins and address vectors       */
 void ipoib_mcast_dev_flush(struct net_device *dev)
 {



More information about the general mailing list