From 73af3711c7028286136bb7e9422b19f5a016626d Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 30 Nov 2022 15:12:50 +0200 Subject: [PATCH] net/mlx5: Lag, set different uplink vport metadata in multiport eswitch mode In a follow-up commit multiport eswitch mode will use a shared fdb. In shared fdb there is a single eswitch fdb and traffic could come from any port. to distinguish between the ports set a different metadata per uplink port. Signed-off-by: Roi Dayan Reviewed-by: Maor Dickman Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 35 ++++++++++ .../net/ethernet/mellanox/mlx5/core/en_rep.h | 2 + .../ethernet/mellanox/mlx5/core/lag/mpesw.c | 67 ++++++++++++++++++- .../ethernet/mellanox/mlx5/core/lag/mpesw.h | 1 + include/linux/mlx5/driver.h | 1 + 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 8d29310c7e48..9b9203443085 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1007,8 +1007,23 @@ static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv) priv->rx_res = NULL; } +static void mlx5e_rep_mpesw_work(struct work_struct *work) +{ + struct mlx5_rep_uplink_priv *uplink_priv = + container_of(work, struct mlx5_rep_uplink_priv, + mpesw_work); + struct mlx5e_rep_priv *rpriv = + container_of(uplink_priv, struct mlx5e_rep_priv, + uplink_priv); + struct mlx5e_priv *priv = netdev_priv(rpriv->netdev); + + rep_vport_rx_rule_destroy(priv); + mlx5e_create_rep_vport_rx_rule(priv); +} + static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv) { + struct mlx5e_rep_priv *rpriv = priv->ppriv; int err; mlx5e_create_q_counters(priv); @@ -1018,12 +1033,17 @@ static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv) mlx5e_tc_int_port_init_rep_rx(priv); + INIT_WORK(&rpriv->uplink_priv.mpesw_work, mlx5e_rep_mpesw_work); + out: return err; } static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv) { + struct mlx5e_rep_priv *rpriv = priv->ppriv; + + cancel_work_sync(&rpriv->uplink_priv.mpesw_work); mlx5e_tc_int_port_cleanup_rep_rx(priv); mlx5e_cleanup_rep_rx(priv); mlx5e_destroy_q_counters(priv); @@ -1132,6 +1152,19 @@ static int mlx5e_update_rep_rx(struct mlx5e_priv *priv) return 0; } +static int mlx5e_rep_event_mpesw(struct mlx5e_priv *priv) +{ + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_eswitch_rep *rep = rpriv->rep; + + if (rep->vport != MLX5_VPORT_UPLINK) + return NOTIFY_DONE; + + queue_work(priv->wq, &rpriv->uplink_priv.mpesw_work); + + return NOTIFY_OK; +} + static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data) { struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb); @@ -1153,6 +1186,8 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event if (event == MLX5_DEV_EVENT_PORT_AFFINITY) return mlx5e_rep_tc_event_port_affinity(priv); + else if (event == MLX5_DEV_EVENT_MULTIPORT_ESW) + return mlx5e_rep_event_mpesw(priv); return NOTIFY_DONE; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 0abe3313c673..dcfad0bf0f45 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -103,6 +103,8 @@ struct mlx5_rep_uplink_priv { /* tc action stats */ struct mlx5e_tc_act_stats_handle *action_stats_handle; + + struct work_struct mpesw_work; }; struct mlx5e_rep_priv { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c index dd3cb9aa06fd..2f7f2af312d7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c @@ -5,8 +5,66 @@ #include #include "lag/lag.h" #include "eswitch.h" +#include "esw/acl/ofld.h" #include "lib/mlx5.h" +static void mlx5_mpesw_metadata_cleanup(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *dev; + struct mlx5_eswitch *esw; + u32 pf_metadata; + int i; + + for (i = 0; i < ldev->ports; i++) { + dev = ldev->pf[i].dev; + esw = dev->priv.eswitch; + pf_metadata = ldev->lag_mpesw.pf_metadata[i]; + if (!pf_metadata) + continue; + mlx5_esw_acl_ingress_vport_metadata_update(esw, MLX5_VPORT_UPLINK, 0); + mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_MULTIPORT_ESW, + (void *)0); + mlx5_esw_match_metadata_free(esw, pf_metadata); + ldev->lag_mpesw.pf_metadata[i] = 0; + } +} + +static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *dev; + struct mlx5_eswitch *esw; + u32 pf_metadata; + int i, err; + + for (i = 0; i < ldev->ports; i++) { + dev = ldev->pf[i].dev; + esw = dev->priv.eswitch; + pf_metadata = mlx5_esw_match_metadata_alloc(esw); + if (!pf_metadata) { + err = -ENOSPC; + goto err_metadata; + } + + ldev->lag_mpesw.pf_metadata[i] = pf_metadata; + err = mlx5_esw_acl_ingress_vport_metadata_update(esw, MLX5_VPORT_UPLINK, + pf_metadata); + if (err) + goto err_metadata; + } + + for (i = 0; i < ldev->ports; i++) { + dev = ldev->pf[i].dev; + mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_MULTIPORT_ESW, + (void *)0); + } + + return 0; + +err_metadata: + mlx5_mpesw_metadata_cleanup(ldev); + return err; +} + static int enable_mpesw(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev; @@ -21,6 +79,10 @@ static int enable_mpesw(struct mlx5_lag *ldev) !mlx5_lag_check_prereq(ldev)) return -EOPNOTSUPP; + err = mlx5_mpesw_metadata_set(ldev); + if (err) + return err; + err = mlx5_activate_lag(ldev, NULL, MLX5_LAG_MODE_MPESW, false); if (err) { mlx5_core_warn(dev, "Failed to create LAG in MPESW mode (%d)\n", err); @@ -30,13 +92,16 @@ static int enable_mpesw(struct mlx5_lag *ldev) return 0; out_err: + mlx5_mpesw_metadata_cleanup(ldev); return err; } static void disable_mpesw(struct mlx5_lag *ldev) { - if (ldev->mode == MLX5_LAG_MODE_MPESW) + if (ldev->mode == MLX5_LAG_MODE_MPESW) { + mlx5_mpesw_metadata_cleanup(ldev); mlx5_disable_lag(ldev); + } } static void mlx5_mpesw_work(struct work_struct *work) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h index d857ea988bf2..02520f27a033 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h @@ -9,6 +9,7 @@ struct lag_mpesw { struct work_struct mpesw_work; + u32 pf_metadata[MLX5_MAX_PORTS]; }; enum mpesw_op { diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index ecd3b5448fe9..a4bb5842a948 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -217,6 +217,7 @@ struct mlx5_rsc_debug { enum mlx5_dev_event { MLX5_DEV_EVENT_SYS_ERROR = 128, /* 0 - 127 are FW events */ MLX5_DEV_EVENT_PORT_AFFINITY = 129, + MLX5_DEV_EVENT_MULTIPORT_ESW = 130, }; enum mlx5_port_status {