diff mbox

[for-next,4/7] net/mlx4_en: Implement mcast loopback prevention for ETH qps

Message ID 1439741133-30145-5-git-send-email-eranbe@mellanox.com (mailing list archive)
State Superseded
Headers show

Commit Message

Eran Ben Elisha Aug. 16, 2015, 4:05 p.m. UTC
From: Maor Gottlieb <maorg@mellanox.com>

Set the mcast loopback prevention bit in the QPC for ETH MLX QPs (not
RSS QPs), when the firmware supports this feature. In addition, all rx
ring QPs need to be updated in order not to enforce loopback checks.
This prevents getting packets we sent both from the network stack and
the HCA. Loopback prevention is done by comparing the counter indices of
the sent and receiving QPs. If they're equal, packets aren't
loopback-ed.

Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx4/en_main.c      | 22 ++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/en_resources.c | 25 +++++++++++++++++++++++
 drivers/net/ethernet/mellanox/mlx4/mlx4_en.h      |  3 ++-
 3 files changed, 49 insertions(+), 1 deletion(-)

Comments

Yuval Shaia Aug. 16, 2015, 7:19 p.m. UTC | #1
On Sun, Aug 16, 2015 at 07:05:30PM +0300, Eran Ben Elisha wrote:
> From: Maor Gottlieb <maorg@mellanox.com>
> 
> Set the mcast loopback prevention bit in the QPC for ETH MLX QPs (not
> RSS QPs), when the firmware supports this feature. In addition, all rx
> ring QPs need to be updated in order not to enforce loopback checks.
> This prevents getting packets we sent both from the network stack and
> the HCA. Loopback prevention is done by comparing the counter indices of
> the sent and receiving QPs. If they're equal, packets aren't
> loopback-ed.
> 
> Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> ---
>  drivers/net/ethernet/mellanox/mlx4/en_main.c      | 22 ++++++++++++++++++++
>  drivers/net/ethernet/mellanox/mlx4/en_resources.c | 25 +++++++++++++++++++++++
>  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h      |  3 ++-
>  3 files changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
> index a946e4b..70e381a 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
> @@ -123,6 +123,28 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
>  	 */
>  	if (mlx4_is_mfunc(priv->mdev->dev) || priv->validate_loopback)
>  		priv->flags |= MLX4_EN_FLAG_ENABLE_HW_LOOPBACK;
> +
> +	mutex_lock(&priv->mdev->state_lock);
> +	if (priv->mdev->dev->caps.flags2 &
> +	    MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB &&
> +	    priv->rss_map.indir_qp.qpn) {
> +		int i;
> +		int err = 0;
> +
> +		for (i = 0; i < priv->rx_ring_num; i++) {
> +			int ret;
> +
> +			ret = mlx4_en_change_mcast_lb(priv,
> +						      &priv->rss_map.qps[i],
> +						      !!(features &
> +							 NETIF_F_LOOPBACK));
If "feature" is not changing inside the loop can we take it out just for
the code to look more readable?
> +			if (!err)
> +				err = ret;
> +		}
> +		if (err)
> +			mlx4_warn(priv->mdev, "failed to change mcast loopback\n");
> +	}
> +	mutex_unlock(&priv->mdev->state_lock);
>  }
>  
>  static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
> diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> index e482fa1b..12aab5a 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> @@ -69,6 +69,15 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
>  	context->pri_path.counter_index = priv->counter_index;
>  	context->cqn_send = cpu_to_be32(cqn);
>  	context->cqn_recv = cpu_to_be32(cqn);
> +	if (!rss &&
> +	    (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
> +	    context->pri_path.counter_index !=
> +			    MLX4_SINK_COUNTER_INDEX(mdev->dev)) {
> +		/* disable multicast loopback to qp with same counter */
> +		if (!(dev->features & NETIF_F_LOOPBACK))
> +			context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
> +		context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
> +	}
>  	context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
>  	if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
>  		context->param3 |= cpu_to_be32(1 << 30);
> @@ -80,6 +89,22 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
>  	}
>  }
>  
> +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
> +			    int loopback)
> +{
> +	int ret;
> +	struct mlx4_update_qp_params qp_params;
> +
> +	memset(&qp_params, 0, sizeof(qp_params));
> +	if (!loopback)
> +		qp_params.flags = MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB;
> +
> +	ret = mlx4_update_qp(priv->mdev->dev, qp->qpn,
> +			     MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB,
> +			     &qp_params);
> +
> +	return ret;
> +}
>  
>  int mlx4_en_map_buffer(struct mlx4_buf *buf)
>  {
> diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> index 666d166..7db86d4 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> @@ -797,7 +797,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
>  void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
>  int mlx4_en_map_buffer(struct mlx4_buf *buf);
>  void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
> -
> +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
> +			    int loopback);
>  void mlx4_en_calc_rx_buf(struct net_device *dev);
>  int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
>  void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
> -- 
> 1.8.3.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
eran ben elisha Aug. 17, 2015, 10:21 a.m. UTC | #2
On Sun, Aug 16, 2015 at 10:19 PM, Yuval Shaia <yuval.shaia@oracle.com> wrote:
>
> On Sun, Aug 16, 2015 at 07:05:30PM +0300, Eran Ben Elisha wrote:
> > From: Maor Gottlieb <maorg@mellanox.com>
> >
> > Set the mcast loopback prevention bit in the QPC for ETH MLX QPs (not
> > RSS QPs), when the firmware supports this feature. In addition, all rx
> > ring QPs need to be updated in order not to enforce loopback checks.
> > This prevents getting packets we sent both from the network stack and
> > the HCA. Loopback prevention is done by comparing the counter indices of
> > the sent and receiving QPs. If they're equal, packets aren't
> > loopback-ed.
> >
> > Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
> > Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> > ---
> >  drivers/net/ethernet/mellanox/mlx4/en_main.c      | 22 ++++++++++++++++++++
> >  drivers/net/ethernet/mellanox/mlx4/en_resources.c | 25 +++++++++++++++++++++++
> >  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h      |  3 ++-
> >  3 files changed, 49 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
> > index a946e4b..70e381a 100644
> > --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
> > +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
> > @@ -123,6 +123,28 @@ void mlx4_en_update_loopback_state(struct net_device *dev,
> >        */
> >       if (mlx4_is_mfunc(priv->mdev->dev) || priv->validate_loopback)
> >               priv->flags |= MLX4_EN_FLAG_ENABLE_HW_LOOPBACK;
> > +
> > +     mutex_lock(&priv->mdev->state_lock);
> > +     if (priv->mdev->dev->caps.flags2 &
> > +         MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB &&
> > +         priv->rss_map.indir_qp.qpn) {
> > +             int i;
> > +             int err = 0;
> > +
> > +             for (i = 0; i < priv->rx_ring_num; i++) {
> > +                     int ret;
> > +
> > +                     ret = mlx4_en_change_mcast_lb(priv,
> > +                                                   &priv->rss_map.qps[i],
> > +                                                   !!(features &
> > +                                                      NETIF_F_LOOPBACK));
> If "feature" is not changing inside the loop can we take it out just for
> the code to look more readable?

Thanks, I will change it in V1.

>
> > +                     if (!err)
> > +                             err = ret;
> > +             }
> > +             if (err)
> > +                     mlx4_warn(priv->mdev, "failed to change mcast loopback\n");
> > +     }
> > +     mutex_unlock(&priv->mdev->state_lock);
> >  }
> >
> >  static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
> > diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> > index e482fa1b..12aab5a 100644
> > --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> > +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
> > @@ -69,6 +69,15 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
> >       context->pri_path.counter_index = priv->counter_index;
> >       context->cqn_send = cpu_to_be32(cqn);
> >       context->cqn_recv = cpu_to_be32(cqn);
> > +     if (!rss &&
> > +         (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
> > +         context->pri_path.counter_index !=
> > +                         MLX4_SINK_COUNTER_INDEX(mdev->dev)) {
> > +             /* disable multicast loopback to qp with same counter */
> > +             if (!(dev->features & NETIF_F_LOOPBACK))
> > +                     context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
> > +             context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
> > +     }
> >       context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
> >       if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
> >               context->param3 |= cpu_to_be32(1 << 30);
> > @@ -80,6 +89,22 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
> >       }
> >  }
> >
> > +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
> > +                         int loopback)
> > +{
> > +     int ret;
> > +     struct mlx4_update_qp_params qp_params;
> > +
> > +     memset(&qp_params, 0, sizeof(qp_params));
> > +     if (!loopback)
> > +             qp_params.flags = MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB;
> > +
> > +     ret = mlx4_update_qp(priv->mdev->dev, qp->qpn,
> > +                          MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB,
> > +                          &qp_params);
> > +
> > +     return ret;
> > +}
> >
> >  int mlx4_en_map_buffer(struct mlx4_buf *buf)
> >  {
> > diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> > index 666d166..7db86d4 100644
> > --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> > +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
> > @@ -797,7 +797,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
> >  void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
> >  int mlx4_en_map_buffer(struct mlx4_buf *buf);
> >  void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
> > -
> > +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
> > +                         int loopback);
> >  void mlx4_en_calc_rx_buf(struct net_device *dev);
> >  int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
> >  void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
> > --
> > 1.8.3.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a946e4b..70e381a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -123,6 +123,28 @@  void mlx4_en_update_loopback_state(struct net_device *dev,
 	 */
 	if (mlx4_is_mfunc(priv->mdev->dev) || priv->validate_loopback)
 		priv->flags |= MLX4_EN_FLAG_ENABLE_HW_LOOPBACK;
+
+	mutex_lock(&priv->mdev->state_lock);
+	if (priv->mdev->dev->caps.flags2 &
+	    MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB &&
+	    priv->rss_map.indir_qp.qpn) {
+		int i;
+		int err = 0;
+
+		for (i = 0; i < priv->rx_ring_num; i++) {
+			int ret;
+
+			ret = mlx4_en_change_mcast_lb(priv,
+						      &priv->rss_map.qps[i],
+						      !!(features &
+							 NETIF_F_LOOPBACK));
+			if (!err)
+				err = ret;
+		}
+		if (err)
+			mlx4_warn(priv->mdev, "failed to change mcast loopback\n");
+	}
+	mutex_unlock(&priv->mdev->state_lock);
 }
 
 static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
