[ofa-general] [PATCH] ipoib: Fix loss of connectivity after bonding failover on both sides

Yossi Etigin yosefe at Voltaire.COM
Fri Oct 31 10:46:52 PDT 2008


Fix bonding failover in the case poth peers have failover and gratuitous arp
is lost.
In that case, ipoib sender side will create ipoib_neigh and issue a path request
with the old gid first. When skb->dst->neighbour->ha changes due to arp refresh,
ipoib_neigh will not be added to the path->list of the path of the new mgid,
because ipoib_neigh already exists. It will not have an ah either, because of
sender-side failover. Therefore, it will not get an ah when the path is resolved.

The solution here is to compare gids even if neigh->ah is invalid, also
initiallize neigh->dgid.raw to have value to compare with.

Signed-off-by: Yossi Etigin <yosefe at voltaire.com>
---

Fix bugzilla 1286.

 drivers/infiniband/ulp/ipoib/ipoib_main.c |   40 +++++++++++++++---------------
 1 file changed, 21 insertions(+), 19 deletions(-)

Index: b/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c	2008-10-31 19:17:42.000000000 +0200
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c	2008-10-31 19:24:52.000000000 +0200
@@ -584,6 +584,8 @@ static void neigh_add_path(struct sk_buf
 			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
 	} else {
 		neigh->ah  = NULL;
+		memcpy(&neigh->dgid.raw, skb->dst->neighbour->ha + 4,
+		       sizeof(union ib_gid));
 
 		if (!path->query && path_rec_start(dev, path))
 			goto err_list;
@@ -687,26 +689,26 @@ static int ipoib_start_xmit(struct sk_bu
 
 		neigh = *to_ipoib_neigh(skb->dst->neighbour);
 
-		if (neigh->ah)
-			if (unlikely((memcmp(&neigh->dgid.raw,
-					    skb->dst->neighbour->ha + 4,
-					    sizeof(union ib_gid))) ||
-					 (neigh->dev != dev))) {
-				spin_lock_irqsave(&priv->lock, flags);
-				/*
-				 * It's safe to call ipoib_put_ah() inside
-				 * priv->lock here, because we know that
-				 * path->ah will always hold one more reference,
-				 * so ipoib_put_ah() will never do more than
-				 * decrement the ref count.
-				 */
+		if (unlikely((memcmp(&neigh->dgid.raw,
+		                     skb->dst->neighbour->ha + 4,
+		                     sizeof(union ib_gid))) ||
+		             (neigh->dev != dev))) {
+			spin_lock_irqsave(&priv->lock, flags);
+			/*
+			 * It's safe to call ipoib_put_ah() inside
+			 * priv->lock here, because we know that
+			 * path->ah will always hold one more reference,
+			 * so ipoib_put_ah() will never do more than
+			 * decrement the ref count.
+			 */
+			if (neigh->ah)
 				ipoib_put_ah(neigh->ah);
-				list_del(&neigh->list);
-				ipoib_neigh_free(dev, neigh);
-				spin_unlock_irqrestore(&priv->lock, flags);
-				ipoib_path_lookup(skb, dev);
-				return NETDEV_TX_OK;
-			}
+			list_del(&neigh->list);
+			ipoib_neigh_free(dev, neigh);
+			spin_unlock_irqrestore(&priv->lock, flags);
+			ipoib_path_lookup(skb, dev);
+			return NETDEV_TX_OK;
+		}
 
 		if (ipoib_cm_get(neigh)) {
 			if (ipoib_cm_up(neigh)) {
-- 
--Yossi



More information about the general mailing list