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

Roland Dreier
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 openib-general mailing list