[ofa-general] Re: [RFC] [PATCH v3] IB/ipoib: Add bonding support to IPoIB

Michael S. Tsirkin mst at dev.mellanox.co.il
Mon Mar 12 08:03:55 PDT 2007


> Quoting Moni Shoua <monis at voltaire.com>:
> To fix it, this patch adds a dev field to struct ipoib_neigh which is used
> instead of the struct neighbour dev one.
> 
> Signed-off-by: Moni Shoua <monis at voltaire.com>
> Signed-off-by: Or Gerlitz <ogerlitz at voltaire.com>
> ---
> 
>  ipoib.h           |    4 +++-
>  ipoib_main.c      |   26 +++++++++++++-------------
>  ipoib_multicast.c |    2 +-
>  3 files changed, 17 insertions(+), 15 deletions(-)
> Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib.h
> ===================================================================
> --- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib.h	2007-01-25 11:05:32.000000000 +0200
> +++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib.h	2007-03-04 19:32:55.000000000 +0200
> @@ -216,6 +216,7 @@ struct ipoib_neigh {
>  	struct sk_buff_head queue;
>  
>  	struct neighbour   *neighbour;
> +	struct net_device *dev;
>  
>  	struct list_head    list;
>  };
> @@ -232,7 +233,8 @@ static inline struct ipoib_neigh **to_ip
>  				     INFINIBAND_ALEN, sizeof(void *));
>  }
>  
> -struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
> +struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh,
> +				      struct net_device *dev);
>  void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh);
>  
>  extern struct workqueue_struct *ipoib_workqueue;
> Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_main.c
> ===================================================================
> --- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c	2007-01-25 11:05:32.000000000 +0200
> +++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_main.c	2007-03-04 19:32:55.000000000 +0200
> @@ -248,7 +248,6 @@ static void path_free(struct net_device 
>  	struct ipoib_neigh *neigh, *tn;
>  	struct sk_buff *skb;
>  	unsigned long flags;
> -
>  	while ((skb = __skb_dequeue(&path->queue)))
>  		dev_kfree_skb_irq(skb);
>  
> @@ -490,7 +489,7 @@ static void neigh_add_path(struct sk_buf
>  	struct ipoib_path *path;
>  	struct ipoib_neigh *neigh;
>  
> -	neigh = ipoib_neigh_alloc(skb->dst->neighbour);
> +	neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
>  	if (!neigh) {
>  		++priv->stats.tx_dropped;
>  		dev_kfree_skb_any(skb);
> @@ -769,32 +768,32 @@ static void ipoib_set_mcast_list(struct 
>  static void ipoib_neigh_destructor(struct neighbour *n)
>  {
>  	struct ipoib_neigh *neigh;
> -	struct ipoib_dev_priv *priv = netdev_priv(n->dev);
> +	struct ipoib_dev_priv *priv;
>  	unsigned long flags;
>  	struct ipoib_ah *ah = NULL;
>  
> -	ipoib_dbg(priv,
> -		  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
> -		  IPOIB_QPN(n->ha),
> -		  IPOIB_GID_RAW_ARG(n->ha + 4));
> -
> -	spin_lock_irqsave(&priv->lock, flags);
>  
>  	neigh = *to_ipoib_neigh(n);
>  	if (neigh) {
> +		priv = netdev_priv(neigh->dev);
> +		ipoib_dbg(priv,
> +			  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
> +			  IPOIB_QPN(n->ha),
> +			  IPOIB_GID_RAW_ARG(n->ha + 4));
> +
> +		spin_lock_irqsave(&priv->lock, flags);
>  		if (neigh->ah)
>  			ah = neigh->ah;
>  		list_del(&neigh->list);
>  		ipoib_neigh_free(n->dev, neigh);
> +		spin_unlock_irqrestore(&priv->lock, flags);
>  	}
> -
> -	spin_unlock_irqrestore(&priv->lock, flags);
> -
>  	if (ah)
>  		ipoib_put_ah(ah);
>  }
>  
> -struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
> +struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
> +				      struct net_device *dev)
>  {
>  	struct ipoib_neigh *neigh;
>  
> @@ -803,6 +802,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(st
>  		return NULL;
>  
>  	neigh->neighbour = neighbour;
> +	neigh->dev = dev;
>  	*to_ipoib_neigh(neighbour) = neigh;
>  	skb_queue_head_init(&neigh->queue);
>  
> Index: linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
> ===================================================================
> --- linux-2.6.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2007-01-25 11:05:32.000000000 +0200
> +++ linux-2.6/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2007-03-04 12:21:46.000000000 +0200
> @@ -774,7 +774,7 @@ out:
>  		if (skb->dst            &&
>  		    skb->dst->neighbour &&
>  		    !*to_ipoib_neigh(skb->dst->neighbour)) {
> -			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour);
> +			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
>  
>  			if (neigh) {
>  				kref_get(&mcast->ah->ref);

I'm re-reading this, and old archives.
Was the following problem addressed?

# It seems that in this design, if multiple ipoib interfaces are present, we might
# get an skb such that skb->dev will be different from the new dev field in struct
# ipoib_neigh.
# 
# ipoib_neigh ah field includes struct ib_ah *.
# This selects important parameters which depend on both packet source and
# destination interfaces.
# 
# It seems that the result will be that the packet will be sent on a wrong interface.
# Right?
# 
# I think the right thing might be to compare ipoib_neigh dev and
# skb->dev, and destroy ipoib_neigh if these do not match.
#
# However, this will affect performance negatively if this happens a lot.
# Need to understand the usage model for the bonding driver and whether
# there is some "locality" here.


-- 
MST



More information about the general mailing list