[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