IPoIB: Clear high octet in QP number
Michael S. Tsirkin [Thu, 16 Nov 2006 08:59:12 +0000 (10:59 +0200)]
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>

drivers/infiniband/ulp/ipoib/ipoib_main.c

index 1eaf00e..85522da 100644 (file)
@@ -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);