index e482fa1b..12aab5a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c
@@ -69,6 +69,15 @@  void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 	context->pri_path.counter_index = priv->counter_index;
 	context->cqn_send = cpu_to_be32(cqn);
 	context->cqn_recv = cpu_to_be32(cqn);
+	if (!rss &&
+	    (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
+	    context->pri_path.counter_index !=
+			    MLX4_SINK_COUNTER_INDEX(mdev->dev)) {
+		/* disable multicast loopback to qp with same counter */
+		if (!(dev->features & NETIF_F_LOOPBACK))
+			context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
+		context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+	}
 	context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
 	if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX))
 		context->param3 |= cpu_to_be32(1 << 30);
@@ -80,6 +89,22 @@  void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 	}
 }
 
+int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
+			    int loopback)
+{
+	int ret;
+	struct mlx4_update_qp_params qp_params;
+
+	memset(&qp_params, 0, sizeof(qp_params));
+	if (!loopback)
+		qp_params.flags = MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB;
+
+	ret = mlx4_update_qp(priv->mdev->dev, qp->qpn,
+			     MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB,
+			     &qp_params);
+
+	return ret;
+}
 
 int mlx4_en_map_buffer(struct mlx4_buf *buf)
 {
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 666d166..7db86d4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -797,7 +797,8 @@  void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
 void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
 int mlx4_en_map_buffer(struct mlx4_buf *buf);
 void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
-
+int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp,
+			    int loopback);
 void mlx4_en_calc_rx_buf(struct net_device *dev);
 int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
 void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);