summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@mellanox.co.il>2006-11-16 10:59:12 +0200
committerRoland Dreier <rolandd@cisco.com>2006-11-16 13:56:45 -0800
commit073ae841d6a5098f7c6e17fc1f329350d950d1ce (patch)
treeb74472c7e5bd8ab009e111807e13408b87770324
parent0f66c08e9611b9a63f2f2fd5af0d12e486c4a02e (diff)
downloadop-kernel-dev-073ae841d6a5098f7c6e17fc1f329350d950d1ce.zip
op-kernel-dev-073ae841d6a5098f7c6e17fc1f329350d950d1ce.tar.gz
IPoIB: Clear high octet in QP number
IPoIB assumes that high (reserved) octet in the hardware address is 0, and copies it into the QPN. This violates RFC 4391 (which requires that the high 8 bits are ignored on receive), and will result in an invalid QPN being used when interoperating with IPoIB connected mode. Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 1eaf00e..85522da 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -49,6 +49,8 @@
#include <net/dst.h>
+#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff)
+
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
MODULE_LICENSE("Dual BSD/GPL");
@@ -520,8 +522,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
sizeof(union ib_gid));
- ipoib_send(dev, skb, path->ah,
- be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
} else {
neigh->ah = NULL;
__skb_queue_tail(&neigh->queue, skb);
@@ -599,8 +600,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
ipoib_dbg(priv, "Send unicast ARP to %04x\n",
be16_to_cpu(path->pathrec.dlid));
- ipoib_send(dev, skb, path->ah,
- be32_to_cpup((__be32 *) phdr->hwaddr));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
} else if ((path->query || !path_rec_start(dev, path)) &&
skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
/* put pseudoheader back on for next time */
@@ -661,8 +661,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
goto out;
}
- ipoib_send(dev, skb, neigh->ah,
- be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
+ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
goto out;
}
@@ -694,7 +693,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
IPOIB_GID_FMT "\n",
skb->dst ? "neigh" : "dst",
be16_to_cpup((__be16 *) skb->data),
- be32_to_cpup((__be32 *) phdr->hwaddr),
+ IPOIB_QPN(phdr->hwaddr),
IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
dev_kfree_skb_any(skb);
++priv->stats.tx_dropped;
@@ -777,7 +776,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
ipoib_dbg(priv,
"neigh_destructor for %06x " IPOIB_GID_FMT "\n",
- be32_to_cpup((__be32 *) n->ha),
+ IPOIB_QPN(n->ha),
IPOIB_GID_RAW_ARG(n->ha + 4));
spin_lock_irqsave(&priv->lock, flags);
OpenPOWER on IntegriCloud